Python functions
-> Types of function
a) Built in function and predefined function
-> id(), type(), print(), input, eval
b) Customized function / user defined function
Syntax:
def function_name(parameters):
‘’’doc_string’’’
body
return value;
Function Parameters
a) Positional Argument
b) Keyword Argument
-> We can use positional argument and keyword argument simultaneouly
but first we have to take positional argument first.
-> Argument vs Parameter
Semantics
def my_func(a,b):
# code here
-> In this context, a and b are called parameters of my_func
-> Also note that a and b are variables, local to my_func
When we call the function
x = 10
y = ‘a’
my_func(x, y)
-> In this context x and y are called arguments of my_func
-> Also note that x and y are passed by reference, i.e the memory address
of x and y are passed.
Positional and keyword arguments
a) Positional argument
-> Most common way of assigning arguments to parameters, via the order
in which they are passed. i.e their position.
b) positional argument with default value
-> A positional argument can be made optional by specifying a default
value for the corresponding parameter.
Def my_func(a, b=100):
-> consider a case where we have 3 arguments, and we want to make one
of them optional.
-> If a positional parameter is defined with a default value every positional
parameter after it must also be given a default value.
c) keyword arguments (named argument)
my_func(a=1, c=2)
-> Positional arguments can, optionally be specified by using the
parameter name, whether or not parameter have default values.
-> Increased readability of code.
-> Order of argument can be changed.
-> But once you used named argument, all argument hereafter must be
named too.
Unpacking iterables
-> (1,2,4)
-> What defines a tuple in Python, is not (), but, 1,2,3 is also a tuple
-> The () are used to make the tuple clearer.
To create a tuple element with a single element
(1) --> will not work as intended --> int
1, or (1,) --> tuple
The only exception is when creating an empty tuple: () or tuple()
Packed Values
-> refers to values that are bundled together is same way.
a) Tuples and list l=[1,2,3] t=(1,2,3)
b) Even a string is considered to be a packed value: s=’python’
c) Sets and dictionaries are also packed values: set1={1,2,3} d={‘a’:‘1’}
-> In fact any iterable can be considered as packed value.
Unpacking Packed values
-> Unpacking is the act of splitting packed values into individual variables
contained in a list or tuple.
A,b,c = [1,2,3] 3 elements in [1,2,3] -> need 3 variables to unpack.
-> this is actually a tuple of 3 variables: a,b and c
-> The unpacking into individual variables is based on the relative
positions of each element.
-> Does this remind you of howpositional arguments were assigned to
parameters in function.
Unpacking other iterables:
1) Unpacking tuple (into tuple)
a,b,c =10,20, ‘hello’ -> a=10, b=20, c=’hello’
2) Unpacking string (into tuple)
a,b,c = ‘XYZ’
Instead of writing a= 10 \n b=20
we can write a, b = 10, 20
In fact, unpacking works with any iterable type.
Simple Application of unpacking
1) Swapping values of two variables
a,b = b,a
-> this works because in python, the entire RHS is evaluated first and
completely.
-> Then assignment are made to the RHS.
-> it creates a tuple in memory the first element of that tuple is a memory
address which is what b is pointing to, and the second element is a which
is the memory address of what a is pointing to, and then it does the
assignment, we looking for the copy of memory addresses.
Unpacking Sets and Dictionaries
d = {‘key1’: 1, ‘key2’:2, ‘key3’: 3}
for e in d: --> e iterated through the keys: ‘key1’, key2’, key3
-> so, when unpacking d, we are actually unpacking the keys of d
a,b,c =d
-> Dictionaries and Sets are unordered type.
-> They can be iterated, but there is no gurantee the order of the results
will match your
-> in practice, we rarely unpack sets and dictionaries in precisely this way.
Applied to python >= 3.5
Extended unpacking
-> We don’t always want to unpack every single item in an iterable.
-> We may, for example, want to unpack the first value, and then unpack
the remaining values into another variable.
L = [1, 2, 3, 4, 5, 6]
we can achieve this using slicing: a = l[0] b=l[1:]
or using simple unpacking a,b = l[0], l[1:] (aka parallel assignment)
We can use the * operator
-> a, *b = l
-> take the first iterable from l and stuffed into it to and everything else
making into a list and put into a b.
-> Apart from cleaner syntax, it also works with any iterable, not just
sequence types.
Usage with ordered types
a, *b = [-10, 5, 2, 100] ==> a= -10, b=[5,2,100]
a, *b = (-10, 5, 2, 100) ==> a= -10, b=[5,2,100]
a, *b = ‘XYZ’ ==> a= X, b=[‘Y’, ‘Z’]
a, b, *c = 1,2,3,4,5
a, b, *c, d = [1,2,3,4,5]
a, *b, c, d = ‘python’
-> The * operator can only be used once in the LHS an unpacking
assignment.
-> l3 = [*l1, *l2] (merging list)
Usage with unordered types
Types such as sets and dictionaries have no ordering
s = {10, -99, 4, ‘d’}
-> sets and dictionary keys are still iterable, but iterating has no gurantee
of preserving the order in which the elements were created/added
-> But the * operators works, since it works with any iterable.
-> in practice we rarely unpack sets and dictionaries directly in this way.
-> It is useful though in a situation where you might want to create single
collection containing all items of multiple sets, or all the keys og multiple
dictionaries.
-> The ** unpacking operator
-> When working with dictionaries we saw that * essentially iterated the
keys.
-> That ** operator cannot be used in the LHS of an assignment.
D= {**d1, **d2, **d3}
-> Duplicate key values will overwrite.
-> You can even use it to add key-value pair from one or more dict into a
dictionary literals.
Nested unpacking
l = [1,2 [3,4]]
a,b ,c = l
a,b, (c,d) = l
a,*b,(c,d,e) = [1,2,3,’XYZ’]
a, *b, (c,*d) = [1,2,3,’python’]
*args
-> def func1(a, b, *args)
# code
args is a tuple not a list
The * parameter name is arbitary you can make it whatever you want.
*args exhausts positional argument
You cannot add more positional argument after *args
-> We can unpack the list first and then pass it to the function.
-> func(*l)