多态

在python中,一切皆对象,包括函数也是对象。因为python是动态类型的语言,所以它的多态实现非常容易。比如下面这个例子,一个操作的意义取决于被操作对象的类型。

def func(a,b):
    return a * b

test1 = func(12,5)
print(test1) #60

test2 = func('ad',5)
print(test2) #adadadadad

而所谓多态就是对不同类型的对象执行相同的操作,这些操作都能根据自己的类型来正常的运行。

变量作用域

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量。python的作用域一共有4种,分别是:

L(Local)局部作用域

E(Encoding)闭包函数外的函数中

G(Global)全局作用域

B(Built-in)内置作用域(内置函数所在模块的范围)

以L->E->G->B的规则查找,及局部找不到,便会在局部外的局部找,再找不到就去全局了,最后在内置中找。

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问。

内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。

下面我们来说说LEG三种。

x = 66
def func(a):
    x = a
    print(x)
    return x
func(99)  #99
print(x)  #66

从上例可以看到,第一次输出本地变量覆盖了全局变量,而第二次输出的就是全局变量,因为在调用完func函数之后,x并没有保存起来,随着函数调用的结束,局部变量的X就消失了。

那么如果我想在函数内部修改函数外部声明的值,就需要用到global和nonlocal关键字了。

x = 66
def func():
    global x
    x = 99
    print(x)
func()    #99
print(x)  #99

关键字global是一个变量命名空间的声明,它告诉python函数打算生成一个或多个全局变量,应用它,就可以在函数内部对全局变量进行引用和修改。如上例,两次的输出都是99。

嵌套函数

x = 88
def func():
    x = 99
    def func1():
         x =77
         print(x)
    return func1

test = func()
test()   #77

如上例所示,在def函数中再嵌套另一个def函数,就是所谓的嵌套函数,而且最终输出的是77。而且本例还有一个特别的地方,前面的例子中,函数的调用结束后,本地作用域就会马上失效,而嵌套作用域在嵌套的函数返回后却仍然有效。

上面这种语言现象叫做闭包:一个能记住嵌套作用域变量值的函数,尽管作用域已经不存在。

def func(x):
    k = 10
    def func1(n):
         return n ** x + k
    return func1

test = func(2)
print(test(4))  #26

这里我们可以看出,内嵌的函数func1记住了嵌套作用域内得两个嵌套变量,一个是变量k,一个是参数x,即使后面func1返回并退出。我们通过调用外部的函数func,得到内嵌的函数func1的引用。这种函数嵌套的方法在后面要介绍的装饰器中会经常用到。这种嵌套作用域引用,就是python的函数能够保留状态信息的主要方法了。

那么如何修改嵌套作用域中的变量呢?这个时候就需要nonlocal关键字了!

def func(num):
    k = num
    def func1(label):
         nonlocal k
         k += 1
         print(label,k)
    return func1
f = func(0)  #100,100
f('a')  #a 1
f('b')  #b 2

我们在func1函数中通过nonlocal关键字引用了内嵌作用域中的变量k,那么我们就可以在func1函数中修改他,即使func函数已经退出调用,这个“记忆”依然有效。

http://www.runoob.com/python3/python3-function.html

https://zhuanlan.zhihu.com/c_147297848