【问题标题】:Unchangeable Python Class Instance Attribute不可更改的 Python 类实例属性
【发布时间】:2021-09-05 07:53:51
【问题描述】:

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

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__ 也无法更改。

所以我的问题是:

我没有看到非常明显的东西还是这个属性真的不可改变?

【问题讨论】:

    标签: python


    【解决方案1】:

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

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

    将成功设置名称。

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

    【讨论】:

    • 啊,就是这样。父母的类 setattr 会起作用是有道理的。也不太确定实例绑定描述符。我只记得不久前偶然发现了那篇文章,然后又查了一遍。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2011-11-24
    相关资源
    最近更新 更多