def greeting(name):
print(f"Hello, {name}!")
greeting("Ayesha")Hello, Ayesha!
(CSE331) Python for Data Science
A function groups a reusable calculation or task under a name. Good functions have a clear purpose, explicit inputs, and predictable results.
Use def, a parameter list, and an indented body. Defining a function does not execute its body; calling it does.
def greeting(name):
print(f"Hello, {name}!")
greeting("Ayesha")Hello, Ayesha!
name is a parameter in the definition; "Ayesha" is an argument supplied in the call.
The same function can be called with another argument:
greeting("Imran")Hello, Imran!
print() displays something. return sends a value back to the caller and immediately ends that function call.
def square(n):
return n**2
result = square(6)
print(result)
print(result + 10)36
46
The returned value can be stored and used in another calculation.
Compare a function that only prints:
def show_square(n):
print(n**2)
result = show_square(6) # displays 36
print(result) # None36
None
A function that reaches its end without an explicit returned value returns None. For a reusable calculation, return the result and let the caller decide how to display it.
Sometimes, it is useful to give a default value to a parameter. This means that if the caller does not provide a value, Python will automatically use the default.
Example:
def sum_first(arg_list, n=5):
total = 0
for value in arg_list[:n]:
total += value
return totaln is a nonnegative integer.n is not specified, the function sums up to the first 5 elements.n is provided, it overrides the default.print(sum_first([1, 2, 3, 4, 5, 6, 7])) # default n=5 gives 15
print(sum_first([1, 2, 3, 4, 5, 6, 7], 3)) # n=3 gives 615
6
An argument can be matched by its position or by the parameter name:
values = [1, 2, 3, 4, 5, 6, 7]
print(sum_first(values, 3)) # positional argument
print(sum_first(values, n=3)) # keyword argument; same result6
6
Keyword arguments make calls easier to read, especially in library functions. In these ordinary calls, positional arguments come before keyword arguments. Do not supply the same parameter twice.
To return several results together, place them in a tuple (or list). The function returns that one object, and the caller can unpack its contents.
Example:
def power(a, b):
return (a**b, b**a)
a_to_b, b_to_a = power(2, 5)
print(a_to_b)
print(b_to_a)32
25
2**5 and 5**2.Python has support for so-called anonymous or lambda functions, which are a way of writing functions consisting of a single expression, whose value is returned automatically.
They are defined with the lambda keyword:
def short_function(x):
return x * 2
# Equivalent Anonymous Function
equiv_anon = lambda x: x * 2
equiv_anon(10)20
They are especially convenient in data analysis because, as we’ll see, there are many cases where data transformation functions will take functions as arguments.
For example, suppose we wanted to sort a collection of strings by the number of distinct letters in each string:
strings = ["foo", "card", "bar", "aaaa", "abab"]sort method:strings.sort(key=lambda x: len(set(x)))
strings['aaaa', 'foo', 'abab', 'bar', 'card']
Sometimes we want a function to produce a sequence of values one at a time instead of returning everything at once. This is where generator functions come in.
def, but use yield to produce individual values. Calling a generator function creates a generator; its body starts running when we request values.Example:
def count_up_to(n):
i = 1
while i <= n:
yield i # produce a value and pause
i += 1
gen = count_up_to(5)
print(next(gen)) # 1
print(next(gen)) # 21
2
yield.next() is called again.After the first two calls to next(), a loop continues from the remaining values:
for value in gen:
print(value) # 3, 4, 5
print(list(gen)) # []: the generator is exhausted3
4
5
[]
Create a new generator to start again. A further next() call on an exhausted generator raises StopIteration.
Why Generators?
Example: Infinite Even Numbers
def infinite_even_numbers():
n = 0
while True:
yield n
n += 2
gen = infinite_even_numbers()
print(next(gen)) # 0
print(next(gen)) # 2
print(next(gen)) # 40
2
4
Division with Remainder Write div_w_remainder(num, div) for integer inputs, assuming div > 0. Return the floor quotient (//) and remainder (%) as a tuple. Both results are already integers; no conversion is needed.
Locating Elements in a List Write a function locate(x, item) that takes a list x and searches for the element item. Return the index of the first match, or -1 if not found. Use a loop over range(len(x)); do not use .index().
Area of a Circle Write circle_area(radius, pi=3.1416) to return the area for a nonnegative radius. Call it using the default, then supply a different approximation of pi by keyword.
Maximum of Three Numbers Write a function max_of_three(a, b, c) that returns the largest of the three numbers without using max(). Check negative numbers and ties.
Generator Exercise Write a generator function squares(n) that yields the squares of numbers from 1 up to n. For n >= 1, test it using next() followed by a for loop. Explain why the loop starts with the next remaining value.
def, then call it with suitable arguments.print() displays a result; return makes a result available to the caller.yield to produce values one at a time and is consumed during iteration.