Python 函数
转载请标明出处(http://blog.youkuaiyun.com/lis_12/article/details/52815944).
1 函数
格式:
def add(x,y):
return x+y
参数的顺序和数量必须与函数定义匹配,否则会引发TypeError.可以为函数设置默认参数,如果函数中存在默认参数,该参数以及后续参数都是可选的.(显式传参没必要按顺序赋值);
定义函数后,默认的参数值会传递给以值的方式提供给默认对象,例如:
a = 1 def f(x = a): print 'a:',a,'x:',x f() #a: 1 x: 1 a = 2 f() #a: 2 x: 1
使用可变对象作为默认值可能会发生意料之外的行为.
def f(x = []): x.append(1) print x f()#[1] f()#[1,1]
如果不理解上述结果,参见(http://blog.youkuaiyun.com/lis_12/article/details/52693333)
函数传参
一般格式:函数中参数顺序为fun(一般参数,默认参数,元组(*),字典(**))
函数中参数传递的是引用;
*arg,给参数中加上*后,函数就可以接受任意数量的参数(这也是Python不需要重载的原因);
可以显式地给每一个参数赋值,此时就不需要按顺序赋值;
函数中以**arg开头的参数,可以把所有额外的关键字参数(不在函数参数中)都放入字典中;
如果函数有多个参数,可以使用*arg来传参,如函数fun(a,b,c,d,e),arg = [0,1,2,3,4],fun(*arg)等价于fun(0,1,2,3,4,5);
def fun(arg1,arg2=0,*arg_tuple,**arg_dict): '''函数说明''' print 'arg1:',arg1 print 'arg2:',arg2 print 'arg_tuple:',arg_tuple print 'arg_dict:',arg_dict def fun0(a,b,c): print a,b,c if __name__ == '__main__':#主程序 '''如果模块是被导入的 __name__为文件名字,如果是直接执行的,__name__ 为__main__''' fun(1) #1,0,[],{} fun(1,2) #1,0,[],{} fun(1,2,3) #1,2,[3],{} fun(1,2,3,4,5) #1,2,[3,4,5],{} fun(1,*(2,3,4,5)) #1,2,[3,4,5],{},等价于fun(1,2,*(3,4,5)) fun(1,2,*(3,4,5)) #1,2,[3,4,5],{} #这两个是不一样的,tuple处不同 fun(1,2,*(3,4,5),**{'x':1,'y':2}) #将(3,4,5)当成了三个参数1,2,[3,4,5],{'y': 2, 'x': 1} fun(1,2,(3,4,5),**{'x':1,'y':2}) #(3,4,5)为一个参数1,2,((3,4,5),),{'y': 2, 'x': 1} fun0(c=1,b=2,a=3) #3 2 1 fun0(*(1,2,3)) #1,2,3 等价于fun0(1,2,3)
注:当元组中只有一个元素时候,需要在后面加上,号,如果不加这个’,’,就会将()按小括号处理.
作用域
每次执行一个函数的时候,都会创建一个新的局部命名空间.该空间代表一个局部环境,其中包含函数参数的名称和函数体内赋值的变量.
解析变量时,解释器将首先搜索局部命名空间,如果没有找到匹配的名称,就会搜索全局命名空间,如果仍未找到,则会检查内置命名空间,还找不到的话就会引发异常.
a = 1 def f(): a = 12 #函数中的a并不是全局变量中的a,而是新建的局部变量a. f() print a #1 #改变上述行为 a = 1 def f(): global a #将a声明为属于全局命名空间的全局变量 a = 12 f() print a #12
局部作用域可以嵌套,但是函数不能给定义在外部函数中的变量重新赋值,即外部的作用域不能给里面作用域的变量重新赋值,如f1()里就不能给f()里面的变量重新赋值.注:虽然不能重新赋值,但是其他的操作还是能够用的.
在函数体内使用global声明的变量为全局变量,在全局命名空间内.
(如果不理解,见图和代码)
a = 1 def f(): b = 2 def f1(): try: a = a - 1#a是全局变量,f1()为a的外部作用域,so不能重新赋值 except Exception,e: print e #print a,b 这样会报错,但是不知道原因.... def f2(): try: b -= 1#b是f1()作用域中的变量,f2()为b的外部作用域,so不能重新赋值 except Exception,e: print e #print a,b def f3(): c = 3 def f31(): #print a,b,c try: c -= 1#c是f3()作用域中的变量,f31()为c的外部作用域,so不能重新赋值 except Exception,e: print e f31() f1() f2() f3() f() ''' result: local variable 'a' referenced before assignment local variable 'b' referenced before assignment local variable 'c' referenced before assignment ''' #other a = [] def f(): a.append(1)#只是在原地址上进行了操作,不是重新赋值 print a f() #[1]
以f1()为例,语句a = a - 1在给a局部赋值之前会尝试读取它的值,虽然存在全局变量a,但是不会给局部变量a提供值,但是局部空间内没有变量a,所以报错.
个人理解:当使用赋值操作时,解释器会认为f1()局部作用域内已经创建了一个局部变量a,所以不会使用全局变量a,但是在f1()内并没有创建一个局部变量a.
函数中的变量在定义时,就确定了它是局部变量还是全局变量,不能中途改变它们的作用域.