python - 为什么 hasattr 在使用 @property 方法的类和实例上表现不同?

标签 python python-decorators readonly-attribute writeonly

我在我的类中使用@property 实现了一个只写 属性。奇怪的是 hasattr 在具有此属性的类和相应实例上的行为不同。

from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin


class User(Base, UserMixin):
    # codes omitted...

    @property
    def password(self):
        raise AttributeError("password is a write-only attribute!")

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)
In [6]: hasattr(User,'password')
Out[6]: True

In [7]: u1=User()

In [9]: hasattr(u1,'password')
Out[9]: False

In [12]: getattr(User,'password')
Out[12]: <property at 0x1118a84a8>

In [13]: getattr(u1,'password')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-b1bb8901adc7> in <module>
----> 1 getattr(u1,'password')

~/workspace/python/flask_web_development/fisher/app/models.py in password(self)
     82     @property
     83     def password(self):
---> 84         raise AttributeError("password is a write-only attribute!")
     85
     86     @password.setter

AttributeError: password is a write-only attribute!

getattr 的结果来看,getattr(u1, 'password') 尝试执行该方法并引发错误,而 getattr(User, ' password') 不执行 @property 方法。为什么他们的行为不同?

最佳答案

属性是 descriptors .


关于getattr:

当您通过 getattr 或对象上的点符号 (u1) 和该对象的类 (User) 访问属性时) 恰好有一个描述符以您尝试访问的名称命名,该描述符的 __get__ 方法称为 1,就像您发出 getattr(u1, '密码')。在您的特定情况下,您在 getter 中定义的逻辑(引发 AttributeError)将被执行。

使用 getattr(User, 'password') 传递给 __get__ 方法的实例是 None,在这种情况下 __get__ 只返回描述符本身,而不是执行您实现的 getter 逻辑。

1如 Descriptor HowTo 中所述,根据您拥有的是数据还是非数据描述符,有一些特殊规则。


关于hasattr:

hasattr(u1, 'password') 返回 False 因为 getattr(u1, 'password') 引发错误。参见 this问题。

关于python - 为什么 hasattr 在使用 @property 方法的类和实例上表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55118728/

相关文章:

python - 使用任何脚本语言(perl、python 或 shell 脚本)查找范围内的缺失值

python - 在 sqlalchemy 字段中将值强制为大写的最佳方法

python - 如何使用 NumPy 通过相应的索引在列表列表中查找最大值

Python,装饰函数中引用类实例/方法

asp.net - 无法获取asp.net中只读文本框的值

python - 如何在 celery 中安排工作日感知工作

在加载/导入时执行的 Python 装饰器

python - 创建一个在 Python 中打印整数的装饰器

java - 限制或阻止方法的实现