简而言之-可能不行。但我试过了。
这真的很奇怪,感觉就像无穷尽的乌龟一样。我以前其实没有深入研究过这个领域,虽然听起来很有趣也很强大。这个解释很令人困惑,那个页面上的其他信息也是如此,但我感觉自己有些启示了。无论我能否清晰地解释这一点,我不确定,但我会试着去做。
首先让我们看看这些乌龟:
>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
等等,什么?
当type
是object
的实例时,object
怎么会是type
的实例呢?这感觉就像在说:
class Parrot: pass
ex = Parrot()
isinstance(ex, Parrot)
isinstance(Parrot, ex)
这两次应该都是True
。但显然并不是这样的。就像Tadhg McDonald-Jensen指出的那样。
>>> isinstance(type, type)
True
这应该向您表明,幕后有一些神奇的事情正在发生。所以在这一点上,让我们完全忘记Python(我知道,为什么我们要做这样可怕的事情呢?)
总的来说,所有计算机程序都是1和0
(更准确地说,它们只是一堆逻辑门和电子,在>〜2.5v和〜<2.5v,但0和1足够好)。无论你是用汇编语言、实际机器码、Python、C#、Java、Perl还是其他什么语言编写的,它们都只是一堆比特。
如果你编写了一个类定义,那么这个类只是一些比特。该类的一个实例只是更多的比特。而编程语言、编译器和解释器只是更多的比特。
对于Python来说,是“python”解释器赋予了意义,这些比特是我们的Python程序。有趣的是,我们通常认为的大部分Python实际上是用Python编写的(虽然大部分是C,对于我们CPython人来说,Jython是Java等)。
现在我们来谈谈我们所说的类型
和对象
。正如文章所指出的那样,它们有点特别。因此,我们知道我们可以创建一个类,然后该类就是一个对象:
>>> 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
之间创建这种循环关系,它给人的印象是一直都是乌龟,但实际上最后两只乌龟只是站在彼此身上。
我认为没有比文章描述更好的解释这里正在发生的事情 - 至少在传统的OOP is-a/has-a思维方式中,并不是那种类型的事情。就像在二维空间中绘制三维图形一样,你会遇到问题。
这只是两组具有一些位于其中的位,恰好是彼此地址的位。