Introduction to Python
davidbpython.com
More About User-Defined Functions
user-defined functions and code organization
User-defined functions help us organize our code -- and our thinking.
Let's now return to functions from the point of view of code organization. Functions are useful because they:
- are separate from, and do not interfere with, the rest of the code
- help us implement a modular program design
- allow us to test the function separately ("unit testing")
- help us avoid repetition in our code
- help organize our thinking
review: function block, argument and return value
def add(val1, val2):
mysum = val1 + val2
return mysum
a = add(5, 10) # int, 15
b = add(0.2, 0.2) # float, 0.4
Review what we've learned about functions:
- when we call the function, program execution jumps up to the function block, executes the block, and then returns
- the arguments are the two values passed to the function call (inside the parentheses)
- inside the function, the arguments are assigned to variables val1 and val2
- the return value inside the function is mysum
- once we have returned from the function, the return value is assigned to the variable assignment in the call, i.e. a or b above
functions without a return statement return None
When a function does not return anything, it returns None.
def do(arg):
print(f'{arg} doubled is {arg * 2}')
# no return statement returns None
x = do(5) # (prints '5 doubled is 10')
print(x) # None
- note that this function does not have a return statement
- even so, we are assigning the return value to a variable (x =)
- x would normally be assigned whatever was returned from the function
- since the function does not explicitly return anything, it returns a default value (None)
- None is the "value that means no value": in other languages it may be called "NULL", "undefined", "void"
Actually, since do() does not return anything useful, then we should not call it with an assignment (i.e., x = above), because no useful value will be returned. If you should call a function and find that its return value is None, it often means that it was not meant to be assigned because there is no useful return value.
the None object type
The None value is the "value that means 'no value'".
zz = None
print(zz) # None
print(type(zz)) # <class 'NoneType'>
aa = 'None' # a string -- not the None value!
- None is a distinct value: it is expressed by None (no quotes)
- None is a value of its own type: NoneType
- it is capitalized the same way that are the boolean values True and False
- None represents "nothing", "empty", "void" or "undefined"
- the null/empty/void value is present in most other programming languages
- it is most often used to say "nothing here", "nothing was found", "the request came up empty" and other such meanings
- the value must not have quotes -- quotes would be a 4-character string, not None
function argument type: positional
Positional arguments are required to be passed, and assigned by position.
def greet(firstname, lastname):
print(f"Hello, {firstname} {lastname}!")
greet('Joe', 'Wilson') # passed two arguments: correct
greet('Marie') # TypeError: greet() missing 1 required positional argument: 'lastname'
- positional arguments are the ones we have used up until now
- the number of arguments shown in the definition, as well as those in the call, must match
- (side note) There is no type requirement for arguments to a function. Python will accept whatever objects are passed.
function argument type: keyword
Keyword args are not required, and if not passed return a default value.
def greet(lastname, firstname='Citizen'):
print(f"Hello, {firstname} {lastname}!")
greet('Kim', firstname='Joe') # Hello, Joe Kim!
greet('Kim') # Hello, Citizen Kim!
- this function has one positional (lastname) and one keyword argument (firstname='Citizen')
- in the def, the keyword argument specifies a default value
- in the first call, the positional and keyword arguments are passed
- in the second call, the keyword argument is not passed, and so the function supplies the default value for that variable
[pr]