您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

被属性遮盖时修改类__dict__

被属性遮盖时修改类__dict__

可能是最好的方法:选择另一个名称调用属性x和dict键'_x',以便您可以通过常规方式访问它。

另一种方法添加另一层间接:

class Meta(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        attrs['x'] = [0]
        return super().__new__(cls, name, bases, attrs)
    @property
    def x(cls):
        return cls.__dict__['x'][0]

class Class(Metaclass=Meta):
    def __init__(self):
        self.id = __class__.x
        __class__.__dict__['x'][0] += 1

这样,您不必修改类dict中的实际条目。

可能会彻底隔离您的Python的超级骇客方式:通过gc模块访问基础dict 。

import gc

class Meta(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        attrs['x'] = 0
        return super().__new__(cls, name, bases, attrs)
    @property
    def x(cls):
        return cls.__dict__['x']

class Class(Metaclass=Meta):
    def __init__(self):
        self.id = __class__.x
        gc.get_referents(__class__.__dict__)[0]['x'] += 1

这绕过type.__setattr__了维护内部不变性的关键工作,尤其是在诸如cpython的类型属性缓存之类的事情中。这是一个糟糕的主意,我只在提及它,以便在此处提出此警告,因为如果有人提出了此警告,那么他们可能不知道弄乱基础的命令是合法的危险。

以悬挂的引用完成此操作非常容易,而且我已经多次尝试使用Python进行段隔离。这是一个在Ideone崩溃的简单案例:

import gc

class Foo(object):
    x = []

Foo().x
gc.get_referents(Foo.__dict__)[0]['x'] = []

print(Foo().x)

输出

*** Error in `python3': double free or corruption (fasttop): 0x000055d69f59b110 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x2b32d5977bcb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x2b32d597df96]
/lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x2b32d597e78e]
python3(+0x2011f5)[0x55d69f02d1f5]
python3(+0x6be7a)[0x55d69ee97e7a]
python3(PyCFunction_Call+0xd1)[0x55d69efec761]
python3(PyObject_Call+0x47)[0x55d69f035647]
... [it continues like that for a while]

这里的情况错误的结果并没有嘈杂的错误消息,提醒您的是什么地方出了错误的事实:

import gc

class Foo(object):
    x = 'foo'

print(Foo().x)

gc.get_referents(Foo.__dict__)[0]['x'] = 'bar'

print(Foo().x)

输出

foo
foo

我绝对不保证使用此方法的任何安全方法,即使在一个Python版本上发生了问题,它们也可能在将来的版本上不起作用。弄弄它可能很有趣,但是实际上并没有用。说真的,不要这样做。您是否 向老板解释您的网站已关闭,或者因为您接受并使用了这个错误的主意而需要撤消已发布的数据分析?

其他 2022/1/1 18:48:28 有305人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶