代码之家  ›  专栏  ›  技术社区  ›  Indominus

python3中的can instance属性不可变

  •  1
  • Indominus  · 技术社区  · 7 年前

    我想在 __init__ 然后不允许对其进行任何更改。在python oop中有这样的机制吗?更具体地说,我使用的是Python3.7。

    在你把它当作复制品投反对票之前,请注意我所说的是 instance attribute 而不是 class instance 他们自己也喜欢类似的题目。

    1 回复  |  直到 7 年前
        1
  •  1
  •   gilch    7 年前

    有多种选择,具体取决于你想做什么。

    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
    

    从这篇文章开始,这应该是有效的,但是 键入扩展名 仍然是实验性的,可能会改变。guido自己一直在研究mypy,所以它可能最终会出现在标准库中。 typing 模块。

    2。@房产

    也可以使用财产(可以规避,但可能不会发生意外)。--

    没有二传手。您仍然需要将变量存储在某个地方。也许与 _ -前缀名,或在闭包中,或直接在实例dict上使用 vars (将绕过描述符函数 @property )

    class Spam:
        def __init__(self, foo):
            vars(self)['foo'] = foo
        @property
        def foo(self):
            return vars(self)['foo']
    

    或者使用一个setter来检查它是否已经设置,如果已经设置则引发异常。这可以让您第一次用普通语法设置它,但是如果您设置它,可能不值得麻烦。 __init__ .

    三。子类元组

    继承自 tuple . 你得用 __new__ 而不是 爱因斯坦 . 您得到了真正的不变性,但这些本身不再是属性,您必须使用整数下标访问它们。( 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 .