7. Functions¶
7.1 Overview¶
Functions are the basic unit of reusable code in Python
if __name__ == '__main__':
__name__
is a special variable.You can also import the functions in a code containing the above statement, but
__name__
would take the name of the module, and so whatever follows this will not be executed.when run as the main unit of execution,
__name__ = __main__
All functions return a value.
if not specified, they return
None
.
7.2 Arguments¶
example:
def kitten(a, b, c = 0):
default arguments can also be used.
any arguments with defaults must be after arguments without defaults.
def main():
x = 5
kitten(x)
print(f'in main: x is {x}')
def kitten(a):
a = 3
print('Meow.')
print(a)
if __name__ == '__main__': main()
returns
Meow.
3
in main: x is 5
call-by value:
when a value is passed to a function, the function operates on a copy of the variable. So the value is passed, not the object itself.
but it can get tricky.
def main():
x = [5]
kitten(x)
print(f'in main: x is {x}')
def kitten(a):
a[0] = 3
print('Meow.')
print(a)
if __name__ == '__main__': main()
returns
Meow.
[3]
in main: x is [3]
This is not call-by value(?) but call-by reference.
an integer is not mutable. When you assign a new value, you’re assigning an entirely new object.
a list is mutable, the object still points to the same list even if elements are mutated.
7.3 Variable length argument lists¶
Syntax
def kitten(*args): if len(args): for s in args: print(s) else: print('Meow.')
Traditional to name arguments,
args
. You can pass as many arguments as you want to the function above.An interesting way to call such functions is:
def main(): x = ['meow', 'grrr', 'purr'] kitten(*x)
7.4 Keyword arguments¶
like list arguments but dictionaries instead of tuples.
Syntax:
def kitten(**kwargs): if len(kwargs): for k in kwargs: print('Kitten {} says {}'.format(k, kwargs[k])) else: print('Meow.')
Call as:
def main(): kitten(Buffy = 'meow', Zilla = 'grr', Angel = 'rawr')
or
def main(): x = dict((Buffy = 'meow', Zilla = 'grr', Angel = 'rawr') kitten(**x)
7.5 Return¶
Again, no return statement => function returns
None
.but all functions return a value.
7.6 Generator¶
instead of a single value, a generator returns a stream of values.
for example.
range
is a generator.consider this example:
def inclusive_range(*args):
numargs = len(args)
start = 0
step = 1
# initialize parameters
if numargs < 1:
raise TypeError(f'expected at least 1 argument, got {numargs}')
elif numargs == 1:
stop = args[0]
elif numargs == 2:
(start, stop) = args
elif numargs == 3:
(start, stop, step) = args
else: raise TypeError(f'expected at most 3 arguments, got {numargs}')
# generator
i = start
while i <= stop:
yield i
i += step
a good example on how to use variable length arguments.
yield
yields a value.you can call the above in this way:
def main():
for i in inclusive_range(25):
print(i, end = ' ')
print()
7.7 Decorator¶
Special type of function that returns a wrapper function
In python, a function is also a type of object.
Syntax:
def elapsed_time(f):
def wrapper():
t1 = time.time()
f()
t2 = time.time()
print(f'Elapsed time: {(t2 - t1) * 1000} ms')
return wrapper
<>
@elapsed_time
def big_sum():
num_list = []
for num in (range(0, 10000)):
num_list.append(num)
print(f'Big sum: {sum(num_list)}')
<>
def main():
big_sum()
The above
wrapper
can be modified for variable argument lists using*args