gpt4 book ai didi

python - __setattr__ 如何处理类属性?

转载 作者:行者123 更新时间:2023-12-01 07:04:14 26 4
gpt4 key购买 nike

我试图了解 __setattr__ 如何与类属性一起工作。当我试图覆盖 __setattr__ 以防止在简单类中写入属性时,这个问题就出现了。

我的第一次尝试使用了实例级属性,如下所示:

class SampleClass(object):

def __init__(self):
self.PublicAttribute1 = "attribute"

def __setattr__(self, key, value):
raise Exception("Attribute is Read-Only")

我原本以为只有外部尝试设置属性才会抛出错误,但即使是 __init__ 内部的语句也会导致抛出异常。

后来我最终找到了另一种方法来做到这一点,同时试图解决一个不同的问题。我最终得到的是:
class SampleClass(object):
PublicAttribute1 = "attribute"

def __setattr__(self, key, value):
raise Exception("Attribute is Read-Only")

我希望得到相同的结果,但令我惊讶的是,我能够设置类属性,同时防止在初始声明后进行更改。

我不明白为什么这行得通。我知道这与类与实例变量有关。我的理论是在类变量上使用 __setattr__ 会创建一个同名的实例变量,因为我相信我认为我以前见过这种行为,但我不确定。

谁能准确解释这里发生了什么?

最佳答案

__setattr__()仅适用于类的实例。在您的第二个示例中,当您定义 PublicAttribute1 ,你在类上定义它;没有实例,所以__setattr__()不叫。

注:在 Python 中,您使用 . 访问的内容符号称为属性,而不是变量。 (在其他语言中,它们可能被称为“成员变量”或类似名称。)

如果您在实例上设置同名属性,则类属性将被隐藏是正确的。例如:

class C(object):
attr = 42

c = C()
print(c.attr) # 42
c.attr = 13
print(c.attr) # 13
print(C.attr) # 42

Python 通过首先查看实例来解析属性访问,如果实例上没有该名称的属性,它会查看实例的类,然后是该类的父类,依此类推,直到它到达 object。 , Python 类层次结构的根对象。

所以在上面的例子中,我们定义 attr在类里面。因此,当我们访问 c.attr (实例属性),我们得到 42,类上的属性值,因为实例上没有这样的属性。当我们设置实例的属性,然后打印 c.attr再次,我们得到了我们刚刚设置的值,因为现在实例上有一个该名称的属性。但是值 42仍然作为类的属性存在, C.attr ,正如我们在第三个 print 中看到的那样.

在您的 __init__() 中设置实例属性的语句方法由 Python 处理,就像在对象上设置属性的任何代码一样。 Python 不关心代码是在类“内部”还是“外部”。所以,你可能想知道,如何绕过 __setattr__()的“保护”?初始化对象时?很简单:您调用 __setattr__()没有这种保护的类的方法,通常是你的父类的方法,并将它传递给你的实例。

所以不要写:
self.PublicAttribute1 = "attribute"

你必须写:
 object.__setattr__(self, "PublicAttribute1", "attribute")

由于属性存储在实例的属性字典中,命名为 __dict__ ,你也可以绕过你的 __setattr__通过直接写信:
 self.__dict__["PublicAttribute1"] = "attribute"

这两种语法都是丑陋而冗长的,但是您可以相对轻松地破坏您尝试添加的保护(毕竟,如果您可以这样做,其他任何人也可以)可能会导致您得出 Python 没有的结论对 protected 属性有很好的支持。事实上它没有,这是设计使然。 “我们都是同意这里的成年人。”你不应该考虑 Python 的公共(public)或私有(private)属性。所有属性都是公开的。有一个使用单个前导下划线命名“私有(private)”属性的约定;这会警告任何使用您的对象的人他们正在搞乱某种实现细节,但如果他们需要并且愿意接受风险,他们仍然可以这样做。

关于python - __setattr__ 如何处理类属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39708662/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com