super()
Hành vi ma thuật mới đã được thêm vào để tránh vi phạm nguyên tắc DRY (Đừng lặp lại chính mình), xem PEP 3135 . Phải đặt tên một cách rõ ràng cho lớp bằng cách gọi nó là toàn cầu cũng dễ xảy ra các vấn đề phản hồi giống như bạn đã phát hiện ra với super()
chính nó:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
Điều tương tự cũng áp dụng cho việc sử dụng các trình trang trí lớp trong đó trình trang trí trả về một đối tượng mới, trong đó đặt lại tên lớp:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
super()
__class__
Tế bào ma thuật vượt qua những vấn đề này một cách độc đáo bằng cách cho phép bạn truy cập vào đối tượng lớp ban đầu.
PEP đã được khởi động bởi Guido, người ban đầu hình dung super
trở thành một từ khóa và ý tưởng sử dụng một tế bào để tra cứu lớp hiện tại cũng là của anh ấy . Chắc chắn, ý tưởng biến nó thành một từ khóa là một phần của dự thảo đầu tiên của PEP .
Tuy nhiên, trên thực tế, chính Guido, người sau đó đã từ bỏ ý tưởng từ khóa là 'quá kỳ diệu' , đề xuất việc triển khai hiện tại thay thế. Ông dự đoán rằng việc sử dụng một tên khác super()
có thể là một vấn đề :
Bản vá của tôi sử dụng một giải pháp trung gian: nó giả sử bạn cần __class__
bất cứ khi nào bạn sử dụng một biến có tên 'super'
. Do đó, nếu bạn (toàn cầu) đổi tên super
thành supper
và sử dụng supper
nhưng không super
, nó sẽ không hoạt động mà không có đối số (nhưng nó vẫn hoạt động nếu bạn vượt qua nó
__class__
hoặc đối tượng lớp thực tế); nếu bạn có một biến không liên quan được đặt tên super
, mọi thứ sẽ hoạt động nhưng phương thức sẽ sử dụng đường dẫn cuộc gọi chậm hơn một chút được sử dụng cho các biến di động.
Vì vậy, cuối cùng, chính Guido đã tuyên bố rằng sử dụng super
từ khóa không cảm thấy đúng và việc cung cấp một __class__
tế bào ma thuật là một sự thỏa hiệp chấp nhận được.
Tôi đồng ý rằng sự kỳ diệu, hành vi ngầm của việc thực hiện có phần đáng ngạc nhiên, nhưng super()
là một trong những chức năng được áp dụng sai nhất trong ngôn ngữ. Chỉ cần nhìn vào tất cả các ứng dụng sai super(type(self), self)
hoặc super(self.__class__, self)
tìm thấy trên Internet; nếu bất kỳ mã nào được gọi từ một lớp dẫn xuất, bạn sẽ kết thúc bằng một ngoại lệ đệ quy vô hạn . Ít nhất là super()
cuộc gọi được đơn giản hóa , không có đối số, sẽ tránh được vấn đề đó .
Đối với việc đổi tên super_
; chỉ cần tham khảo __class__
trong phương pháp của bạn cũng và nó sẽ hoạt động trở lại. Ô được tạo nếu bạn tham chiếu tên super
hoặc __class__
tên trong phương thức của mình:
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping