Python3 函数
定义函数
def 函数名(参数列表):
函数体
- 函数内容以冒号起始,并且缩进
return [表达式]
表示返回一个值。不带表达式的return
相当于返回None
参数传递
在python中,类型属于对象,变量是没有类型的。
a=[1,2,3]
a='Google'
[1,2,3]
是List类型,'Google'
是String类型,变量a
没有类型,仅仅是一个对象的引用(指针),可以指向List类型对象,也可以String类型对象。
可变对象(mutable)与不可变(immutable)对象
在python中,string,tuple,number,None是不可变对象,list,dict是可变对象
python中函数的参数传递
* 不可变对象:类似C++的值传递,如number,string,tuple,None。如fun(a),传递的是a的值,没有影响a对象本身
* 可变对象:类似C++的引用传递,如list,dict。如fun(a),则是将a真正地传过去,更改后fun()外部的a也将变化
参数类型
默认参数
调用函数时,如果没有传递参数,则会使用默认参数。
def power(x,n=2):
s=1
while n>0:
n=n-1
s=s*x
return s
当调用power(5)
时,相当于调用power(5,2)
>>>power(5)
25
>>>power(5,2)
25
注意事项:
1. 必选参数在前,默认参数在后
2. 当函数有多个参数时,把变化大的参数放前面,变化小的参数放在后面。变化小的参数就可以作为默认参数。
3. 有多个默认参数的时候,调用的时候,既可以按顺序提供默认参数,也可以不按顺序提供部分默认参数。
当不按顺序提供部分默认参数时,需要把参数名写上。
4. 默认参数必须指向不变对象
可变参数
定义可变参数,需要在参数前加*
,在函数内部接收到的是一个tuple
。调用时,可传入任意个参数,包括0个参数:
def calc(*numbers):
sum=0
for n in numbers:
sum+=n*n
return sum
>>> calc(1,2,3)
14
>>> calc(1,3,5,7)
84
如果有一个list
或tuple
,在list
和tuple
前加*
,把其元素变为可变参数传进去
>>>nums=[1,2,3]
>>>calc(*nums)
14
关键字参数
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
,用**
表示
def person(name,age,**kw):
print('name:',name,'age:',age,'other:',kw)
person()
除了必选参数name
和age
,还接受关键字参数kw
。在调用该函数时,可以只传入必选参数:
>>>person('Michael',30)
name:Micheael age:30 other:{}
也可以传入任意个数的关键字参数:
>>>person('Bob',35,city='Beijing')
name:Bob age:35 other:{'city':'Beijing'}
命名关键字参数
- 如果要限制关键字参数的名字,可以用命名关键字参数。
- 命名关键字参数需要一个分隔符
*
,*
后面的参数被视为命名关键字参数。
定义如下:
def person(name,age,*,city,job):
print(name,age,city,job)
调用如下:
>>>person('Jack',24,city='Beijing',job='Engineer')
- 如果函数定义中已经有一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
*
【注】使用命名关键字参数时,如果没有可变参数,必须加*
作为特殊分隔符。如果缺少*
,Python解释器将无法识别位置参数和命名关键字参数
def person(name,age,*args,city,job):
print(name,age,args,city,job)
- 命名关键字参数必须传入参数名,如果没有传入,调用则报错
>>>person('Jack',24,'Beijing','Engineer')
Traceback(most recent call last):
File "<stdin>",line 1,in <module>
TypeError:person() takes 2 positonal argments but 4 were given
由于调用时缺少参数名city
和job
,python解释器把这4个参数视为位置参数,但person()
函数仅接受2个位置参数。
- 命名关键字参数可以有缺省值。
def person(name,age,*,city='Beijing',job):
print(name,age,city,job)
>>>person('Jack',24,job='Engineer')
Jack 24 Beijing Engineer
参数组合
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数、命名关键字参数。但定义的顺序必须是必选参数、默认参数、可变参数、命名关键字参数、关键字参数
匿名函数
python使用lamda创建匿名函数
匿名函数不使用def
语句定义一个函数。
* lamda只是一个表达式,函数体比def
语句简单
* lamda函数有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数
语法
lamda [arg1,agr2,...argn]:expression
sum = lamda arg1,arg2: arg1+arg2
print('相加后的值:',sum(10,20))
变量作用域
分类
- L(Local) 局部作用域
- E(Enclosing) 闭包函数外的函数中
- G(Global) 全局作用域
- B(Bulit-in) 内建作用域
按以上顺序查找变量。
x=int(2.9) #内建作用域
g_count=0 #全局作用域
def outer():
o_count=1 #闭包函数外的函数中
def inner():
i_count=2 #局部作用域
Python中只有模块(module),类(class),函数(def,lamda)才会引入新作用域,其他代码块(如if/elif/else、try/except、for/while)不会引入新作用域
global和nonlocal关键字
- 当内部作用域想修改外部作用域的变量时,使用
global
和nonlocal
num=1
def fun1():
global num
print(nmu)
num=123
print(num)
fun1()
>1
>123
- 如果修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量需要
nonlocal
def outer():
num=10
def inner():
nonlocal num
num=100
print(num)
inner()
print(num)
outer()
错误范例
a=10
def test():
a=a+1
print(a)
test()
错误原因时局部作用域引用错误,因为test中a是局部,但未定义,无法修改。