python之函数基础
从定义开始
众所周知,函数是可以重用的程序段,它们允许你给一块语句一个名称,然后你可以在你的程序的任何地方使用这个名称任意多次地运行这个语句块。
python的函数是用def关键字来定义,主要包括:函数名、函数参数、函数体、函数返回值。
#!/usr/bin/env python def foo(): return 1 print foo()
以上例子的运行结果为:
该例子中,函数名为foo, 我们通过foo()来调用该函数,打印返回值1
函数Scope
python函数运行的时候,会创建自己的scope,即作用域(或者说函数有自己的namespace,即命名空间)。执行函数时,如果在函数体中遇到了变量名,python首先会在该函数的namespace内寻找该变量。
python有一些内置函数,可以让我们来查看函数的namespaces,下面看一个例子,可以查看函数的local 和global 作用域。
#!/usr/bin/env python a_string = "This is a global variable" def foo(): print "locals:" print locals() print "globals:" print globals() # doctest: +ELLIPSIS foo() # 2
执行结果:
{'foo': <function foo at 0x19c100c8>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': './2.py', 'a_string': 'This is a global variable', '__name__': '__main__', '__package__': None, '__doc__': None}
locals:
{}
可以看到,内建函数globals返回的是一个dict,里面是全局性的一些变量(注意:我们定义的a_string也在里面,a_string是在函数外定义的)。代码里的#2处,调用了foo函数,里面的locals函数返回的是函数自己的namespace(foo中没有定义任何变量,所以是空的)
变量分辨规则
在函数内部也可以访问global变量。python的作用域规则是:
1. 变量在创建时,local作用域中默认创建的是local变量
2. 在local作用域(scope)中访问变量时,首先在local作用域中寻找变量,然后在所有外围作用域中寻找变量。
3. 在local作用域中修改变量时,默认是在local作用域寻找该变量,如果找不到,则新建一个变量。除非声明要修改的是global变量。
下面的例子是在foo函数里打印global变量。
#!/usr/bin/env python a_string = "This is a global variable" def foo(): print locals() print a_string #1 foo()
执行结果:
This is a global variable
在foo函数里,先打印了locals,是空的。然后在#1处,打印a_string这个变量。这时候发生以下事情:
1. python先在locals里面寻找,locals是空的,所以找不到。
2.python在globals里面寻找,可以找到a_string,然后获得值,打印。
再看一个例子:
#!/usr/bin/env python a_string = "This is a global variable" def foo(): a_string = "test" #1 print locals() print a_string #2 def foo1(): global a_string #4 a_string = "Oh. global variable has been changed in foo1." #5 foo() print a_string #3 print "---------------------" foo1() print a_string#6
执行结果为:
test
This is a global variable
---------------------
Oh. global variable has been changed in foo1.
上面的代码中,有以下几个要点:
1. #1是要给a_string赋值(即修改变量值),先在locals中寻找a_tring, 没有找到,则新创建local变量。所以打印locals时,结果为:{'a_string': 'test'} 。
2. #2处打印时,按照我们之前说的变量分辨规则, 先从locals中寻找a_tring变量,在#1处有定义,所以直接打印
3.#3处不在任何函数中,位于全局作用域,所以直接查找globals,找到了a_string,打印。
4.#4处声明了一个全局变量(a_string之前已经声明,这里表示在local作用域中使用全局a_string)
#5处修改a_string, 因为#4中声明了a_string是全局的,所以修改a_string之后,#6处打印的是修改后的值
变量生存周期
#!/usr/bin/env python def foo(): x = 1 foo() print x # 1
执行结果:
File "./5.py", line 6, in <module>
print x # 1
NameError: name 'x' is not defined
变量都是有生存周期(lifetime)的,变量的生存周期与变量声明时的作用域息息相关。其作用域销毁时,变量也就销毁了。
上面的例子主要有以下要点:
1. x是在foo函数内定义的,在foo的locals中存在,因此,其作用域是foo函数的作用域。
也就是说:foo运行时,locals创建,x位于locals中,结束后,foo的locals被销毁,x不在了。
2. #1处打印x,#1位于全局作用域,因此,其在globals中寻找x,没有找到,所以会报错。
函数参数与参量
函数的参数与参量也可称为函数的形参和实参(形参和实参的概念可以咨询查找学习)
Python中,函数运行时,其参数和参量实际上会成为local变量,存在于locals中。如下例子:
#!/usr/bin/env python def foo(x): print locals() foo(1)
结果为:
可以看到,形参x和运行时foo(1)的实参1都成了foo运行时的local变量
python有许多种定义函数形参和实参的方法,这里我就不具体说了,请参照:
https://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions
下面我再贴一个例子:
#!/usr/bin/env python def foo(x, y=0): # 1 return x - y print foo(3, 1) # 2 print foo(3) # 3 print foo(y=1, x=3) # 4 print foo() # 5
运行结果:
3
2
Traceback (most recent call last):
File "./7.py", line 12, in <module>
print foo() # 5
TypeError: foo() takes at least 1 argument (0 given)
可以看到#1处定义了x和y两个参数,y给了默认值0.
在函数调用中,#2,#3,#4都是没有问题的,只有#5报错了。也就是说:
1. 定义函数参数时,如果没有给某参数设定默认值,则在调用函数时,必须给该参数设定值。
2. 如果给某参数设定了默认值,则调用函数时,可以给该参数赋值,也可以忽略。
函数基础大概介绍到这里,关于嵌套函数、闭包等知识,我在另一个博文中介绍: