【问题标题】:Prevent creating new attributes for class or module防止为类或模块创建新属性
【发布时间】:2020-04-10 02:01:08
【问题描述】:

我在 SO Prevent creating new attributes outside init 上看到了这个问题,它展示了如何防止向类的对象添加新属性。

我希望整个类甚至整个加载的模块都具有相同的行为。

示例类:

class Klass:
     a = 0
     b = 1

另一个模块:

from Klass import Klass

Klass.c = 2 # this should raise an error

这可能吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    如果您试图阻止修改类本身,您可以创建一个为该类定义 __setattr__ 方法的元类。

    class FrozenMeta(type):
        def __new__(cls, name, bases, dct):
            inst = super().__new__(cls, name, bases, {"_FrozenMeta__frozen": False, **dct})
            inst.__frozen = True
            return inst
        def __setattr__(self, key, value):
            if self.__frozen and not hasattr(self, key):
                raise TypeError("I am frozen")
            super().__setattr__(key, value)
    
    class A(metaclass=FrozenMeta):
        a = 1
        b = 2
    
    A.a = 2
    A.c = 1 # TypeError: I am frozen
    

    【讨论】:

    • 这在课堂上按预期工作!太糟糕了,整个模块都没有东西
    • @RoQuOTriX:查看this answer 了解将类变成模块的方法。
    【解决方案2】:

    slots 的答案是 Pythonic 方式。

    class Klass:
        __slots__ = ['a', 'b']
    
        def __init__(self, a=0, b=1):
            self.a = a
            self.b = b
    
    >>> k = klass.Klass()
    >>> k.a
    0
    >>> k.b
    1
    >>> k.c = 2
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Klass' object has no attribute 'c'
    >>>
    

    【讨论】:

    • 但是你仍然可以做 Klass.c=2 然后 k 也会有 c
    • __slots__ 并非旨在防止创建属性,这只是一个副作用。
    猜你喜欢
    • 2011-09-06
    • 2015-10-02
    • 2014-09-26
    • 2011-04-05
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多