2011-02-03 18 views
8

Tôi thường làm điều này khi trọng một phương pháp trong một lớp học phụ:Shortcut cho siêu (loại (tự), tự)

def method_x(self): 
    x = super(type(self), self).method_x() 

    [Some extra code] 
    return x 

Câu hỏi của tôi là: Có một cắt ngắn cho siêu (loại (tự) , tự)?

+14

Cảnh báo với bất kỳ ai đọc điều này: mã ở trên là * sai *. Đừng bắt chước nó! –

+0

Glenn, Duncan: cảm ơn vì đã chỉ ra rằng điều này là sai. Tôi sẽ phải grep mã của tôi và thay đổi điều này. –

+0

@Glenn Maynard: Không chắc tôi hiểu tại sao bạn coi nó * sai *. Liệu có sử dụng 'siêu (self .__ class__, self) 'có tốt hơn không? – martineau

Trả lời

17

Đừng làm điều đó: nếu super chỉ có thể sử dụng type(self) làm đối số đầu tiên của nó thì nó sẽ không được viết để lấy hai đối số ngay từ đầu. Bạn phải vượt qua lớp thực tế ở đây không phải là một biểu thức có thể thay đổi nếu lớp đã được phân lớp.

Đối số đầu tiên cho siêu cần phải là lớp chứa định nghĩa phương thức hiện tại khi bạn đang nói siêu trong danh sách cơ sở để bắt đầu tìm kiếm của nó.

Python 3 biết về điều này và xử lý super() một cách kỳ diệu vào thời gian biên dịch, nhưng trong Python 2.x nó chỉ là một hàm bình thường để nó không có cách nào tìm ra các tham số đó.

[Chỉnh sửa để thêm vào điểm ban đầu của tôi] Thực ra, có một cách ít được sử dụng hơn để sử dụng super() bằng Python 2.x. Bạn có thể sử dụng một hình thức ràng buộc của siêu và có nó ràng buộc khi bạn truy cập vào nó:

>>> class A(object): 
    def foo(self): 
     print "A.foo" 


>>> class B(A): 
    def foo(self): 
     self.__super.foo() 
     print "B.foo" 


>>> B._B__super = super(B) 
>>> class C(A): 
    def foo(self): 
     self.__super.foo() 
     print "C.foo" 


>>> C._C__super = super(C) 
>>> class D(C,B): pass 

>>> D._D__super = super(D) 
>>> D().foo() 
A.foo 
B.foo 
C.foo 

Có một bắt quan trọng ở đây: bạn phải sử dụng một tên khác để lưu trữ mỗi super đối tượng, mà bạn có thể thực hiện bằng cách sử dụng self.__super, nhưng bạn không thể tạo trực tiếp super không trực tiếp trong định nghĩa lớp (vì bạn không thể đặt tên cho lớp nếu nó chưa tồn tại) và nếu bạn tạo lớp bên ngoài, bạn phải tự xáo trộn tên để đảm bảo bạn đã đặt đúng __super đối tượng cho lớp học. Đối với Python 2.6 và phiên bản mới hơn, bạn có thể quấn nó lên như một trình trang trí lớp.

+1

Tôi khuyên bạn không đề xuất điều này; nó không phải là một chiến thắng để làm một cái gì đó rất bất thường. –

+2

Vâng, đó là lộn xộn mà có lẽ là lý do tại sao nó ít được sử dụng, nhưng tôi nghĩ tôi nên đề cập đến nó như là một lựa chọn. Một lựa chọn tốt hơn tất nhiên là chỉ sử dụng Python 3.x (tùy thuộc vào nó hỗ trợ bất cứ thư viện nào bạn cần) – Duncan

+0

Tôi đã xem xét sử dụng python3 hôm nay. Tôi đang sử dụng Pylons Pyramid và nó và một số phụ thuộc của nó không hỗ trợ py3, vì vậy tôi sẽ phải kiểm tra lại sau một vài tháng. –

Các vấn đề liên quan