Python3中的简单方法继承
新手python继承问题。。当您编写以下内容时:Python3中的简单方法继承,python,inheritance,Python,Inheritance,新手python继承问题。。当您编写以下内容时: class A: def foo(self): print("a") class B(A): pass b = B() getattr(b, "foo") 产生 <bound method A.foo of <__main__.B object at 0x000000000604CC88>> 看起来Python创建了一个绑定到A.foo的属性foo,它知道foo是一个A方法 我应
class A:
def foo(self):
print("a")
class B(A):
pass
b = B()
getattr(b, "foo")
产生
<bound method A.foo of <__main__.B object at 0x000000000604CC88>>
看起来Python创建了一个绑定到A.foo
的属性foo
,它知道foo
是一个A
方法
我应该认为继承只是创建指向基类对象的指针(解释器知道它是基类对象)而不是在派生类中创建属性的副本吗
似乎这是一个重要的观点,但一开始我并不清楚-在玩
super()
的时候,我提出了这个问题。你部分正确,让我们从你的错误开始
我应该认为继承只是创建指向基类对象的指针吗
这是不正确的。当您使用getattr(obj,attr)
或执行obj.attr
访问属性时,Python首先通过。特别是,这意味着这不会发生在类创建时,而是发生在属性查找时
看起来Python创建了一个属性foo
,该属性绑定到A.foo
给你,你说得对。绑定类或实例方法会在过程中创建新对象
恢复属性后,Python可能需要绑定它。它首先检查它是否是一个对象,即一个具有\uuuu get\uuuu
方法的对象,以允许将其绑定到某个实例
下面是getattr
的Python实现,以帮助可视化检索属性时发生的情况
首先,这是Python如何使用mro解析类属性
然后,如果它是在Python中,这就是getattr
的实现方式
def getattr(instance, attr):
cls = instance if isinstance(instance, type) else type(instance)
# Recover instance attribute
if hasattr(instance, '__dict__') and attr in instance.__dict__:
attr_value = instance.__dict__[attr]
# Recover the attribute from the class
else:
attr_value = _resolve_cls_attr(cls, attr)
# We recovered a simple class attribute
if not hasattr(attr_value, '__get__'):
return attr_value
# We recovered an instance method from a class or a staticmethod descriptor
if instance is cls or isinstance(attr_value, staticmethod):
return attr_value.__get__(None, cls)
# We recovered an instance method or a custom descriptor
return attr_value.__get__(instance, cls)
记住,为了坚持你的问题,上面省略了几个步骤。举例来说,它不会像内置的
getattr
那样依赖\uuuu getattr\uuuuu
和\uuu getattribute\uuuuuu
。当您使用b.foo
时,Python将首先查看b
的\uu dict\uu
中找不到foo的地方。然后,它将依次检查mro()
,即类型层次结构中的所有类型,以检查它可以从何处获取foo
。在你的例子中,它会先检查B.foo
,然后再检查A.foo
@poke right,所以我想我的问题的关键是:当你做B(A)
,foo
时,不会添加到B
的命名空间中,相反,\uuuuuu dict\uuuuu
包含所有在B
中专门创建的属性,而不是从其他地方继承的属性,是吗?\uuuuuu dict\uuuuuu
将只包含实例成员,即您执行self.something=value
操作的对象。方法通常存在于类中,而不是实例中。@poke很高兴知道!所以说它是foo
的正确方式不会添加到B中。当你执行B(A)
,而不是调用B.foo
时,会检查B.\uu dict\uu
,然后进一步检查MRO,因为找不到它?是的,任何属性访问都会像这样工作。这是一种非常容易误导人且有缺陷的处理描述符的方法。为什么要使用所有特殊的大小写,而不是只实现实际的规则(\uuu get\uuuuuuuuuuuuuuuu(实例,cls)
对于一个实例,\uuuuuu get\uuuuuuuuuuuuuuuuuu(无,cls)
对于一个类?另外,如果你要做描述符处理,数据描述符可能至少值得一提。@user2357112我是在凌晨1点左右写的,睡个好觉后可能会有所改善。请注意,答案中已经链接了文档到描述符。
def getattr(instance, attr):
cls = instance if isinstance(instance, type) else type(instance)
# Recover instance attribute
if hasattr(instance, '__dict__') and attr in instance.__dict__:
attr_value = instance.__dict__[attr]
# Recover the attribute from the class
else:
attr_value = _resolve_cls_attr(cls, attr)
# We recovered a simple class attribute
if not hasattr(attr_value, '__get__'):
return attr_value
# We recovered an instance method from a class or a staticmethod descriptor
if instance is cls or isinstance(attr_value, staticmethod):
return attr_value.__get__(None, cls)
# We recovered an instance method or a custom descriptor
return attr_value.__get__(instance, cls)