我通过http://blog.thedigitalcatonline.com/blog/2014/09/01/python-3-oop-part-5-metaclasses/#.Vv1T7zG1XGA阅读,其中包含:
因为在Python中,一切都是对象,所以一切都是类的实例,甚至是类。好吧,type是实例化的类来获取类。所以请记住:object是每个对象的基础,type是每个类型的类。听起来令人费解?这不是你的错,不用担心。但是,只是为了让你完成最后的动作,这就是Python构建的基础
>>> type(object)
<class 'type'>
>>> type.__bases__
(<class 'object'>,)
我无法理解这一点,任何人都可以用不同的方式解释这种关系,以使其更清晰吗?
答案 0 :(得分:3)
type(x)
之间的关系与x.__class__
的结果基本相同:
for obj in (object,type,1,str):
assert type(obj) is obj.__class__
print("type(obj) and obj.__class__ gave the same results in all test cases")
__bases__
表示类派生的基础:
class parent:
pass
class child(parent,int):
pass
print(child.__bases__)
但是,如果您询问object
和type
之间的奇怪关系:
>>> isinstance(object, object)
True
>>> isinstance(type, type)
True
>>> isinstance(object, type)
True
>>> isinstance(type, object)
True
这更像是一个鸡与蛋的问题:哪个先出现了?
答案是PyObject
,它在C中定义。
在object
或type
可用于python解释器之前,它们的基础机制在C中定义,并且实例检查在定义后会被覆盖。 (就像抽象类一样,参见PEP 3119)
你可以认为它类似于这个python实现:
#this wouldn't be available in python
class superTYPE(type):
def __instancecheck__(cls,inst):
if inst ==TYPE:
return True
else:
return NotImplemented #for this demo
class TYPE(type,metaclass=superTYPE):
def __instancecheck__(cls,inst):
if inst in (OBJECT,TYPE):
return True
else:
return NotImplemented #for this demo
class OBJECT(metaclass=TYPE):
pass
print(isinstance(TYPE,OBJECT))
print(isinstance(OBJECT,TYPE))
print(isinstance(TYPE,TYPE))
print(isinstance(OBJECT,OBJECT))
实际上它可能更好地表示为:
#this isn't available in python
class superTYPE(type):
def __instancecheck__(cls,inst):
if inst in (TYPE,OBJECT):
return True
else:
return NotImplemented #for this demo
class OBJECT(metaclass=superTYPE):
pass
class TYPE(OBJECT):
pass
但是如果你想确切知道它是如何工作的,你需要查看用C编写的源代码。
答案 1 :(得分:1)
这真的很奇怪,感觉就像海龟一样。我之前并没有非常深入研究这个领域,尽管它听起来很有趣和强大。这个解释令人困惑,该页面上的其他信息也是如此,但我感觉就像我有一些启示。无论我是否能清楚地解释清楚,我都不确定,但我会有所作为。
让我们先看看海龟:
>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
等等,什么?
当object
是type
的实例时,type
object
的实例如何?这就像说:
class Parrot: pass
ex = Parrot()
isinstance(ex, Parrot)
isinstance(Parrot, ex)
两次都应该True
。但显然它不是。甚至(正如Tadhg McDonald-Jensen指出的那样)
>>> isinstance(type, type)
True
这应该向你表明,幕后有一些魔力。所以在这一点上,让我们完全忘掉Python(我知道,为什么我们想要做这么可怕的事情?)
一般来说,所有的计算机程序都是1和0&lt; sub> (更准确地说,它们只是一堆逻辑门和电子在&gt; ~2.5 v和〜&lt; 2.5v,但0&s;和1&#39; s足够好了) 。无论你是在汇编,实际的机器代码,Python,C#,Java,Perl,还是其他任何东西中编写的,它们都只是位。
如果你写一个类定义,那个类只是位。该类的一个实例只是更多的位。编程语言,编译器和解释器就更多了。
对于Python,它是python
解释器,它为我们的Python程序提供了意义。有趣的是,我们通常认为是Python的很多内容实际上是用Python编写的(尽管大多数是C语言,对于我们CPython人员,Java用于Jython等)。
现在我们来讨论type
和object
。正如文章指出的那样,它们有点特殊。所以,我们知道我们可以创建一个类,然后该类就是一个对象:
>>> class Confusion: pass
...
>>> isinstance(Confusion, object)
这是有道理的,如果你考虑一下 - 你可能已经创建了类级变量:
>>> class Counter:
... count = 0
... def __init__(self):
... Counter.count += 1
... print(self.count)
...
>>> Counter()
1
<__main__.Counter object at 0x7fa03fca4518>
>>> Counter()
2
<__main__.Counter object at 0x7fa03fca4470>
>>> Counter()
3
<__main__.Counter object at 0x7fa03fca4518>
>>> Counter()
4
<__main__.Counter object at 0x7fa03fca4470>
>>> Counter.count
4
>>> Counter.__repr__(Counter)
'<type object at 0x1199738>'
但是,正如最后一个示例所示(并在帖子中提到),类声明,您使用class SomeClass: pass
得到的,该类的声明实际上是另一个的实例类。特别是,它是type
类的一个实例。那个实例(我们称之为类)在调用时会产生一个实例:
>>> Counter.__call__()
5
<__main__.Counter object at 0x7fa03fca4518>
那么这与type
和object
之间的关系有什么关系呢?
好吧,某处,python
创建一系列位object
,以及一系列位type
,然后将它们连接在一起以某种方式
>>> type.__bases__
(<class 'object'>,)
>>> object.__bases__
()
因为我目前不想查看来源,所以我要先猜测type
是先创建的,object
是从该类型产生的, type.__bases__
设置为(class 'object')
。通过在type
和object
之间建立这种循环关系,它给出的外观是它只是乌龟一直向下,而真正最后两只乌龟只是站在彼此之上。
我认为 -a /具有一种思维方式,因为它实际上并不是那种东西。就像试图在二维空间中绘制一个三维图形一样,你会遇到问题。
它只是两组位,其中有一些位恰好是彼此的地址。
答案 2 :(得分:0)
虽然我的第一个答案解决了Python内置变量type
和object
之间的矛盾关系,但并不一定要消除关于type
和{{ 1}}意味着更大的前景。该答案将说明object
和object
在实际可能会遇到的上下文中如何影响其他python对象。
在Python中,一切都是
type
这意味着语句object
将始终为isinstance(x, object)
给出任何可能的值True
。
这也意味着定义的任何类都将被视为对象的子类。因此,x
对于任何类总是正确的。
实际上这意味着将在issubclass(x, object)
中定义所有python对象的标准操作,例如属性查找和获取内存中对象的大小。它还定义了通常被覆盖的行为,例如转换为字符串或初始化,因此,如果您不在子类中覆盖object
或__str__
,它仍然会做一些合理的事情。
__init__
是实例化以获得类的类
这意味着所有类都被视为type
的实例。因此type
对于所有类都是正确的。当我说类时,我的意思是诸如isinstance(x, type)
,int
,str
或bool
关键字创建的变量。
一切都是对象-甚至是类。
这意味着所有对象存在的标准行为也适用于类对象。因此,编写class
将查找str.join
方法并为您提供join
type是每种类型的类
以与<method 'join' of 'str' objects>
定义int
应该做什么或1+3
定义字符串方法的方式相同,str
定义特定于类型对象的行为。例如,调用一个类对象(如type
)将创建该类的新实例-这种创建新对象的行为是在int("34")
方法中定义的。
作为一个更具体的示例,请查看type.__call__
和str.join
之间的对偶性
type.mro
因此,每个类都定义了作用于其实例的方法,类本身的行为在>>> x = "hello"
>>> str.join # unbound method of strings
<method 'join' of 'str' objects>
>>> x.join #bound method of x
<built-in method join of str object at 0x109bf23b0>
>>> hex(id(x)) # the memory address of x as seen above
'0x109bf23b0'
>>> type.mro #unbound method
<method 'mro' of 'type' objects>
>>> int.mro #mro method bound to int
<built-in method mro of type object at 0x106afeca0>
>>> hex(id(int)) # address of int object as seen above
'0x106afeca0'
>>> int.mro() #mro stands for Method Resolution Order, is related to __bases__
[<class 'int'>, <class 'object'>]
类中进行了定义。
所有对象共有的行为-您通常只是以内置方式注销的那种行为-由type
定义,因此所有对象都具有这些行为(除非子类覆盖它:)
P.S。以相同的方式,您可以创建object
的子类来创建具有不同行为的特殊字符串对象,也可以创建str
的子类来创建具有不同行为的特殊类。这称为元类(类对象的类)和practical applications of using meta-classes are usually abstract。 (双关语意味)