python - 实例和类变量的实现
问题描述
我很好奇Python的类和实例变量的实现。我在文档中找不到答案,坦率地说,我并不想深入了解所有 Python 源代码。
这些属性可以总结如下:
- 更改类变量会更改所有类实例的此属性
- 更改实例变量会覆盖类变量
这在下面演示
>>> class cA:
... pub = "public"
... def __init__(self):
... self.priv = "private"
...
>>> aI = cA()
>>> bI = cA()
>>> aI.pub; bI.pub
'public'
'public'
>>> cA.pub = "public2"
>>> aI.pub; bI.pub
'public2'
'public2'
>>> aI.pub = "public3"
>>> aI.pub; bI.pub
'public3'
'public2'
>>> # Oh no!
我的问题是:这是如何完成的(相关的实现细节是什么)?
以下是我的假设和推理。
重新启动一切并检查实例的命名空间,看起来它们每个都包含对 object 的直接引用pub
,并且检查内存位置告诉我们它们确实指向同一个对象:
>>> aI = cA()
>>> bI = cA()
>>> dir(aI)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'priv', **'pub'**]
>>> dir(bI)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'priv', **'pub'**]
>>> id(aI.pub); id(bI.pub)
4466990384
4466990384
检查类本身的命名空间,我们pub
在这里也看到:
如果aI
并且bI
确实包含对该对象的直接引用,那么对该对象的任何更改(创建新对象)都必须将新对象放在同一位置,以便 aI.pub 正确解析。但是,我们看到情况并非如此:
>>> id(cA.pub)
4466990384
>>> cA.pub = "public2 I'm making this longer to avoid interning effects"
>>> id(cA.pub)
4467260752
>>> id(aI.pub); id(bI.pub)
4467260752
4467260752
现在,由于我们没有修改任何aI
内存,我们只能假设它pub
实际上不dir
包含对类变量的引用pub
。
我的假设(请确认/拒绝)是实例不包含任何实际将它们连接到类变量的东西,每个实例都有一个类字典,然后是一个字典,并且当访问类变量时会发生什么是本地解析失败,它会上升层次结构(下一行是类dict),然后解析引用并访问对象(引用到类→引用到对象→对象),即
cADict = {reference to pub object}
aIDict = {reference to priv object, to class}
(aI
实际上确实包含对 pub 对象的直接引用的替代方案将要求每次更新类实例时都必须遍历该类的所有实例并更新它们的 pub 引用 - 这是不切实际的)
对我的原作的跟进:看到 aspub
实际上不在aI
's 的命名空间中,为什么dir()
说它在?
(我认为dir
打印对象命名空间中所有引用的列表?)
解决方案
推荐阅读
- javascript - 我在 Firebase Cloud 功能中使用 FFMPEG 转换的文件不可访问
- python - 模块调用错误。不能循环输入功能
- c - 如何修改函数内部的多维指针?
- javascript - 如何使用javascript将html页面转换为pdf
- python-3.x - 我想通过多行输入来提高算法的速度。Python。查找列表中连续元素的平均值
- javascript - 产生一个进程返回不明错误和选项列表?
- c++ - 通过引用和并行使用 qml 从另一个 QObject 类访问 QObject 类
- firebase - firebase 使用用户昵称或用户 ID?
- c# - 如何使用反射获取属性?
- angular - 让 NGX 翻译在 NX 工作区库中工作