我想在__init__
中设置一个实例属性,然后禁止对其进行任何更改。 Python OOP中是否有这样的机制?更具体地说,我正在使用Python 3.7。
在您否决它作为重复项之前,请注意,我所谈论的是instance attribute
的不变性,而不是class instance
本身的不变性,就像建议的类似问题标题所问的那样。
答案 0 :(得分:1)
有多种选择,具体取决于您要执行的操作。
使用mypy和Final
中的typing_extensions
类型。仅使用mypy进行静态检查,而不是在运行时强制执行。
$ pip install typing_extensions
from typing_extensions import Final
class Spam:
foo: Final[int]
def __init__(self, foo):
self.foo = foo
这在撰写本文时应该可以使用,但是typing_extensions
仍处于试验阶段,并且可能会发生变化。 Guido本人一直在研究mypy,因此它甚至可能最终出现在标准库typing
模块中。
也使用属性(可以绕开,但可能并非偶然)-
没有二传手。您仍然必须将变量存储在某个地方。也许使用_
前缀的名称,或者在闭包中,或者直接在实例字典上使用vars
(这将绕过@property
的描述符函数)。
class Spam:
def __init__(self, foo):
vars(self)['foo'] = foo
@property
def foo(self):
return vars(self)['foo']
或使用setter来检查它是否已设置,并引发异常。这样一来,您就可以使用常规语法进行首次设置,但是如果您在__init__
中进行设置,则可能不值得花时间。
继承自tuple
。您必须使用__new__
而不是__init__
。您获得了真正的不变性,但是这些本身不再是属性,您必须使用整数下标(self[0]
等)来访问它们。从tuple
继承意味着您也可以获取所有元组方法,而这可能是您不想要的。
如果您仍然希望访问点,则可以尝试创建collections.namedtuple
并从中继承。
from collections import namedtuple
class Spam(namedtuple('Spam', 'foo')):
def __new__(cls, foo):
return super().__new__(cls, foo)
def print_foo(self):
print(self.foo)
当然,您可以通过这种方式继承更多的方法。
另请参见typing.NamedTuple
。