繁体   English   中英

不可更改的 Python 类实例属性

[英]Unchangeable Python Class Instance Attribute

所以我一直在阅读描述符以试图更好地了解它们的工作原理,虽然我知道你不能真正禁止 Python 中的东西,但灯泡亮了,我想到了这个想法(我记得阅读过实例绑定描述符在这里并借用了实现):

class Immutable:
    __slots__ = "name"

    def __init__(self, name):
        def name_setter(obj, val):
            print("Cannot change name!")
        self.name = property(lambda obj: name, name_setter)

    def __setattr__(self, attr, value):
        try:
            # Try invoking the descriptor protocol __set__ "manually"
            got_attr = super().__getattribute__(attr)
            got_attr.__set__(self, value)
        except AttributeError:
            # Attribute is not a descriptor, just set it:
            super().__setattr__(attr, value)

    def __getattribute__(self, attr):
        # If the attribute does not exist, super().__getattribute__()
        # will raise an AttributeError
        got_attr = super().__getattribute__(attr)
        try:
            # Try "manually" invoking the descriptor protocol __get__()
            return got_attr.__get__(self, type(self))
        except AttributeError:
            # Attribute is not a descriptor, just return it:
            return got_attr


mark = Immutable("Mark White")
print(mark.name)

mark.name = "test1"
print(mark.name)

setattr(mark, "name", "test2")
print(mark.name)

mark.__setattr__("name", "test3")
print(mark.name)

jon = Immutable("Jon Snow")
print(jon.name)
print(mark.name)


输出:

Mark White
Cannot change name!
Mark White
Cannot change name!
Mark White
Cannot change name!
Mark White
Jon Snow
Mark White

这个想法是,这限制了 name 属性被更改,因为它是作为属性创建的,其 setter 是 __init__ 中定义的函数。 此外,自定义 __setattr__ 和 __getattribute__ 函数允许描述符被实例绑定。 所以这个值是在创建对象时设置的,就是这样。 由于__slots__被定义,甚至__dict__也不能改变。

所以我的问题是:

我是不是没有看到非常明显的东西,或者这个属性真的不能改变吗?

不,这个属性肯定是可变的:

object.__setattr__(mark, 'name', 'Foo')

将成功设置名称。

不确定“实例绑定”描述符的意义是什么。 这永远不会通过任何理智的代码审查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM