Python and its Functions

Shrayas (@shrayasr)


Note: Won't spend too much time on the body of the functions unless required


Defining functions

def

In [1]:
def foobar():
    print "Foobar"
    
foobar()
Foobar

Passing Arguments to functions

In [2]:
def say_hello(name, language):

    language_responses = {
        "ENGLISH": "Hello, ",
        "JAPANESE": "Konichiwa, ",
    }

    # Clean the input
    language = language.strip().upper()
    hello_str = language_responses.get(language)

    if hello_str:
        return hello_str + name
    else:
        return "Language not supported"

Positional arguments

Arguments passed one after another

In [3]:
say_hello("Chennaipy", "English")
Out[3]:
'Hello, Chennaipy'
In [4]:
say_hello("English", "Chennaipy")
Out[4]:
'Language not supported'

Which of course means, the order in which they are passed, matters


Keyword Arguments

Arguments passed into the function with a keyword

In [5]:
say_hello(name="Chennaipy", language="Japanese")
Out[5]:
'Konichiwa, Chennaipy'
In [6]:
say_hello(language="Japanese", name="Chennaipy")
Out[6]:
'Konichiwa, Chennaipy'

Which of course means, the order in which they are passed, doesn't matter


Variadic functions

*

Positional

In [7]:
def square(*nums):
    print type(nums)
    print nums
        
square(2,3,4,6,7,8,5,4,3,2)
<type 'tuple'>
(2, 3, 4, 6, 7, 8, 5, 4, 3, 2)

**

Keyword

In [8]:
def make_coffee(**config):
    print type(config)
    print config
    
make_coffee(decaf=False, milk=True, extra_sugar=True)
<type 'dict'>
{'decaf': False, 'extra_sugar': True, 'milk': True}

Mix and Match

Because, Python yo!

In [9]:
def illustrate_pos_kw_args(first_arg, *args, **kwargs):
    print first_arg
    print args
    print kwargs
    
illustrate_pos_kw_args(1,2,3,a=1, b=2)
1
(2, 3)
{'a': 1, 'b': 2}

Default arguments to functions

In [10]:
def hello_world(name=None):
    if name:
        return "Hello, " + name
    else:
        return "Hello, world"
In [11]:
print hello_world()
print hello_world("Chennaipy")
Hello, world
Hello, Chennaipy

Defining Functions inside Functions

In [12]:
def make_dosa(masala=False, red_chutney=False, extra_roast=False):
    
    def _evaluate_dosa_configuration(masala, red_chutney, extra_roast):
        print masala
        print red_chutney
        print extra_roast
        return True
    
    def _make_dosa(masala, red_chutney, extra_roast):
        return " ______\n(______)"
    
    if _evaluate_dosa_configuration(masala, red_chutney, extra_roast):
        return _make_dosa(masala, red_chutney, extra_roast)
        
print make_dosa(masala=True)
True
False
False
 ______
(______)

Lexical Scoping in functions

In [13]:
def fn1(arg1, arg2, arg3):
    
    def fn2():
        print "from fn2", arg1, arg2, arg3
        
    fn2()

fn1(1,2,3)
from fn2 1 2 3
In [14]:
def make_dosa(masala=False, red_chutney=False, extra_roast=False):
    
    def _evaluate_dosa_configuration():
        print masala
        print red_chutney
        print extra_roast
        return True
    
    def _make_dosa():
        return " ______\n(______)"
    
    if _evaluate_dosa_configuration():
        return _make_dosa()
        
print make_dosa(masala=True)
True
False
False
 ______
(______)

Passing Functions as Arguments to Functions

In [15]:
def make_dosa(masala=False, red_chutney=False, extra_roast=False, \
              method_of_preparation=None):
    
    if not method_of_preparation:
        raise Exception("Don't know how to make dosa")
    
    def _evaluate_dosa_configuration():
        return True
    
    def _make_dosa():
        return method_of_preparation()
    
    if _evaluate_dosa_configuration():
        return _make_dosa()
        
def chennai_dosa():
    return " ___________\n(__CHENNAI__)"

def bangalore_dosa():
    return " ___________\n(_BANGALORE_)"

        
print make_dosa(masala=True, method_of_preparation=chennai_dosa)
print make_dosa(masala=True, method_of_preparation=bangalore_dosa)
 ___________
(__CHENNAI__)
 ___________
(_BANGALORE_)
In [16]:
chennai_dosa
Out[16]:
<function __main__.chennai_dosa>
In [17]:
chennai_dosa.__class__
Out[17]:
function

Returning Functions from Functions

In [18]:
def dosa_maker(style):
    
    def chennai(*args, **kwargs):
        print args, kwargs
        return "Suda suda dosa saar"
    
    def bangalore(*args, **kwargs):
        print args, kwargs
        return "Bisi Bisi dose saar"
    
    styles = {
        "CHENNAI": chennai,
        "BANGALORE": bangalore
    }
    
    style = style.strip().upper()
    return styles[style]

bangalore_dosa_maker = dosa_maker(style="bangalore")
print bangalore_dosa_maker(masala=True)
() {'masala': True}
Bisi Bisi dose saar

Conclusion

  • Functions in Python are awesome
  • You can:
    • Define functions inside functions
    • Pass functions as arguments to other functions
    • Return functions from functions
  • Functions in Python are First Class

Fin.


First class!