Tất cả các lớp Python có nên mở rộng đối tượng không?


129

Tôi đã tìm thấy rằng cả hai công việc sau đây:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

Tất cả các lớp Python có nên mở rộng đối tượng không? Có bất kỳ vấn đề tiềm năng với việc không mở rộng đối tượng?


2
Có sự khác biệt giữa class Foo():class Foo:? Khi tôi quan sát, cả hai đều hoạt động trong Python 3.
Wolf

Nó đã được trả lời tốt trong câu hỏi này: stackoverflow.com/questions/4015417/ từ
nngeek

Câu trả lời:


117

Trong Python 2, không kế thừa từ objectsẽ tạo ra một lớp kiểu cũ, trong đó, trong số các hiệu ứng khác, gây ra typekết quả khác nhau:

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

so với

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

Ngoài ra, các quy tắc cho nhiều kế thừa là khác nhau theo những cách mà tôi thậm chí sẽ không tóm tắt ở đây. Tất cả các tài liệu tốt mà tôi đã thấy về MI mô tả các lớp kiểu mới.

Cuối cùng, các lớp kiểu cũ đã biến mất trong Python 3 và kế thừa từ objectđó trở nên ẩn. Vì vậy, luôn thích các lớp kiểu mới trừ khi bạn cần compat ngược với phần mềm cũ.


68

Trong Python 3, các lớp mở rộng objectngầm, cho dù bạn có tự nói như vậy hay không.

Trong Python 2, có các lớp kiểu cũ và kiểu mới . Để báo hiệu một lớp là kiểu mới, bạn phải kế thừa rõ ràng từ đó object. Nếu không, việc thực hiện kiểu cũ được sử dụng.

Bạn thường muốn một lớp học theo phong cách mới. Kế thừa từ objectrõ ràng. Lưu ý rằng điều này cũng áp dụng cho mã Python 3 nhằm tương thích với Python 2.


Vâng, sự khác biệt Free Foo đã chỉ ra , đã biến mất, BTW: các dấu ngoặc rỗng có tùy chọn không?
Sói

4
Có rất nhiều mã python 3 sử dụng foo (object) :. Đây chỉ là một quy ước sau đó?
RFV5

2
@RFVenter Nó có thể là mã được cho là chạy theo cả Python 2 và 3, trong trường hợp đó bạn cần phải phân lớp đối tượng một cách rõ ràng để làm cho lớp hoạt động giống nhau theo Python 2.
blubberdiblub

@blubberdiblub Đó là những gì tôi nghi ngờ NHƯNG dự án của chúng tôi đang chạy độc quyền trên python 3.5 virtualenv. Tôi nghĩ rằng mã phải được sao chép từ một dự án python 2.
RFV5

@RFVenter yup, đó có thể là một lời giải thích khác. Và tất nhiên, nếu bây giờ chỉ là Python 3.x, bạn có thể thoát khỏi các tham chiếu đối tượng.
blubberdiblub

17

Trong python 3, bạn có thể tạo một lớp theo ba cách khác nhau và bên trong chúng đều bằng nhau (xem ví dụ). Không quan trọng bạn tạo một lớp như thế nào, tất cả các lớp trong python 3 đều thừa hưởng từ lớp đặc biệt gọi là đối tượng . Đối tượng lớp là lớp cơ bản trong python và cung cấp rất nhiều chức năng như các phương thức gạch dưới kép, mô tả, phương thức super (), phương thức property (), v.v.

Ví dụ 1.

class MyClass:
 pass

Ví dụ 2.

class MyClass():
 pass

Ví dụ 3.

class MyClass(object):
  pass

1
Điều này không hoàn toàn đúng ... stackoverflow.com/questions/1238606/ Quảng cáo
Philip Adler

Tôi không chắc là tôi theo bạn. Và có, có lẽ không liên quan đến hầu hết mọi người cho đến khi nó có liên quan.
Philip Adler

@PhilipAdler Nó thường được giả định là objecttham chiếu đến tích hợp sẵn object. Nếu chúng ta phải tính đến việc có thể thay thế bất kỳ số nhận dạng tích hợp nào của CPython, chúng ta hầu như không thể đưa ra một số khẳng định nào về mô hình dữ liệu. Có thể lập luận nghiêm túc rằng strkhông phải lúc nào cũng chấp nhận một chuỗi như là một đối số bởi vì người ta có thể gán builtins.str = None?
Nuno André

Tôi tiếp tục thấy tuyên bố này rằng đây là "giả định rộng rãi" và tôi chấp nhận rằng đó là một giả định mà mọi triển khai hiện tại đưa ra (nó không phải là một yêu cầu của ngôn ngữ), đó không phải là kinh nghiệm của tôi mà phần lớn các lập trình viên python tôi đã gặp giả định này, biết về nó, hoặc thậm chí đã xem xét nó. Bất kể trong số đó, khẳng định rằng nó thường được giả định, ngay cả khi đúng, không làm mất hiệu lực khẳng định của tôi rằng sự tương đương không hoàn toàn đúng.
Philip Adler

1

Có, tất cả các lớp Python nên mở rộng (hoặc đúng hơn là lớp con, đây là đối tượng Python ở đây). Mặc dù thông thường sẽ không có vấn đề nghiêm trọng nào xảy ra, trong một số trường hợp (như với nhiều cây thừa kế), điều này sẽ rất quan trọng. Điều này cũng đảm bảo khả năng tương thích tốt hơn với Python 3.


1
chính xác, về mặt kỹ thuật nếu bạn không có lớp cổ điển, nhưng không có lợi thế thực sự cho việc này và dù sao nó cũng không được hỗ trợ bởi python 3
max k.

Tôi tò mò về lý do tại sao nó cải thiện khả năng tương thích với python3. Theo hiểu biết của tôi, python3 sẽ làm cho nó mở rộng đối tượng tự động ngay cả khi bạn không chỉ định nó, phải không?
Paul Lo

2
@PaulLo Đúng, nhưng nếu bạn kế thừa rõ ràng từ đối tượng, bạn sẽ có hành vi (kiểu mới) giống nhau trên cả Python 2 và Python 3. Đây không phải là vấn đề thay đổi cách Python 3 hoạt động, đó là vấn đề sử dụng chuyển tiếp -Khả năng tương thích trên Python 2.
pydsigner

Đề xuất này có vẻ không thanh lịch lắm, nhưng trong trường hợp bạn giải quyết Python2 và Python3, nó có vẻ hiệu quả. Nhưng nó có liên quan như thế nào trong thực tế?
Sói

@Wolf Nó phụ thuộc vào những gì bạn đang làm. Nếu bạn có cây thừa kế phức tạp, nó khá quan trọng. Nếu bạn muốn lớp của bạn là một mô tả, bạn phải sử dụng kiểu mới. Bạn có thể theo các liên kết từ stackoverflow.com/questions/54867/, nếu bạn muốn biết thêm thông tin chi tiết.
pydsigner

1

Như các câu trả lời khác đã trình bày, kế thừa Python 3 từ đối tượng là ẩn. Nhưng họ không nói rõ bạn nên làm gì và quy ước là gì.

Tất cả các ví dụ về tài liệu Python 3 đều sử dụng kiểu sau đây là quy ước, vì vậy tôi khuyên bạn nên làm theo cách này cho bất kỳ mã nào trong tương lai trong Python 3.

class Foo:
    pass

Nguồn: https://docs.python.org/3/tutorial/groupes.html#group-objects

Trích dẫn ví dụ:

Các đối tượng lớp hỗ trợ hai loại hoạt động: tham chiếu thuộc tính và khởi tạo.

Tham chiếu thuộc tính sử dụng cú pháp tiêu chuẩn được sử dụng cho tất cả các tham chiếu thuộc tính trong Python: obj.name. Tên thuộc tính hợp lệ là tất cả các tên trong không gian tên của lớp khi đối tượng lớp được tạo. Vì vậy, nếu định nghĩa lớp trông như thế này:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

Một trích dẫn khác:

Nói chung, các biến đối tượng là dành cho dữ liệu duy nhất cho từng thể hiện và biến lớp là dành cho các thuộc tính và phương thức được chia sẻ bởi tất cả các thể hiện của lớp:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

0

trong python3 không có sự khác biệt, nhưng trong python2 không mở rộng objectmang đến cho bạn một lớp kiểu cũ; bạn muốn sử dụng một lớp kiểu mới trên một lớp kiểu cũ.


2
Câu trả lời này là hợp lý, nhưng những người trả lời khác đã đến đó nhanh hơn và / hoặc chi tiết hơn; câu trả lời này không thêm bất kỳ giá trị nào vào trang.
Mark Amery
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.