简体   繁体   English

查找旧式Python类的魔术方法

[英]Lookup of magic methods on old-style Python classes

I know old-style Python classes aren't recommended anymore, especially since Python 3 removes them. 我知道不再推荐旧式Python类,特别是因为Python 3删除了它们。 However, I'd still like to understand what is happening here: 但是,我仍然想了解这里发生的事情:

class MyClass:
  pass

my_instance = MyClass()
str(my_instance)

This snippet prints the following: 此代码段打印以下内容:

'< main .MyClass instance at 0x108ec4290>' '< main .MyClass实例位于0x108ec4290>'

So, I don't have any explicit inheritance and I didn't overload the str method. 所以,我没有任何显式继承,我没有重载str方法。 However, this doesn't raise an exception for the supposedly missing method. 但是,这并没有引起所谓的遗漏方法的异常。 Why? 为什么?

I know that old-style classes have the concept of an 'instance' and a 'type' and that new-style classes aim to unify these concepts. 我知道旧式课程具有“实例”和“类型”的概念,新式课程旨在统一这些概念。 So is Python finding and calling the str method on the 'instance' type that my instance is implicitly connected to? 那么Python是否在我的实例隐式连接的'instance'类型上查找和调用str方法?

Here are some clues: 以下是一些线索:

dir(my_instance) - Returns: dir(my_instance) - 返回:

['__doc__', '__module__']

type(my_instance) - Returns: type(my_instance) - 返回:

<type 'instance'>

dir(type(my_instance)) - Returns: dir(type(my_instance)) - 返回:

['__abs__', '__add__', '__and__', '__call__', '__class__', '__cmp__', '__coerce__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__', '__idiv__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__index__', '__init__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'next']

Can anyone explain exactly the relationship between classes and types in old-style classes and what is happening here? 任何人都可以准确地解释旧式课程中的类和类型之间的关系以及这里发生了什么?

I am sure other people can give you more concrete reasons that this, but there is a quote from a similar discussion located here: old-style class 我相信其他人可以给你更具体的理由,但这里有一个类似讨论的引用: 旧式的

object is the base class that is at the top of any inheritance tree. object是任何继承树顶部的基类。 The purpose of insisting on the base class, I believe, is to unify object behavior without requiring too much 'magic.' 我认为,坚持基类的目的是统一对象行为,而不需要太多的“魔力”。 That is, prior to new-style classes, objects just magically had properties like __doc__ and __str__ ; 也就是说,在新式类之前,对象只是神奇地拥有像__doc____str__这样的属性; now, they have them for a reason: because they inherited them from the base class. 现在,他们有他们是有原因的:因为他们从基类继承了它们。

That part about the "magic" I believe is just that... black-box magic. 关于“神奇”的那一部分,我相信只是......黑盒魔术。 Obviously the MRO (method resolution order) of old style classes was much more magical, in that it probably had to check both explicit definitions on the instance object, as well as on the type . 显然,旧样式类的MRO(方法解析顺序)更加神奇,因为它可能必须检查instance对象上的显式定义以及type Either that, or part of the mechanics of an old style class is to always provide a default __str__ method when one cannot be located. 要么,或者旧样式类的一部分机制是在无法定位时始终提供默认的__str__方法。

It would be less magical now with new-style classes, because due to the inheritance, the methods are really right there on the instance. 现在使用新式类会不那么神奇,因为由于继承,这些方法实际上就在那里。

Here is another site with some good quotes and examples: Principle of Biggest Surprise 这是另一个网站,有一些很好的引用和例子: 最大的惊喜原则

For old-style classes all lookup is done in the instance. 对于旧式类,所有查找都在实例中完成。

For instances of new-style classes, all special method lookup that is done implicitely is done in the class struct 对于新式类的实例,所有特殊方法查找都是在类结构中完成的

New-style: 新风格:

class Foo(object):
    def __str__(self):
        return "old str"

foo = Foo()
foo.__str__ = lambda: "new str"

print str(foo)
print foo.__str__()

# old str
# new str

Old-Style: 老式:

class Foo:
    def __str__(self):
        return "old str"

foo = Foo()
foo.__str__ = lambda: "new str"

print str(foo)
print foo.__str__()

# new str
# new str

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM