hug2wisdom / learnpython

note the points of learn python
0 stars 0 forks source link

Namespace & Scope #13

Open hug2wisdom opened 5 years ago

hug2wisdom commented 5 years ago
def test_scope():

    def do_local():
        spam = 'local'

    def do_nonlocal():
        nonlocal spam
        spam = 'nonlocal'

    def do_global():
        global spam
        spam = 'global'

    spam = 'test'

    do_local()
    print("After do_local the spam is {0}: ".format(spam))
    do_nonlocal()
    print("After do_nonlocal the spam is {0}: ".format(spam))
    do_global()
    print("After global the spam is {0}: ".format(spam))

test_scope()
print("the global spam is {0}".format(spam))

# result:

# After do_local the spam is test:
# After do_nonlocal the spam is nonlocal:
# After global the spam is nonlocal:
# the global spam is global

image

scope - Copy

hug2wisdom commented 5 years ago

Class

class Dog:
         tricks = []

这里的 tricks 是所有的实例所共有的,所有的变化都会记录在这里面。

class Dog:

    tricks = []             # mistaken use of a class variable

    def __init__(self, name):
        self.name = name

    def add_trick(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks                # unexpectedly shared by all dogs
['roll over', 'play dead']

这个一般不是我们所想要的,下面才是我们真正想要的“

class Dog:

    def __init__(self, name):
        self.name = name
        self.tricks = []    # creates a new empty list for each dog

    def add_trick(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']
hug2wisdom commented 5 years ago

Inheritance 继承

Python has two built-in functions that work with inheritance:

Use isinstance() to check an instance’s type: isinstance(obj, int) will be True only if obj.__class__ is int or some class derived from int. isinstance() 主要检查变量是什么类型 isinstance()会认为子类是一种父类类型 type()不会认为子类是一种父类类型 Python3 里的 Bool 型是 int 型的一个特例而不是一个独立的类型。 所以,isinstance(bool, int) is true

Useissubclass() to check class inheritance:issubclass(bool, int) is True since bool is a subclass of int. However, issubclass(float, int) is False since float is not a subclass of int.

hug2wisdom commented 5 years ago

多重继承

class DerivedClassName(Base1, Base2, Base3): 如果一个变量在 DerivedClassName 中找不到,那么就在 Base1 中找,再找不到,就在 Base1 的上一级找,找到此就不找了,如果没有,就去 Base2 中找。总之,规定是:先深度,再广度,不超两层。

For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy. Thus, if an attribute is not found in DerivedClassName, it is searched for in Base1, then (recursively) in the base classes of Base1, and if it was not found there, it was searched for in Base2, and so on.

hug2wisdom commented 5 years ago

变量作用域

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

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

L (Local) 局部作用域 E (Enclosing) 闭包函数外的函数中 G (Global) 全局作用域 B (Built-in) 内置作用域(内置函数所在模块的范围) 以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

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

hug2wisdom commented 5 years ago

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()

result: 100 100

hug2wisdom commented 5 years ago

特别注意:

a = 10
def test():
    a = a + 1
    print(a)
test()

这样会报错,因为在test()内,a 并没有定义,所以无法修改,但是如果是print(a)则是可以的 函数内可以访问全局变量,但不能更新(修改)其值

a = 10
def test(a):
    a = a + 1
    print(a)
test(a)

这样不会报错,因为全局作用的a作为实参传给了test()

hug2wisdom commented 5 years ago

nonlocal 只能修改外层函数的变量而不能修改外层函数所引用的全局变量,给一个例子如下:

x = 0
def outer():
    global x
    x = 1    
    def inner():
        nonlocal x
        x = 2        
        print(x)
    inner()

outer()
print(x)

结果会报错:

line 6
    nonlocal x
    ^
SyntaxError: no binding for nonlocal 'x' found