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

python-为什么hasattr在使用@property方法的类和实例上的行为有所不同?,第1张

概述我在类中使用@property实现了只写属性.奇怪的是,具有此属性的hasattr在类和相应实例上的行为不同.from werkzeug.security import generate_password_hash, check_password_hash from flask_login import UserMixin class User(Base

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

from werkzeug.security import generate_password_hash,check_password_hashfrom flask_login import UserMixinclass 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]: TrueIn [7]: u1=User()In [9]: hasattr(u1,'password')Out[9]: FalseIn [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.setterAttributeError: password is a write-only attribute!

根据getattr的结果,getattr(u1,’password’)尝试执行该方法并引发错误,而getattr(User,’password’)不执行@property方法.他们为什么表现不同?最佳答案除了@timgeb提到的内容外,背景中发生的事情比看上去要多得多.

属性被实现为描述符,并且当您使用对象和类访问属性时,属性查找的方式有所不同.当您使用obj.attr这样的对象访问属性时,基本上,属性查找的规则如下

>在__class __.__ dict__内部查找,查看此属性是否为数据描述符,如果是,则调用__get__,这将转换为type(obj).__ dict __ [‘attr’] .__ get __(obj,type(obj)).
>查看对象的__dict__并返回obj .__ dict __ [‘attr’]
>如果属性是非数据描述符,则调用其__get__,这将再次转换为type(obj).__ dict __ [‘attr’] .__ get __(obj,type(obj)).
>从类的__dict__获取属性.
>调用getattr的默认实现.

现在,当您尝试使用class.attr访问相同的属性时,将应用相同的规则,但略有不同,这次还涉及该类的元类,因此看起来

>元类是否为此属性定义了数据描述符,则在其上调用return type(class).__ dict __ [‘attr’] __ get __(class,type(class)).
>在类的__dict__内部查看,看看该属性是否是任何类型的描述符,则获取调用__get__的属性,如果不是描述符则从类的__dict__获取值.
>如果该属性是重要元素中的非数据描述符,请调用其__get__.
>从元类的__dict__获取属性.
>调用getattr的默认实现.

此外,针对属性的__get__的默认实现会检查一下,当您使用类访问属性时,它会返回描述符实例本身,但是,当您使用对象访问属性时,它实际上会触发__get__内部的代码.

def __get__(self,instnace,class):    if instance is None:        return self    else:        # code

这也解释了为什么hasattr(User,’password’)返回True的原因,因为由于您正在使用类调用该属性,否则else不会得到执行,因此不会引发异常,并且hasattr(u1,’password’)遇到时将返回False例外. 总结

以上是内存溢出为你收集整理的python-为什么hasattr在使用@property方法的类和实例上的行为有所不同? 全部内容,希望文章能够帮你解决python-为什么hasattr在使用@property方法的类和实例上的行为有所不同? 所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1199598.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存