2009-01-28 33 views
101

Trong Python 2.5.2, đoạn mã sau đặt ra một Lỗi Loại:Python siêu() nâng TypeError

>>> class X: 
... def a(self): 
...  print "a" 
... 
>>> class Y(X): 
... def a(self): 
...  super(Y,self).a() 
...  print "b" 
... 
>>> c = Y() 
>>> c.a() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in a 
TypeError: super() argument 1 must be type, not classobj 

Nếu tôi thay thế class X với class X(object), nó sẽ làm việc. Giải thích cho điều này là gì?

+2

"tuy nhiên tôi thay thế lớp X với lớp X (đối tượng)" đã khắc phục sự cố của tôi! thanx – AliBZ

Trả lời

124

Lý do là siêu() chỉ hoạt động trên các lớp kiểu mới, mà trong chuỗi 2.x có nghĩa là kéo dài từ đối tượng.

+3

Từ phiên bản python nào đã trở thành hành vi mặc định? – Geo

+6

2.2 là khi các lớp kiểu mới được giới thiệu, 3.0 là nơi chúng trở thành mặc định. –

+6

@tsunami nếu bạn muốn nhận được ở siêu lớp, làm "X.a (tự)" –

13

Ngoài ra, không sử dụng siêu() trừ khi bạn phải. Nó không phải là "điều đúng" có mục đích chung để làm với các lớp học theo phong cách mới mà bạn có thể nghi ngờ.

Có những lúc bạn đang mong đa kế thừa và bạn có thể muốn nó, nhưng cho đến khi bạn biết các chi tiết lông của MRO, để lại nó một mình tốt nhất và dính vào:

X.a(self) 
+2

là đúng bởi vì trong 6 tháng của tôi Python/Django tôi đã sử dụng siêu như là "quyền chung để làm"? – philgo20

+1

Vâng, nó không * làm tổn thương * bạn đối với việc thừa kế đơn lẻ trong chính nó (ngoại trừ việc nó hơi chậm hơn một chút), nhưng nó cũng không tự mình làm gì cả. Bạn phải thiết kế bất kỳ phương thức nào cần nhân kế thừa (đáng chú ý nhất là '__init__') để truyền qua các đối số một cách sạch sẽ và hợp lý, nếu không bạn sẽ nhận được các vấn đề về Loại hoặc các vấn đề gỡ lỗi tồi tệ hơn khi ai đó cố gắng nhân thừa kế thừa bằng cách sử dụng lớp của bạn . Trừ khi bạn thực sự được thiết kế để hỗ trợ MI theo cách này (điều này khá phức tạp), có lẽ tốt hơn nên tránh hàm ý 'super' có phương thức là MI-safe. – bobince

1

Tôi đã thử các các phương thức Xa() khác nhau; tuy nhiên, họ dường như yêu cầu một thể hiện của X để thực hiện một(), vì vậy tôi đã làm X() một (tự), mà dường như hoàn chỉnh hơn các câu trả lời trước đó, ít nhất là cho các ứng dụng tôi đã gặp phải. Nó không có vẻ là một cách tốt để xử lý vấn đề là có xây dựng và phá hủy không cần thiết, nhưng nó hoạt động tốt.

Ứng dụng cụ thể của tôi là mô-đun cmd.Cmd của Python, rõ ràng không phải là đối tượng NewStyle vì một lý do nào đó.

Kết quả cuối cùng:

X().a(self) 
3

Trong trường hợp không ai trong số các câu trả lời trên đề cập đến nó rõ ràng. Lớp cha của bạn cần phải kế thừa từ "đối tượng", mà về cơ bản sẽ biến nó thành một lớp kiểu mới.

# python 3.x: 
class ClassName(object): # This is a new style class 
    pass 

class ClassName: # This is also a new style class (implicit inheritance from object) 
    pass 

# Python 2.x: 
class ClassName(object): # This is a new style class 
    pass 

class ClassName:   # This is a old style class 
    pass 
Các vấn đề liên quan