0% found this document useful (0 votes)
47 views

Functions in Python: Arguments, Lambdas, Decorators, Generators

This document discusses various Python functions concepts including defining simple functions, functions with arguments, default arguments, lambda functions, generators, and decorators. It provides examples of defining functions that take positional and keyword arguments, functions with default arguments, lambda functions, generator functions and expressions, and using decorators to modify function behavior. Various introspection methods like type(), dir(), and getattr() are also demonstrated.

Uploaded by

Eps Sabangan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
47 views

Functions in Python: Arguments, Lambdas, Decorators, Generators

This document discusses various Python functions concepts including defining simple functions, functions with arguments, default arguments, lambda functions, generators, and decorators. It provides examples of defining functions that take positional and keyword arguments, functions with default arguments, lambda functions, generator functions and expressions, and using decorators to modify function behavior. Various introspection methods like type(), dir(), and getattr() are also demonstrated.

Uploaded by

Eps Sabangan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Functions in Python

arguments, lambdas, decorators, generators


Defining simple functions:
>>> def my_func():
... print "Inside my function"
...
>>> my_func()
Inside my function
Function with arguments - basics
>>> def func_with_args(a, b):
... print 'a: ', a
... print 'b: ', b
...
>>> func_with_args(5, 'c')
a: 5
b: c
Two types of arguments
● positional - arguments order matters
>>> func_with_args(5, 'c')
a: 5
b: c
● keyword - argument name matters
func_with_args(b=5, a='c')
a: c
b: 5
Mixing position and keyword
arguments
>>> def func_with_args(a, b, c):
... print a, b, c
...

>>> func_with_args(1, c=3, b=2)


123

>>> func_with_args(a=1, 3, b=2)


File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
Passing attributes - old style
>>> func_with_args(1, 2, 3) # standart call
123

>>> apply(func_with_args, [1, 2, 3]) # positional


123

>>> apply(func_with_args, [], {'a': 1, 'c': 3, 'b': 2}) # keywords


123

>>> apply(func_with_args, [1], {'c': 3, 'b': 2}) # mixed


123
Passing attributes - new style
>>> func_with_args(*[1, 2, 3]) # positional
123

>>> func_with_args(**{'b': 2, 'a': '1', 'c': 3}) # keywords


123

>>> func_with_args(*[1], **{'b': 2, 'c': 3}) # mixed


123

>>> func_with_args(*[1], **{'b': 2, 'a': '1', 'c': 3})


TypeError: func_with_args() got multiple values for keyword
argument 'a'
Function arguments revisited
>>> def f(*args, **kwargs):
... print args
... print kwargs

>>> f()
()
{}
>>> f(1,2,3)
(1, 2, 3)
{}
>>> f(a=1, c=3, b=2)
()
{'a': 1, 'c': 3, 'b': 2}
>>> f(1, b=2, c=3)
(1,)
{'c': 3, 'b': 2}
Default arguments
>>> def func(a=5):
... print a

>>> func()
5

>>> func(6)
6

>>> func()
5
Default arguments - part II
>>> def func(a=[]):
... print a

>>> func()
[]

>>> func(['a'])
['a']

>>> func()
[]
Default arguments - part III
>>> def func(a=[]):
... a = a * 5
... print a
>>> func()
[]
>>> func()
[]
>>> func([1])
[1, 1, 1, 1, 1]
>>> func()
[]
Default arguments - part IV - problem
>>> def func(a=[]):
... a.append(2)
... print a

>>> func()
[2]
>>> func()
[2, 2]
>>> func([1])
[1, 2]
>>> func()
[2, 2, 2]
Default arguments - part V - solution
>>> def func(a=None):
... a = a or []
... a.append(2)
... print a
...

>>> func()
[2]

>>> func()
[2]
Preloading arguments
>>> def func(a, b, c):
... print a, b, c

>>> import functools


>>> func_preloader = functools.partial(func, a=5, c=3)
>>> func_preloader()
TypeError: func() takes exactly 3 arguments (2 given)

>>> func_preloader(b=2)
523
Preloading arguments - mixing
>>> def func(a, b, c):
... print a, b, c

>>> import functools


>>> func_preloader = functools.partial(func, a=5, c=3)

>>> func_preloader(2)
TypeError: func() got multiple values for keyword argument 'a'
Python introspection

""" In computing, type introspection is the ability of a


program to examine the type or properties of an object
at runtime. """

Wikipedia - Type Introspection


Introspection basics
>>> def func(a, b, c):
... """ Just an example how introspection works """
... pass

>>> help(func)
Help on function func in module __main__:
func(a, b, c)
Just an example how introspection works
Methods related to introspection
● type(var) # show the type of the object
● dir(var) # lists object's methods and attributes
● id(var) # return object specific identificator
● getattr(obj, <attribute name>, <default value>)
● hasattr(obj, <attribute name>)
● globals()
● locals()
● callable(obj) # returns True if the object is callable
Lambda functions
>>> f = lambda x,y: x+y
>>> f(1,2)
3

>>> f = lambda x,y=[]: x+y


>>> f([1])
[1]

>>> f([1], [2])


[1, 2]
Lambdas and print
# Python 2.7.3
>>> a = lambda x: print x # print is a statement
File "<stdin>", line 1
a = lambda x: print x

Lambdas can not contain statements

# Python 3.2.3
>>> f = lambda x: print(x) # print is a function
>>> f(5)
5
Lambdas usage
>>> map(lambda x: x**2, range(5))
[0, 1, 4, 9, 16]

>>> [x**2 for x in range(5)]


[0, 1, 4, 9, 16]

>>> reduce(lambda a, x: a+x, range(5))


10

Avoid using lambdas and check Guido van Rossum's vision


for lambdas http://www.artima.com/weblogs/viewpost.jsp?thread=98196
Generators
yield x # Generator function send protocol
>>> def a():
... yield 5
... yield 6
... yield 7

>>> a()
<generator object a at 0x158caa0>

>>> a()
<generator object a at 0x158caa0>
Generators - range vs xrange
>>> range(10**10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError

>>> xrange(10**10)
xrange(10000000000)

# range has been replaced by xrange in Python 3.x


Creating generators
>>> def fib():
... a, b = 0, 1
... while True:
... yield a, b
... a, b = b, a+b
...
>>> g = fib()
>>> g
<generator object fib at 0x19b4be0>
Creating generators
>>> g.next()
(0, 1)
>>> g.next()
(1, 1)
>>> g.next()
(1, 2)
>>> g.next()
(2, 3)
Exhausting generators
>>> def cubes(n):
... for i in range(n):
... yield i**3
>>> c = cubes(3)
>>> c.next() # 0
>>> c.next() # 1
>>> c.next() # 8
>>> c.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Generators and comprehension lists
>>> def cubes(n):
... for i in range(n):
... yield i**3
...
>>> [a for a in cubes(3)]
[0, 1, 8]
Generators and the send method
>>> def waiting_for_input():
... i = 0
... while True:
... i = yield i**3
...
>>> f = waiting_for_input()
>>> f.next() # 0
>>> f.send(8) # 512
>>> f.send(10) # 1000
>>> f.send(12) # 1728
Decorators
>>> def decorator(func):
... print 'Entering decorator'
... return func
...
>>> @decorator
... def f():
... print 'Executing F'
...
Entering decorator
>>> f()
Executing F
Decorators simplified
>>> def decorator(func):
... print 'Entering decorator'
... return func
...
>>> @decorator
... def f():
... print 'Executing F'

# Using the decorator above is the same as using:


>>> f = decorator(f)
Functions as Decorators
>>> def decorator(func):
... def wrap():
... print 'Calling function %s' % func.__name__
... func()
... print 'Exiting decorator'
... return wrap
...
>>> @decorator
... def f():
... print 'Executing F'
...
>>> f()
Calling function f
Executing F
Exiting decorator
Functions as decorators - part II
>>> def decorator(func):
... def wrap(a, b, c):
... print 'Function f called with %s, %s, %s' % (a, b, c)
... return func(a, b, c)
... return wrap
...
>>> @decorator
... def f(a, b, c):
... return a + b + c
...
>>> f(1, 2, 3)
Function f called with 1, 2, 3
6
Classes as decorators
>>> class decorator(object):
... def __init__(self, func):
... print 'Initializing decorator'
... self.func = func
... def __call__(self, *args, **kwargs):
... print 'Calling method'
... return self.func(*args, **kwargs)
>>> @decorator
... def f(a, b, c):
... return a + b + c
...
Initializing decorator
>>> f(1, 2, 3)
Calling method
6
Decorators with arguments
>>> def decorator(debug=False):
... def wrap(func):
... def f_wrap(a, b, c):
... if debug:
... print 'Function f called with %s, %s, %s' % (a,
b, c)
... return func(a, b, c)
... return f_wrap
... return wrap
Decorators with arguments
>>> @decorator(debug=True)
... def f(a, b, c):
... return a + b + c
...
>>> f(1, 2, 3)
Function f called with 1, 2, 3
6

>>> @decorator(debug=False)
... def f(a, b, c):
... return a + b + c
...
>>> f(1, 2, 3)
6
Q&A
Problems to solve
1) Create a function that accept both positional and
keyword arguments and returns their sum

2) Create a generator that implements a dice that "brokes"


after the 10th roll

3) Create a decorator that converts letters to number


according to their position in the alphabet and combine it
with the solution of problem #1. When converting letters to
numbers make them lowercase and count from 0 i.e. a==0,
b==1.
About Me
eng. Ilian Iliev

● Web Developer for 9+ years


● Python/Django fan for 3+ years
[email protected]
● http://ilian.i-n-i.org
● https://github.com/IlianIliev/

You might also like