# -*- 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的过程
- _obj = A() 的加载过程:
因为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()