文章目录
global与nonlocal
1.函数内部定义的为局部变量,其作用域是局部作用域,函数外无法调用的
2.函数外定义的为全局变量,其作用域是全局作用域,如果在函数内想要进行修改,需要使用global修饰变量
3.外层函数的变量,如果想要在内层函数进行修改,需要nonlocal
关于这部分,有一篇博文写得很详细,通过看他的这篇博文,我已经看懂了两个修饰词的作用。
python:函数作用域 global与nonlocal
大家感兴趣的可以去看看。上一段我修改过的代码:
span = '123'
def scope_test():
def do_local():
spam = "local spam"
span = 'local'
def do_nonlocal():
nonlocal spam
global span
spam = "nonlocal spam"
span = "global"
def do_global():
global spam
global span
span = 'global'
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam, span)
do_global()
print("After global assignment:", spam, span)
do_nonlocal()
print("After nonlocal assignment:", spam, span)
scope_test()
print("In global scope:", spam, span)
这是对网上的一段代码进行了改进,别人的那个示例按照顺序,容易误导别人。大家关注我这里do_global和do_nonlocal的调用顺序。
运行结果:
刚开始看别人的代码,我很疑惑,为什么别人的运行结果,调用了global,结果还是nonlocal,见下图:
后面仔细理解才发现,因为没有全局变量spam,所以执行了global修饰的spam,并没有什么作用。而是直接打印了spam,由于上一次执行了nonlocal spam,所以spam的结果是nonlocal spam。
然后我的代码里面,do_nonlocal也是用的global span,而不是用nonlocal span,是因为没有局部变量span,编译会报错。
这里说明一个问题,global 修饰的变量可以不存在,编译不会报错,nonlocal修饰的变量必须要存在,否则编译会报错。
下面用一段代码验证:
str1 = '123'
def test1():
def test2():
nonlocal str2
str2 = 'str2_test2'
print(str2)
nonlocal str1
str1 = 'str1_test2'
print(str1)
def test3():
global str1
str1 = 'str1_test3'
print(str1)
global str2
str2 = 'str1_test3'
print(str2)
str2 = '456'
test3()
test2()
编译报错:
表示str1不能用nonlocal修饰。
str1 = '123'
def test1():
def test2():
nonlocal str2
str2 = 'str2_test2'
print('str2 = ', str2)
global str1
str1 = 'str1_test2'
print('str1 = ', str1)
def test3():
global str1
str1 = 'str1_test3'
print('str1 = ', str1)
global str2
str2 = 'str2_test3'
print('str2 = ', str2)
str2 = '456'
test3()
print("After global assignment:", str1, str2)
test2()
print("After nonlocal assignment:", str1, str2)
test1()
这段代码把test2里面的nonlocal str1改成了global str1,然后输出也加了打印语句,运行结果:
因为先调用test3,使用了global str2,并且str2 = ‘str2_test3’,但是在运行以后,打印出来的str2任然是456,这就说明了,global修饰了str2,但是没有全局str2,编译不会报错,运行也不会报错。
再次调用test3,结果为:str2_test2,并没有对str2的值有改变。
继承和多态
划重点:
Python 中所有的方法实际上都是 virtual 方法。
这和其他语言不一样。
class CA:
def myPrint(self):
print('这是CA')
class CB(CA):
def myPrint(self):
CA.myPrint(self)
print(' 这是CB')
class CC(CA):
def myPrint(self):
CA.myPrint(self)
print(' 这是CC')
ca = CA()
cb = CB()
cc = CC()
def runTest(ca):
ca.myPrint()
for item in [ca, cb, cc]:
runTest(item)
运行结果:
这里体现了子类中重载函数时,可以先调用基类中的方法,然后再继续实现自己的功能。
除了单重集成以外,还可以有多重继承,原理和单重继承一样,这里就不再细说了。