python property 研究

这篇博客探讨了Python中property属性在继承时的工作原理。作者通过疑问和解释指出,当子类重写父类的property方法时,由于Python解释器的加载顺序,子类的重写方法并不会自动覆盖父类的property。解决这个问题的关键在于,在子类中显式地重载property,确保使用子类自己的方法。博客最后提供了实现property重载的一种方法。
摘要由CSDN通过智能技术生成
# -*- coding:utf-8 -*-
'''
@email:289012724@qq.com
@author: shuiyaoyao
@telephone:13587045516
'''

def function():
    print "1"

class A(object):
    def __init__(self):
        object.__init__(self)
    def get(self):
        return 'A'
    def set(self):
        print 'A'
    test = property(get,set)

class B(A):
    def __init__(self):
        A.__init__(self)
    def get(self):
        print 'B'
    def set(self):
        print "B"

def run():
    print A().test
    print B().test


输出结果为
#-----
# A
# A
#-----
疑问:
  • 第二个打印什么不是 “B” 呢。不是明明已经重写了 继承的方法吗?
解释:
  • python 解释器 从上到下 读取加载 python 的文件。然后在内存创建相关实例和对象可以通过 type 查看返回的对象类型。比如 type(A.get) 返回的是 instancemethod 而 type(function) 返回的 是function .不同类型调用的方式不一样。

  • 最核心的是解释器加载的流程:

    • _obj = A() 的加载过程:
      • 执行文件中的字节流,创建相关属性, 和方法
      • 调用 new(cls,*args,**kwgs) 返回 self 对象
      • 调用 init(self)
    • _obj2= B() 的 加载过程 是:
      • 先执行 上面的 过程— 此时 创建了 test 这个property 对象
      • 再执行B的过程
  • 因为B 是继承自A的,所以加载的时候 ,会获得 A中定义的所有方法和属性
    对 test 来说。

  • 在加载 A的时候 ,创建的时候, property 中传入的是 A类的 相关方法。而不是B中的。
  • 因为是继承,先创建A的内容。然后才是B中的。所有为什么 后面会有方法的重载内容。因为在 创建自己的时候,用了新的方法—(内存中的一个地址),来覆盖了原来的方法。所有才会有重载。如果是反着走。那就不会有重载了。
疑问:

有方法可以实现,property 调用自己重写的方法吗?

解释:

答案是有的
在调用 new 这个方法的时候,自己重载一个 property 属性。相当于在 B的 后面 加一个 test = property(fget,fset) 方法。记住此时 要传入的是自己的方法。而不是继承而来的。这样就可以实现重载。以下给出一种实现方式

def __new__(cls,*args,**kwgs):
    _key_words = dir(cls)
    for _key in _key_words:
        _is_pro = getattr(cls,_key)
        # 判断是否文 property 对象
        if isinstance(_is_pro,property)):
            #TODO
            #1 获得 fget fset 方法名称
            #2 检测自己是否重载此方法
            setattr(cls,_property_name,property(fget,fset))
    return object.__new__(cls,*args,**kwgs)

完整代码

# -*- coding:utf-8 -*-
'''
@email:289012724@qq.com
@author: shuiyaoyao
@telephone:13587045516
'''

class A(object):
    def __init__(self):
        object.__init__(self)
    def get(self):
        return 'A'

    def set(self):
        return 'A'
    test = property(get,set)

class B(A):
    def __new__(cls,*args,**kwgs):
        _key_words = dir(cls)
        for _key in _key_words:
            _is_pro = getattr(cls,_key)
            # 判断是否文 property 对象
            if isinstance(_is_pro,property):
                fget = getattr(cls,_is_pro.fget.__name__)
                fset = getattr(cls,_is_pro.fset.__name__)
                setattr(cls,_key,property(fget,fset))
        return object.__new__(cls,*args,**kwgs)

    def __init__(self):
        A.__init__(self)

    def get(self):
        return  'B'

    def set(self):
        return "B"

def run():
    print A().test
    print B().test

if __name__ == "__main__":
    run()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值