Có bất kỳ lý do cho một khai báo lớp để kế thừa từ object
?
Tôi chỉ tìm thấy một số mã làm điều này và tôi không thể tìm thấy một lý do tốt tại sao.
class MyClass(object):
# class code follows...
Có bất kỳ lý do cho một khai báo lớp để kế thừa từ object
?
Tôi chỉ tìm thấy một số mã làm điều này và tôi không thể tìm thấy một lý do tốt tại sao.
class MyClass(object):
# class code follows...
Câu trả lời:
Có bất kỳ lý do cho một khai báo lớp để kế thừa từ
object
?
Trong Python 3, ngoài khả năng tương thích giữa Python 2 và 3, không có lý do . Trong Python 2, nhiều lý do .
Trong Python 2.x (từ 2.2 trở đi) có hai kiểu lớp tùy thuộc vào sự hiện diện hay vắng mặt của object
lớp cơ sở:
Các lớp phong cách "cổ điển" : họ không có object
lớp cơ sở:
>>> class ClassicSpam: # no base class
... pass
>>> ClassicSpam.__bases__
()
Các lớp kiểu "mới" : chúng có, trực tiếp hoặc gián tiếp (ví dụ: kế thừa từ một kiểu dựng sẵn ), object
như một lớp cơ sở:
>>> class NewSpam(object): # directly inherit from object
... pass
>>> NewSpam.__bases__
(<type 'object'>,)
>>> class IntSpam(int): # indirectly inherit from object...
... pass
>>> IntSpam.__bases__
(<type 'int'>,)
>>> IntSpam.__bases__[0].__bases__ # ... because int inherits from object
(<type 'object'>,)
Không còn nghi ngờ gì nữa, khi viết một lớp học, bạn sẽ luôn muốn tham gia các lớp học theo phong cách mới. Các đặc quyền làm như vậy là rất nhiều, để liệt kê một số trong số họ:
Hỗ trợ cho người mô tả . Cụ thể, các cấu trúc sau được thực hiện với các mô tả:
classmethod
: Một phương thức nhận lớp dưới dạng một đối số ngầm thay vì thể hiện.staticmethod
: Một phương thức không nhận được đối số ngầm self
là đối số đầu tiên.property
: Tạo các hàm để quản lý việc nhận, cài đặt và xóa thuộc tính.__slots__
: Lưu các giả định bộ nhớ của một lớp và cũng dẫn đến truy cập thuộc tính nhanh hơn. Tất nhiên, nó không áp đặt các hạn chế .Các __new__
phương pháp tĩnh: cho phép bạn tùy chỉnh cách mới trường lớp được tạo ra.
Thứ tự phân giải phương thức (MRO) : theo thứ tự các lớp cơ sở của một lớp sẽ được tìm kiếm khi cố gắng giải quyết phương thức nào sẽ gọi.
Liên quan đến MRO, super
các cuộc gọi . Cũng thấy, super()
coi là siêu.
Nếu bạn không thừa kế từ object
, hãy quên những thứ này. Một mô tả đầy đủ hơn về các điểm đạn trước đó cùng với các đặc quyền khác của các lớp phong cách "mới" có thể được tìm thấy ở đây .
Một trong những nhược điểm của các lớp kiểu mới là bản thân lớp này đòi hỏi nhiều bộ nhớ hơn. Tuy nhiên, trừ khi bạn đang tạo ra nhiều đối tượng lớp, tôi nghi ngờ đây sẽ là một vấn đề và đó là một sự tiêu cực chìm trong một biển tích cực.
Trong Python 3, mọi thứ được đơn giản hóa. Chỉ có các lớp kiểu mới tồn tại (được gọi đơn giản là các lớp), do đó, sự khác biệt duy nhất trong việc thêm object
là yêu cầu bạn nhập thêm 8 ký tự. Điều này:
class ClassicSpam:
pass
là hoàn toàn tương đương (ngoài tên của họ :-) với điều này:
class NewSpam(object):
pass
và về điều này:
class Spam():
pass
Tất cả đều có object
trong họ __bases__
.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]
Trong Python 2: luôn kế thừa từ object
rõ ràng . Nhận các đặc quyền.
Trong Python 3: kế thừa từ object
nếu bạn đang viết mã cố gắng là bất khả tri của Python, nghĩa là, nó cần phải hoạt động cả trong Python 2 và Python 3. Nếu không, nó thực sự không có gì khác biệt vì Python chèn nó cho bạn đằng sau hậu trường.
object
. IIRC đã có một thời điểm mà không phải tất cả các kiểu dựng sẵn được chuyển sang các lớp kiểu mới.
object
. Tôi có một Python 2.2.3 xung quanh và sau khi kiểm tra nhanh tôi không thể tìm thấy một kẻ phạm tội nhưng, tôi sẽ điều chỉnh lại câu trả lời sau để làm cho nó rõ ràng hơn. Sẽ được quan tâm nếu bạn có thể tìm thấy một ví dụ mặc dù, sự tò mò của tôi được khơi gợi.
object
trong các cơ sở của nó.
staticmethod
và classmethod
làm việc tốt ngay cả trên các lớp học kiểu cũ. property
sorta hoạt động để đọc trên các lớp kiểu cũ, nó chỉ không thể ghi được ghi (vì vậy nếu bạn gán cho tên, thì thể hiện sẽ có được một thuộc tính của tên đã cho làm mờ thuộc tính). Cũng lưu ý rằng __slots__
sự cải thiện về tốc độ truy cập thuộc tính chủ yếu là về việc làm mất đi sự mất mát mà quyền truy cập thuộc tính lớp kiểu mới phải gánh chịu, vì vậy nó không thực sự là một điểm bán của các lớp kiểu mới (mặc dù tiết kiệm bộ nhớ là một điểm bán hàng).
Con trăn 3
class MyClass(object):
= Lớp học kiểu mớiclass MyClass:
= Lớp kiểu mới (hoàn toàn kế thừa từ object
)Con trăn 2
class MyClass(object):
= Lớp học kiểu mớiclass MyClass:
= LỚP PHONG CÁCHGiải thích :
Khi định nghĩa các lớp cơ sở trong Python 3.x, bạn được phép bỏ object
định nghĩa. Tuy nhiên, điều này có thể mở ra cơ hội cho một vấn đề nghiêm trọng khó theo dõi
Python đã giới thiệu các lớp kiểu mới trở lại trong Python 2.2 và bây giờ các lớp kiểu cũ thực sự khá cũ. Thảo luận về các lớp kiểu cũ được chôn trong các tài liệu 2.x và không tồn tại trong các tài liệu 3.x.
Vấn đề là, cú pháp cho các lớp học kiểu cũ bằng Python 2.x cũng giống như cú pháp thay thế cho các lớp học kiểu mới bằng Python 3.x . Python 2.x vẫn được sử dụng rất rộng rãi (ví dụ GAE, Web2Py) và bất kỳ mã nào (hoặc bộ mã hóa) vô tình đưa các định nghĩa lớp kiểu 3.x vào mã 2.x sẽ kết thúc với một số đối tượng cơ sở lỗi thời nghiêm trọng. Và bởi vì các lớp kiểu cũ không có trên radar của bất kỳ ai, nên có khả năng họ sẽ không biết thứ gì đánh trúng họ.
Vì vậy, chỉ cần đánh vần nó trên con đường dài và tiết kiệm cho một số nhà phát triển 2.x những giọt nước mắt.
__metaclass__ = type
ở đầu mô-đun (sau from __future__ import absolute_import, division, print_function
dòng :-)); Đây là một hack tương thích trong Py2, làm cho tất cả các lớp được xác định sau đó trong mô-đun theo kiểu mới theo mặc định và trong Py3, nó hoàn toàn bị bỏ qua (chỉ là một biến toàn cục ngẫu nhiên ngồi xung quanh), vì vậy nó vô hại.
Vâng, đây là một đối tượng 'phong cách mới'. Đó là một tính năng được giới thiệu trong python2.2.
Đối tượng phong cách mới có một mô hình đối tượng khác nhau để đối tượng cổ điển, và một số điều sẽ không hoạt động đúng với các đối tượng theo phong cách cũ, ví dụ, super()
, @property
và mô tả. Xem bài viết này để có một mô tả tốt về một lớp phong cách mới là gì.
Liên kết SO cho một mô tả về sự khác biệt: Sự khác biệt giữa các kiểu kiểu cũ và các lớp kiểu mới trong Python là gì?
object
Python 2.
Lịch sử từ Tìm hiểu Python theo cách khó :
Biểu hiện ban đầu của Python về một lớp học đã bị phá vỡ theo nhiều cách nghiêm trọng. Vào thời điểm lỗi này được nhận ra thì đã quá muộn và họ phải hỗ trợ. Để khắc phục sự cố, họ cần một số kiểu "lớp mới" để "lớp cũ" tiếp tục hoạt động nhưng bạn có thể sử dụng phiên bản mới chính xác hơn.
Họ quyết định rằng họ sẽ sử dụng một từ "đối tượng", hạ cấp, để trở thành "lớp" mà bạn kế thừa để tạo ra một lớp. Thật khó hiểu, nhưng một lớp kế thừa từ lớp có tên là "đối tượng" để tạo ra một lớp nhưng nó không phải là một đối tượng thực sự là một lớp, nhưng đừng quên kế thừa từ đối tượng.
Ngoài ra, chỉ để cho bạn biết sự khác biệt giữa các lớp kiểu mới và các lớp kiểu cũ là gì, đó là các lớp kiểu mới luôn kế thừa từ object
lớp hoặc từ một lớp khác được thừa hưởng từ object
:
class NewStyle(object):
pass
Một ví dụ khác là:
class AnotherExampleOfNewStyle(NewStyle):
pass
Trong khi một lớp cơ sở kiểu cũ trông như thế này:
class OldStyle():
pass
Và một lớp trẻ kiểu cũ trông như thế này:
class OldStyleSubclass(OldStyle):
pass
Bạn có thể thấy rằng một lớp cơ sở Kiểu cũ không kế thừa từ bất kỳ lớp nào khác, tuy nhiên, các lớp Kiểu cũ dĩ nhiên có thể kế thừa từ nhau. Kế thừa từ đối tượng đảm bảo rằng chức năng nhất định có sẵn trong mỗi lớp Python. Các lớp kiểu mới đã được giới thiệu trong Python 2.2
object
không phải là điều khó hiểu, và trên thực tế, nó khá chuẩn. Smalltalk có một lớp gốc được đặt tên Object
và một siêu dữ liệu gốc có tên Class
. Tại sao? Bởi vì, cũng giống như Dog
một lớp học cho chó, Object
là một lớp học cho các đối tượng và Class
là một lớp học cho các lớp học. Java, C #, ObjC, Ruby và hầu hết các ngôn ngữ OO dựa trên lớp khác mà mọi người sử dụng ngày nay có lớp gốc sử dụng một số biến thể Object
như tên, không chỉ Python.
Vâng, đó là lịch sử . Không có nó, nó tạo ra một lớp kiểu cũ.
Nếu bạn sử dụng type()
trên một đối tượng kiểu cũ, bạn chỉ cần lấy "thể hiện". Trên một đối tượng kiểu mới, bạn có được lớp của nó.
type()
trên một lớp kiểu cũ, bạn sẽ nhận được "classobj" thay vì "type".
Cú pháp của câu lệnh tạo lớp:
class <ClassName>(superclass):
#code follows
Trong trường hợp không có bất kỳ siêu lớp nào khác mà bạn đặc biệt muốn kế thừa từ đó, superclass
thì luôn luôn phải object
là gốc của tất cả các lớp trong Python.
object
về mặt kỹ thuật là gốc của các lớp "kiểu mới" trong Python. Nhưng các lớp học theo phong cách mới ngày nay cũng tốt như là phong cách duy nhất của các lớp học.
Nhưng, nếu bạn không sử dụng rõ ràng từ này object
khi tạo các lớp, thì như những người khác đã đề cập, Python 3.x hoàn toàn kế thừa từ object
siêu lớp. Nhưng tôi đoán rõ ràng luôn luôn tốt hơn ngầm (địa ngục)