簡體   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