本章还参考了函数的参数-廖雪峰
*def
定义函数,包括函数名、参数和功能实现代码,若有返回值,则在逻辑代码中用return
返回。
def function_name(parameters):
expressions
def function():
print('This is a function')
a = 1+2
print(a)
定义了名为 function 的函数,函数没有接收参数,之后是函数的功能代码。
执行该脚本,并无任何输出,因为只定义了函数,而并没执行函数。
输入函数调用 function(), 函数内部的功能代码将会执行。
function()
输出结果:
This is a function
3
形参:函数完成其工作所需的一项信息。
实参:调用函数时传递给函数的信息。
例2
定义函数
def greet_user(username):
print("Hello, " + username.title() + "!")
调用函数
greet_user('jesse')
输出
Hello, Jesse!
例子中,变量username是一个形参,值’jessi’是实参。
必选参数(required arguments)在函数定义必选参数后,每次调用都必须赋值,否则报错。
定义
def fun(a,b):
c = a+b
print("the c is',c)
传递参数
按顺序传递,参数个数和位置要按照定义
fun(1,2)
输出the c is 3
fun(b=3,a=2)
输出the c is 5,实参顺序位置不受影响
默认参数(default arguments),定义函数时,可以给每个形参指定默认值。通过默认参数可以减轻函数调用的复杂度。
def function_name(para_1,...,para_n=defau_n,..., para_m=defau_m):
expressions
def sale_car(price,color='red',brand='carmy',is_second_hand=True):
print('price',price,
'color',color,
'brand',brand,
'is_second_hand",is_second_hand,)
定义了 sale_car 函数,参数为车的属性,但除了 price 之外,其他形参都是有默认值的。
调用函数 sale_car(1000), 与 sale_car(1000, ‘red’, ‘carmy’, True) 是一样的效果。
也可以在函数调用过程中传入特定的参数用来修改默认参数。如 sale_car(1000,color=‘blue’)。
def get_formatted_name(first_name, middle_name, last_name):
full_name = first_name + ' ' + middle_name + ' ' + last_name
return full_name.title()
调用
musician = get_formatted_name('john', 'lee', 'hooker')
print(musician)
输出
John Lee Hooker
但不是每个人都有中间名,因此将函数修改成:
def get_formatted_name(first_name, last_name, middle_name=''):
full_name = first_name + ' ' + middle_name + ' ' + last_name
return full_name.title()
调用
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
输出
Jimi Hendrix
可变参数(arguments),不确定参数的个数,即传入参数可变,可避免将参数封装在list
或tuple
。
def function_name(*args):
expressions
def report(name,*grades):
total_grade = 0
for grade in grades:
total_grade += grade
print(name,'total grade is',total_grade)
定义的函数传入必须参数name,和可变参数*grade,是可以迭代的对象,可以是数值、列表或元组等。
调用
report('Mike',8,9)
调用时输入姓名和各科成绩
输出
Mike total grade is 17
输出姓名和总成绩。
关键字参数(keyword arguments)可以任意个数含参数名的参数,这些参数名在定义时没有出现,在函数内部自动封装成一个字典dict
。
def function_name(**kwargs):
expressions
定义
def person(name,**kw):
print('name:',name,'age:',age,'other:',kw)
调用
person('Mike',30,gender='M',city='Beijing')
输出
name: Mike age: 30 other: {'city': 'Beijing'}
定义
def portrait(name,**kw):
print('name',name)
for k,v in kw.items(): #dict.items() 可遍历字典(键,值)
print(k,v)
调用
portrait('Mike', age=24, country='China', education='bachelor')
输出
name Mike
age 24
country China
education bachelor
关键字参数可以不受限制地通过函数调用来传入。若要显示关键字函数的名字,可使用命名关键字参数。
def function_name(arg1,arg2,*,arg3,arg4):
expressions
需要*作为特殊分隔符,后面的参数为命名关键字参数。
定义
def person(name, age, *, city, job):
print(name, age, city, job)
调用
person('Jack', 24, city='Beijing', job='Engineer')
输出
Jack 24 Beijing Engineer
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数可以组合使用。
定义顺序:必选→默认→可变→命名关键字→关键字参数
定义
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
调用
f1(1, 2, 3, 'Hello', 'Bye', x=99)
输出
a = 1 b = 2 c = 3 args = ('Hello', 'Bye') kw = {'x': 99}
func(*args, **kw)
的形式调用任意函数,无论参数如何定义。可以理解成提供位置参数来拆解元组,提供关键字参数来拆解字典。调用
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)
输出
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
函数返回的值称为返回值。用return
实现。
函数可以返回任何类型的值,包括列表、字典等。
如1.5.2 (2)的例2,利用return返回人的英文全名。
def get_formatted_name(first_name, last_name, middle_name=''):
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title()
定义
def build_person(first_name, last_name):
person = {'first': first_name, 'last': last_name}
return person
该函数返回一个字典, 其中包含有关一个人的信息
调用
musician = build_person('jimi', 'hendrix')
print(musician)
输出
{'first': 'jimi', 'last': 'hendrix'}
函数内部可以调用其他函数。如果一个函数在内部调用函数本身,这个函数就是递归函数。
定义
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
这里的函数fact(n)
,相当于计算阶乘
fact(n)=n!=1×2×3×⋅⋅⋅×(n−1)×n=(n−1)!×n=fact(n−1)×n
因此,fact(n)可以表示为n x fact(n-1),只有n=1需要特殊处理
调用
fact(5)
输出
120
递归函数可以写成循环的方式,但是循环的逻辑不够清晰。递归函数定义简单,逻辑清晰。
栈(stack),又名堆栈,是限定仅在表尾(栈顶)进行插入和删除操作的线性表(表头成为栈底)。
使用递归函数要防止栈溢出。每次调用,栈就会加一层栈帧,每当函数返回就会减少一层栈帧。但是栈的大小是有限的,递归调用的次数过多会导致栈溢出。如调用fact(1000)
,就会报错。
解决递归调用栈溢出的方法是通过尾递归优化。指的是在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,interpreter会优化尾递归,无论递归调用多少次,都只占用一个栈帧,避免栈溢出。
例2
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
可以看到,return fact_iter(num - 1, num * product)
返回递归函数本身,num - 1和num * product在函数调用前就会被计算,不影响函数调用。
fact(5)对应的fact_iter(5, 1)的调用如下:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
zip函数接受任意多个(包括0个和1个)序列作为参数,合并后返回一个tuple列表.
a=[1,2,3]
b=[4,5,6]
ab=zip(a,b)
print(list(ab))
如果直接调用zip
,输出结果是一个object。如果需要可视化,则需要list()。
输出
[(1, 4), (2, 5), (3, 6)]
就会把a和b矩阵的第i位组成元组输出。
因此可以当做迭代器,用for语句进行每一位的运算。
a=[1,2,3]
b=[4,5,6]
ab=zip(a,b)
print(list(ab))
for i,j in zip(a,b):
print(i/2,j*2)
输出
0.5 8
1.0 10
1.5 12
lambda可以用来创建匿名函数,也能将其赋给变量供调用
lambda parameters:expressions
一般函数定义方法:
def fun1(x,y):
return(x+y)
调用和输出
fun1(2,3)
5
如果使用lambda
:
fun2= lambda x,y:x+y
可以用一行的代码定义简单的函数,清晰明了。
map
是把函数和参数绑定在一起运算。
定义
def fun(x,y):
return (x+y)
调用
list(map(fun,[1],[2]))
与zip
一样,直接调用map
会输出一个object(对象),因此需要用list()
进行可视化。
输出
[3]
多个列表调用
list(map(fun,[1,3],[2,5]))
输出
[3,8]
两个列表第i位进行运算,而不是列表内的元素进行运算。
====================================================================
Python学习的内容参考
《Python编程:从入门到实践》-[美] Eric Matthes
《21天学通PYTHON》
莫烦Python
廖雪峰的Python教程
等