標籤:

Python 為什麼要繼承 object 類?

很多時候新建一個類都要繼承object ,久而久之,已經忘了為什麼要繼承它了


在大概是2.4 - 3.0 之間都會這麼去做, 繼承object用的是新式類.

自己可以試試用兩種方式創建兩個類去看看, (dir)


歷史遺留問題.2.2以前的時候type和object還不統一. 在2.2統一以後到3之間, 要用class Foo(object)來申明新式類, 因為他的type是 &< type type &> .不然的話, 生成的類的type就是 &< type classobj &>


歷史原因,2.x 里 object 是一個較新基類。具體區別見這篇文章,講的很清楚: http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html

在3.x里object已經做為所有東西的基類了。


Python2 里的新式類, 其特點如下(截取Guido的博客內容, 然後添加點自己的解釋, 輕拍~):

  • low-level constructors named __new__() – 低級別的構造函數.

    Note: Python 的 class __init__ 並不是其他語言意義上的構造函數,

    在 new 創建實例後對實例屬性初始化的函數.

  • descriptors, a generalized way to customize attribute access – 描述符.

    或者說描述符協議支持.descriptor protocol __get__, __set__ ,__delete__ 等,

    可以閱讀 descriptor 文檔

  • static methods and class methods - 靜態方法和類方法

  • properties (computed attributes) – 屬性訪問 setter getter.

  • decorators (introduced in Python 2.4) – 裝飾器.

    現在裝飾器語法糖遍布各Python框架.

  • slots – 用戶設置後可以限定實例的屬性.

    在 Python2 中替代 __dict__, 可以節省近 2/3 內存, Python3 中可以

    不因為優化內存使用率而使用 slots, 因為 __dict__ 結構內存做了優化,

    Note: __dict__ 並不是 Python 意義上的內置的 dict, 其實是一個 proxy 類.

  • a new Method Resolution Order (MRO) – MRO 方法解析次序改變

    (由左遞歸改為C3演算法)

貼上博客,另外博客參考的是Guido的親自介紹的博文.

Python 新式類介紹 (包含 new-style-and-classic-classes 文檔翻譯)

http://python-history.blogspot.com/2010/06/inside-story-on-new-style-classes.html


py 2.2 後繼承 object 的目的是使這個類成為 new style class, 沒有繼承 object 的為傳統 classic class,

在本機進行了測試,環境為 py 2.7.3

class Foo(object):

pass

class Foo1:

pass

print type(Foo), type(Foo1)

print dir(Foo)

print dir(Foo1)

print isinstance(Foo, object)

print isinstance(Foo1, object)

結果如下:

& &

[__class__, __delattr__, __dict__, __doc__, __format__, __getattribute__, __hash__, __init__, __module__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__, __weakref__]

[__doc__, __module__]

True

True(這個 True 有些疑問,Foo1 不應是 object 的實例啊)

還有一個問題是上面兄弟說 py 3.0 以上 object 已經作為默認基類被繼承了(跟 java 一樣),本機環境不太方便測試,所以不知是否正確.


寫東西的時候剛好遇到這個問題,回答一波……

繼承 object 類的是新式類,不繼承 object 類的是經典類,在 Python 2.7 裡面新式類和經典類在多繼承方面會有差異:

class A:
def foo(self):
print(called A.foo())

class B(A):
pass

class C(A):
def foo(self):
print(called C.foo())

class D(B, C):
pass

if __name__ == __main__:
d = D()
d.foo()

B、C 是 A 的子類,D 多繼承了 B、C 兩個類,其中 C 重寫了 A 中的 foo() 方法。

如果 A 是經典類(如上代碼),當調用 D 的實例的 foo() 方法時,Python 會按照深度優先的方法去搜索 foo() ,路徑是 B-A-C ,執行的是 A 中的 foo() ;

如果 A 是新式類,當調用 D 的實例的 foo() 方法時,Python 會按照廣度優先的方法去搜索 foo() ,路徑是 B-C-A ,執行的是 C 中的 foo() 。

因為 D 是直接繼承 C 的,從邏輯上說,執行 C 中的 foo() 更加合理,因此新式類對多繼承的處理更為合乎邏輯。

在 Python 3.x 中的新式類貌似已經兼容了經典類,無論 A 是否繼承 object 類, D 實例中的 foo() 都會執行 C 中的 foo() 。但是在 Python 2.7 中這種差異仍然存在,因此還是推薦使用新式類,要繼承 object 類。


python3.4 測試,不繼承object也是可以的:

class aa:
pass
&>&>&> type(aa)
&
&>&>&> print(isinstance(aa, object))
True
&>&>&> dir(aa)
[__class__, __delattr__, __dict__, __dir__, __doc__, __eq__, __format__, __ge__, __getattribute__, __gt__, __hash__, __init__, __le__, __lt__, __module__, __ne__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__, __weakref__]


http://www.cnblogs.com/limuyuan/p/why-python-extend-object-class.html

2017/9/25更新:

=============

剛剛才知道Java里的Object類也是所有class的父類。。這麼說Python的新式類是從Java借鑒過來的?

2017/9/13原答案:

=============

自學Learn Python The Hard Way看到了這個問題,樓上各位回答講真我是看的一頭霧水。。

然後去stackoverflow搜索了一下,結合官方文檔,說一下我自己的理解:

2 PEPs 252 and 253: Type and Class Changes

First, you should know that Python 2.2 really has two kinds of classes: classic or old-style classes, and new-style classes. The old-style class model is exactly the same as the class model in earlier versions of Python. All the new features described in this section apply only to new-style classes. This divergence isnt intended to last forever; eventually old-style classes will be dropped, possibly in Python 3.0.

So how do you define a new-style class? You do it by subclassing an existing new-style class. Most of Pythons built-in types, such as integers, lists, dictionaries, and even files, are new-style classes now. A new-style class named object, the base class for all built-in types, has also been added so if no built-in type is suitable, you can just subclass object:

其實這裡已經說得很清楚,Python 2.2有兩種類:舊式類、新式類。舊式類是什麼樣的暫時不用管,只要記住,以後都用並且只用新式類,就對了。

那麼怎麼來聲明或定義(define)一個新式類呢?做法就是,從現有的新式類中創建子類。

大多數的Python的內建類型(built-in type),比如整型(integers),列表(lists),字典(dictionaries),甚至文件(files),現在都是新式類了。我們也添加了一個叫object的新式類,作為所有內建類型的基類(base class),所以如果沒有適合的內建類型,從object創建子類就好了:

class C(object):
def __init__ (self):
...
...

所以現在明白了嗎?object只是從Python 2.2開始被引入的一個新式類(new-style class),作用是所有內建類型(built-in types)的基類(base class),而新式類需要從現有的新式類中創建,所以如果沒有適合的,用object就好了,就是這麼簡單。

至於新式類和舊式類的區別,網上有很多文章,可以自行查閱學習

(其實只是因為我不知道。。


繼承了object的類是新式類,由於他們都是object的派生類,便於統一操作。py2由於一些類不繼承object,就弄了一些內置函數,兩種風格摻雜在一起很彆扭。其實這點在動態語言裡面看不出優勢,在靜態類型的語言比如java之中優勢一目了然。


舊式類沒有property和super方法吧,對吧


推薦閱讀:

opencv庫的python版為啥比c++版小這麼多?是功能有區別嗎?
1.4從零開始學Scrapy爬蟲之第一個爬蟲
Python實現3D建模工具
樹的平衡與再平衡。
Python3 簡明教程

TAG:Python |