Câu hỏi Gọi classmethod của lớp cơ sở trong Python


Xem xét 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.dotôi gọi như thế nào Base.do?

Tôi thường sử dụng super hoặc thậm chí tên lớp cơ sở trực tiếp 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) bản in Base lớp thay vì Derived lớp học.


76
2017-08-12 23:07


gốc


Liên quan: Làm thế nào để gọi một phương thức của lớp cha mẹ từ lớp con trong python? - Piotr Dobrogost


Các câu trả lời:


Nếu bạn đang sử dụng một lớp kiểu mới (tức là có nguồn gốc từ object trong Python 2, hoặc luôn luôn bằng Python 3), bạn có thể làm điều đó với super() như thế này:

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 cls được đặt thành lớp dẫn xuất.


86
2017-08-12 23:09



uh uh .. làm thế nào đến nó không bao giờ xảy ra với tôi rằng tôi có thể sử dụng super trên classmethods quá. - Sridhar Ratnakumar
điều này chỉ hoạt động (do một giới hạn áp đặt bởi siêu) nếu cơ sở xuất phát từ đối tượng, phải không? bạn sẽ làm gì nếu không phải vậy? - ars-longa-vita-brevis
Vâng, điều này chỉ hoạt động cho các lớp học theo phong cách mới, bắt nguồn từ object. (ít nhất là trong Python 2, nhưng trong Py3 tôi nghĩ tất cả các lớp là kiểu mới, IIRC) Nếu không bạn phải làm Base.do(self, ...), Tôi nghĩ, qua đó mã hóa cứng tên của siêu lớp. - David Z
Phía trong Derived.do(), không phải cls giống như Derived? - Ray
@Ray Nếu nó thực sự là một thể hiện của Derived nhưng không phải của một phân lớp, sau đó có. - David Z


đ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 unbound gốc đượ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')

10
2018-04-15 21:01



Lưu ý: Cách tiếp cận này hoạt động đối với các lớp kiểu cũ khi siêu () không hoạt động - Alex Q
Cũng có sẵn dưới dạng __func__ trong python 2.7 và 3 - dtheodor


Điều này làm việc cho tôi:

Base.do('hi')

-2
2017-08-12 23:12



Các cls đối số sau đó sẽ bị ràng buộc Base thay vì Derived - Sridhar Ratnakumar
những gì làm việc cho tôi là điều này - trông rất giống với câu trả lời của Ned: ở đây tự xuất phát từ QGraphicsView có paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent) - user192127