*def 定义函数,包括函数名、参数和功能实现代码,若有返回值,则在逻辑代码中用return返回。
结构 def function_name(parameters): expressions 例1 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 例1 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’)。
默认值还能将参数变为可选例2 定义 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 例1定义
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'} 例2定义
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'}函数内部可以调用其他函数。如果一个函数在内部调用函数本身,这个函数就是递归函数。
例1定义
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局部变量的作用域在某个函数的内部范围。
例先定义一个函数
def fun(): a = 10 print(a) return a+100 print(fun())此时输出
10 110这里定义了一个局部变量a,作用域在函数fun内部,在函数外则不是局部变量的a。
全局变量的作用域在所编写的整个程序。全局变量一般全部用大写字母表示,便于辨认。
例定义
APPLE = 100 def fun(): a = 10 print(a) return a+100 print(APPLE) print(a)此时只能输出100,而输出a则报错,因为a是局部变量。 函数中调用全局变量
APPLE = 100 def fun(): a = APPLE return a+100 print(APPLE) print(fun())输出
100 200 函数内定义全局变量 APPLE = 100 def fun(): global a a = 20 return a+100 print(APPLE) print(a) 在外部调用能在局部中修改的全局变量。即在函数中使用函数外的变量,可使用global关键字。打印APPLE输出100,输出a会报错。但是python3.7.0版本以上,支持函数体内声明全局变量。因此一般在外部先赋值None。
APPLE = 100 a = None def fun(): global a a = 20 return a+100 print(APPLE) print('a past=',a) print(fun()) print('a now=',a) 100 a past= None 120 a now =20==================================================================== Python学习的内容参考 《Python编程:从入门到实践》-[美] Eric Matthes 《21天学通PYTHON》 莫烦Python 廖雪峰的Python教程 等