python笔记 类作用域下

77 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

0 环境

  • 编辑器:pycharm或者vscode
  • 系统版本:windows10
  • python版本:3.9.6

1 作用域

实例对象.类变量或者自定义个属性名字 = 新值,之后测试会发生其他实例或类访问类变量和你实例修改过的类变量,最终的值是不一样的,侧面说明了,赋值了就是重新创建了。那它们到底存放在哪里的呢,或者谁记录了这些值。如下代码:

如下该d实例,d.NAME和d.class.NAME的结果是一样的。这里的d.class.NAME是我们的class属性,所有的类变量都是存放在<实例名>..class.<类变量>中。

class Demo:
    NAME = "A"

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

if __name__ == '__main__':
    d = Demo("a")
    print(d.NAME)
    print(d.__class__.NAME)

image.png

既然类变量有专门的地方存放了,那么实例变量应该也有吧,打印d1.dict,确实我们的NAME在其中的,那么我们要确实它是不是类变量,还是实例变量,现在打印,还不确定,是不是就可以调用这两个__class____dict__得到结果,就知道了。

class Demo:
    NAME = "A"

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

if __name__ == '__main__':
    d1 = Demo("b")
    d1.NAME = "B"
    print(d1.NAME)
    print(d1.__dict__)

image.png

当我用实例给类变量重新赋值了,并且在__dict__可以看到该NAME的类变量的键值,并且__class__.__dict__里也有类变量的值,最终的结果:打印出来的是我们重新赋值的那个值,而类变量并且被使用,也就说明,当我实例定义类变量同名并且赋值了,或者说是我用当前实例重新给类变量重新赋值了,也就说该重新赋值的变量,被放在__dict__中,而当我们使用实例.类变量时,就会得到重新赋值的值,而当我们实例没有对类变量进行赋值或者说没有对它操作(该实例中__dict__中没有同名的类变量),那么会得到__class__.__dict__里存放的类变量的值。也就说:当我们实例.类变量时,会先到该实例的__dict__中找,有这个类名?有,返回,没有继续到__class__.__dict__里找,有返回,没有报错。 image.png

可以这样理解,当然写的不严谨,不要纠结,理解其中意思就行,当我的实例有该同名的类变量,这里的key可以看作是定义的类变量名,返回实例.__dict__[key]的值,假如出现异常了,说明没有找到,那么我到实例.__class__.__dict__[key]再去找,类属性里有,很好直接返回出去,没有抛出异常。

try:
    return 实例.__dict__[key]
except Exception:
    try:
        return 实例.__class__.__dict__[key]
    except Exception:
        异常处理

2 总结

当我们知道实例.__dict__实例.__class__.__dict__[key],存在的是什么变量,以及它们的执行优先顺序,一旦知道这个规则后,再去看它是不是实例变量和类变量,是不是就很清晰,没有搞混肴了。