Gọi classmethod của lớp cơ sở bằng Python


105

Hãy xem xét đoạn mã sau:

class Base(object):

    @classmethod
    def do(cls, a):
        print cls, a

class Derived(Base):

    @classmethod
    def do(cls, a):
        print 'In derived!'
        # Base.do(cls, a) -- can't pass `cls`
        Base.do(a)

if __name__ == '__main__':
    d = Derived()
    d.do('hello')

> $ python play.py  
> In derived! 
> <class '__main__.Base'> msg

Từ Derived.do, làm thế nào để tôi gọi Base.do?

Tôi thường sử dụng superhoặc thậm chí trực tiếp tên lớp cơ sở nếu đây là một phương thức đối tượng bình thường, nhưng dường như tôi không thể tìm thấy cách gọi classmethod trong lớp cơ sở.

Trong ví dụ trên, Base.do(a)in Baselớp thay vì Derivedlớp.


Câu trả lời:


121

Nếu bạn đang sử dụng một lớp kiểu mới (nghĩa là bắt nguồn từ objectPython 2 hoặc luôn trong Python 3), bạn có thể làm điều đó với super()như sau:

super(Derived, cls).do(a)

Đây là cách bạn sẽ gọi mã trong phiên bản của lớp cơ sở của phương thức (tức là print cls, a), từ lớp dẫn xuất, với clsviệc được đặt thành lớp dẫn xuất.


8
uh uh .. tại sao nó không bao giờ xảy ra với tôi mà tôi cũng có thể sử dụng supertrên classmethods.
Sridhar Ratnakumar

điều này chỉ hoạt động (do một giới hạn áp đặt bởi super) nếu cơ sở bắt nguồn từ đối tượng, phải không? bạn sẽ làm gì nếu không phải như vậy?
ars-longa-vita-brevis

Vâng, điều này chỉ hoạt động cho các lớp kiểu mới, bắt nguồn từ object. (ít nhất là trong Python 2, nhưng trong Py3, tôi nghĩ rằng tất cả các lớp đều là kiểu mới, IIRC) Nếu không thì bạn phải làm như vậy Base.do(self, ...), tôi nghĩ vậy, bằng cách đó, hãy mã hóa tên của lớp cha.
David Z

Bên trong Derived.do(), không clsgiống như Derived?
Ray

@Ray Nếu nó thực sự là một thể hiện của Derivednhưng không phải của một lớp con, thì có.
David Z

15

điều này đã được một thời gian, nhưng tôi nghĩ rằng tôi có thể đã tìm thấy một câu trả lời. Khi bạn trang trí một phương thức trở thành một classmethod, phương thức không liên kết ban đầu được lưu trữ trong một thuộc tính có tên 'im_func':

class Base(object):
    @classmethod
    def do(cls, a):
        print cls, a

class Derived(Base):

    @classmethod
    def do(cls, a):
        print 'In derived!'
        # Base.do(cls, a) -- can't pass `cls`
        Base.do.im_func(cls, a)

if __name__ == '__main__':
    d = Derived()
    d.do('hello')

2
Lưu ý: Cách tiếp cận này hoạt động đối với các lớp kiểu cũ nơi super () không hoạt động
Alex Q

2
Cũng có sẵn như __func__trong python 2.7 và 3
dtheodor

-3

Điều này phù hợp với tôi:

Base.do('hi')

9
Các clstranh luận sau đó sẽ bị ràng buộc để Basethay vìDerived
Sridhar Ratnakumar

cái này phù hợp với tôi - trông (rất nhiều) giống như câu trả lời của Ned: nơi tự lấy từ QGraphicsView có paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127
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.