作用域

一个标识符的可见范围 这就是标识符的作用域。一般常说的是变量的

  • 全局作用域
  • 在整个程序运行环境中都可见
  • 局部作用域
  • 在函数、类等内部可见
  • 局部变量使用范围不能超过其所在的局部作用域

全局变量global

x = 5
def foo():
    global x
    x += 1

使用global关键字的变量 将foo内的x声明为使用外部的全局作用域中的定义的x
全局作用域中必须有x的定义

def foo():
    global x
    x = 10
    x += 1 # 不报错
    print(x) # 打印11

foo()
print(x)

使用gloval关键字的变量 将foo内的x声明为使用外部的全局作用域中定义的x
但是 x=10 赋值即定义 在内部作用域为一个外部作用域的变量x赋值 不是在内部作用域定义一个新变量 所以x += 1 不会报错 注意 这里x的作用域还是全局的

x = 5
def foo():
    global x
    x = 10
    x += 1
    print(x) #打印11

foo()
print(x) 打印11

总结

  • x+=1这种是特殊形式产生的错误的原因?先引用后赋值,而python动态语言是赋值才算定义,才能被引用。解决办法,在这条语句前增加x-0之类的赋值语句,或者使用global告诉内部作用域,去全局作用域查找变量定义
  • 内部作用域使用x =5之类的赋值语句会重新定义局部作用域使用的变量x,但是,一旦这个作用域中使用global声明x为全局的,那么x=5相当于在为全局作用域的变量x赋值

Global使用原则

  • 外部作用域变量会内部作用域可见,但也不要在这个内部的局部作用域中直接使用,因为函数的目的就是为了封装,尽量与外界隔离
  • 如果函数需要使用外部全局变量,请使用函数的形参传参解决
  • 一句话:不用global,学习它就是为了深入理解变量作用域

nonlocal关键字

def counter():
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc

foo = counter()
print(foo()) 打印1
print(foo()) 打印2
a = 50
def counter():
    nonlocal a
    a += 1
    print(a)
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc

foo = counter()
print(foo())
print(foo())

使用nonlical 变量a不能在全局作用域中


闭包

自由变量:未在本地作用域中定义的变量。例如定义在内存函数外的外层函数的作用域中的变量

闭包:就是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包。很多语言都有这个概念,最熟悉就是JavaScript


变量名解析原则LEGB

  • Local,本地作用域、局部作用域的local命名空间。函数调用时创,建,调用结束消亡
  • Enclosing , Python2.2时引入了嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间,
  • Global,全局作用域,即一个模块的命名空间。模块被import时 !在内置变量名模块中之定义 : pin ang Sntaro..创建,解释器退出时消亡,
  • Build-in ,内置模块的命名空间,生命周期从python解释器启动:时创建到解释器退出时消亡。例如print(open) , print和open都是内置的变量

所以一个名词的查找顺序就是LEGB

之字形打印矩阵元素

打印矩阵元素
 1   2   6   7
 3   5   8   13
 4   9   12  14
 10  11  15  16
之字形打印结果为1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16

思路

0,0  
0,1 1,0   
2,0 1,1 0,2  
0,3 1,2 2,1 3,0  
3,1 2,2 1,3   i =1  sum = 4  j =0 1 2
2,3 3,2    i ==2   sum =5  j =0 1
3,3  i ==3  sum =6  j = 0

计算从1到16的坐标发现规律如上


lst = [[1,2,6,7],[3,5,8,13],[4,9,12,14],[10,11,15,16]]
sum = -1
for i in range(-3,4):
    sum += 1
    for j in range(4-abs(i)):
        if i < 1 and i % 2 == 0:
            print(lst[j][sum-j])
        else:
            if i < 1:
                print(lst[sum-j][j])
            else:
                if i % 2 == 0:
                    print(lst[i+j][sum-i-j])
                else:
                    print(lst[sum -i-j][i+j])

扩展为5*5的矩阵

01 02 06 07 15
03 05 08 14 16
04 09 13 17 22
10 12 18 21 23
11 19 20 24 25

00
01 10
20 11 02
03 12 21 30
40 31 22 13 04
14 23 32 41
42 33 24
34 43
44

规律如上 由此改进代码 发现通常规律


lst = [[1,2,6,7,15],[3,5,8,14,16],[4,9,13,17,22],[10,12,18,21,23],[11,19,20,24,25]]
sum = -1
for i in range(-len(lst)+1,len(lst)):
    sum += 1
    for j in range(len(lst)-abs(i)):
        if i < 1 and i % 2 == 0 :
            print(lst[sum - j][j])
        else:
            if i < 1:
                print(lst[j][sum - j])
            else:
                if i % 2 == 0:
                    print(lst[sum - i - j][i + j])
                else:
                    print(lst[i + j][sum - i - j])

01 02 06 07 15 16
03 05 08 14 17 26
04 09 13 18 25 27
10 12 19 24 28 33
11 20 23 29 32 34
21 22 30 31 35 36

lst = [[1,2,6,7],[3,5,8,13],[4,9,12,14],[10,11,15,16]]
lst = [[1,2,6,7,15],[3,5,8,14,16],[4,9,13,17,22],[10,12,18,21,23],[11,19,20,24,25]]
lst = [[1,2,6,7,15,16],[3,5,8,14,17,26],[4,9,13,18,25,27],[10,12,19,24,28,33],[11,20,23,29,32,34],[21,22,30,31,35,36]]
sum = -1
k = len(lst) % 2
for i in range(-len(lst)+1,len(lst)):
    sum += 1
    for j in range(len(lst)-abs(i)):
        if i < 1 and i % 2 != k:
            print(lst[sum - j][j])
        else:
            if i < 1 :
                print(lst[j][sum - j])
            else:
                if i % 2 != k:
                    print(lst[sum - i - j][i + j])
                else:
                    print(lst[i + j][sum - i - j])

由此得出适用于各个规格矩阵的之字形打印代码