• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
python属性描述符和属性查找过程
# ############### 定义 ###############
class Goods(object):

    @property
    def price(self):
        print '@property'

    @price.setter
    def price(self, value):
        print '@price.setter'

    @price.deleter
    def price(self):
        print '@price.deleter'

# ############### 调用 ###############
obj = Goods()

obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值

obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数

del obj.price      # 自动执行 @price.deleter 修饰的 price 方法

 

from datetime import date, datetime
import numbers
import string

#数据描述符
class IntField:
    #数据描述符
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        if not isinstance(value, numbers.Integral):
            raise ValueError("int value need")
        if value < 0:
            raise ValueError("positive value need")
        self.value = value
    def __delete__(self, instance):
        pass

#非数据描述符
class NonDataIntField:
    #非数据属性描述符
    def __get__(self, instance, owner):
        return self.value

 

第一种情况:

class User:
    age = IntField()
if __name__ == "__main__":
    user = User()
    user.age = 30
    print (user.age)
    print (user.__dict__)//此处输出的是{}
    user.__dict__['age'] = '29'
    print (user.age)
    print (user.__dict__['age'])

 

 输出: 

30
{}
30
29

print (user.__dict__) 是 {}呢?

 

原理如下:

  

如果user是某个类的实例,那么user.age(以及等价的getattr(user,’age’))

首先调用__getattribute__。如果类定义了__getattr__方法,
那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,
而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。
user = User(), 那么user.age 顺序如下:

(1)(类和基类)如果“age”是出现在User类或其基类的__dict__中, 且age是data descriptor(数据描述符IntField), 那么调用其__get__方法, 否则

(2)如果“age”出现在user对象的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则

(3)如果“age”出现在User类或其基类的__dict__中

(3.1)如果age是non-data descriptor(非数据描述符),那么调用其非数据描述符(NonDataIntField)__get__方法, 否则

(3.2)返回 __dict__[‘age’]

(4)如果User类有__getattr__方法,调用__getattr__方法,否则

(5)抛出AttributeError

 

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/articles/9388065.html

posted on 2018-07-29 22:40  孙龙-程序员  阅读(232)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3