防止为类或模块创建新属性
Posted
技术标签:
【中文标题】防止为类或模块创建新属性【英文标题】: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
这可能吗?
【问题讨论】:
【参考方案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__
并非旨在防止创建属性,这只是一个副作用。以上是关于防止为类或模块创建新属性的主要内容,如果未能解决你的问题,请参考以下文章