Python函数与变量作用域
来源:互联网 发布:网易上海房产成交数据 编辑:程序博客网 时间:2024/05/29 07:08
一、函数
1.1 函数定义
def 函数名([参数1][,参数2][,参数3]...): [函数语句]#函数语句和return语句不能同时省略 [return [返回值]]#return后面可以没有返回值
1.2函数调用
在Python中,所有语句都是实时执行的,不存在C/C++的编译过程,def也是一条可执行语句,定义一个函数。所以函数的调用必须在定义之后
>>> def add(a,b):... return a+b...>>> add<function add at 0x0000000005DAB730>>>> add(1,2)3>>> x=add>>> x(1,2)3>>> def nullFun(a,b):... return...>>> nullFun(1,2)>>>
1.3 函数参数
调用函数时,参数表中提供的参数成为实际参数,简称实参。在Python中,变量保存的是对象的引用,类似于C/C++中的指针。实参传递给形参就是将对象引用赋值给形参。
函数的多态性
多态是面向对象的一个特点,指同一个行为针对不同对象可能会得到不同的结果。Python中的对象无类型属性,变量可饮用各种不同类型的对象。同一个函数,传递的实际参数类型不同时,可获得不同的结果,体现了多态性。例如:
>>> def add(a,b):... return a+b...>>> add(1,3)4>>> add(1,1.5)2.5>>> add('abc', 'def')'abcdef'>>> add([1,3],[2,4])[1, 3, 2, 4]
参数赋值传递
Python允许以形参赋值的方式,指定将实参传递给形参。例如:
>>> def add(a,b):return a+b...>>> add(a='ab',b='cd')'abcd'>>> add(b='ab',a='cd')'cdab'
可以看出,采用这种方式时,以形参赋值为准,参数顺序可以忽略。
参数传递与共享引用
>>> def f(x): x=100...>>> a=10>>> f(a)>>> a10
可以看出在函数中重新赋值a,并不会影响函数外的a,因为Python中的赋值时建立变量到对象的引用。重新赋值时,意味着形参引用了新的对象,原来的引用已经作废。
小心使用可变参数
>>> def f(a):... a[0]='abc'...>>> x=[1,2]>>> f(x)>>> x['abc', 2]
当使用可变参数时,如列表、字典等,若在函数中修改形参,因为是共享引用,通过实参也获得修改后的对象。如上。
如果不希望在函数中的修改影响函数外的变量,也可以显示的避免。
例如列表,可以使用列表的拷贝作为实参。如:
>>> def f(a):... a[0]='abc'...>>> x=[1,2]>>> f(x[:])>>> x[1, 2]
也可以在函数内对列表进行拷贝,实参仍使用变量。例如
>>> def f(a):... a=a[:]...>>> def f(a):... a=a[:]... a[0]='abc'...>>> x=[1,2]>>> f(x)>>> x[1, 2]
有默认值的参数
如c++
传递任意个数的参数
定义参数时,参数名前使用“*”,表示可以接受任意个参数(包括0个),这些参数保存在一个元组中。
>>> def add(a,*b,c):... print(c)... s=a... for x in b:... s+=x... return s...>>> add(1,2)3>>> add(1,2,3)6>>> add(1)1
如果带“*”参数的后面仍然有参数,则必须通过赋值传递。如上。
函数嵌套定义
内部定义的函数作用域为函数内
>>> def add(a,b):... def getsum(x):... s=0... for n in x:... s+=ord(n)... return s... return getsum(a)+getsum(b)...>>> add('12', '34')202
lambda函数
lambda函数也成为表达式函数,用于定义一个匿名函数,可以将该函数赋值给变量,通过变量调用。lambda函数定义的基本格式如下。
lambda 参数:表达式
如:
>>> add=lambda a,b:a+b>>> add(1,2)3>>> add('ab','cd')'abcd'
递归函数
如C/C++
函数列表
Python允许将函数作为列表对象,然后列表索引来调用函数。如:
>>> add=lambda a,b:a+b #通过lambda简历>>> add(1,2)3>>> add('ab','cd')'abcd'>>>>>>>>> d=[lambda a,b:a+b,lambda a,b:a*b]>>> d[0](1,3)4>>> d[1](1,3)3>>>>>>#通过def建立>>> def add(a,b):... return a+b...>>> def fac(n):... if n==0:... return 1... else:... return n*fac(n-1)...>>> d=[add,fac]#建立包含函数列表的列表对象>>> d[0](1,2)3>>> d[1](5)120>>> d=(add,fac)#建立包含函数列表的元组对象>>> d[0](2,3)5>>> d[1](5)120
提示:函数列表的实质就是在元组、列表和字典等序列中简历函数对象的引用,然后通过索引来调用函数。
二、变量作用域
2.1 作用域类型
变量作用域就是变量的可访问范围,也可称为命名空间。在第一次给变量赋值时,Python创建变量,第一次给变量赋值的位置决定了变量的作用域。
作用域由大到小分为:内置作用域>文件作用域>函数嵌套作用域>本地作用域
本地作用域:不包含其他函数定义的函数的内部成为本地作用于。函数内通过赋值创建的变量,函数参数都属于本地作用域
函数嵌套作用域:包含了其他函数定义的函数的内部成为函数嵌套作用域
文件作用域:程序文件(也称模块文件)的内部为文件作用域
内置作用域:最顶层,包含了python各种预定义变量和函数的作用域成为内置作用域。
内置作用域和文件作用域有时都被成为全局作用域(变量称为全局变量),函数嵌套作用域优势也成为本地作用域(变量成为本地变量)。
作用域外的变量与作用域内的变量名称相同时,遵循“本地”优先原则,此时外部的作用域被屏蔽--成为作用隔离原则。与C/C++类似。但与C/C++不同的是,在更小作用域整体里,定义该重复变量之前的范围,程序是检测不到那个大作用域的变量的。
>>> a=10>>> def show():... print('a=',a)... a=100... print('a=',a)...>>> show()Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in showUnboundLocalError: local variable 'a' referenced before assignment
2.2 global语句
使用global语句可以在函数内部声明全局变量。全局变量增大了代码维护调试难度,不建议用。
>>> a=10>>> def show():... global a#有用吗?前面不是定义了个全局的a吗?... a+=1... print('a=',a)...>>> show()a= 11>>> show()a= 12>>> show()a= 13
2.3 nonlocal语句
作用域隔离原则同样适用于函数内部的嵌套函数。在嵌套函数内使用与上层函数本地变量同名的变量时,若该变量没有被赋值,则该变量就是上层函数的本地变量。如:
>>> def test():... a=10... def show():... print('in show(),a=',a)... show()... print('in test(),a=',a)...>>> test()in show(),a= 10in test(),a= 10
稍微修改
>>> def test():... a=10... def show():... a=100... print('in show(),a=',a)... show()... print('in test(),a=',a)...>>> test()in show(),a= 100in test(),a= 100
若想这个a与上一层a为同一个,则需要加一句nonlocal a,来声明变量是外部的本地变量。
>>> def test():... a=10... def show():... nonlocal a... a=100... print('in show(),a=',a)... show()... print('in test(),a=',a)...>>> test()in show(),a= 100in test(),a= 100