เรียกใช้เมธอดคลาสของคลาสพื้นฐานใน Python


105

พิจารณารหัสต่อไปนี้:

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

จากDerived.doฉันจะโทรBase.doอย่างไร?

โดยปกติฉันจะใช้superหรือแม้แต่ชื่อคลาสฐานโดยตรงหากนี่เป็นเมธอดอ็อบเจ็กต์ปกติ แต่ดูเหมือนว่าฉันไม่สามารถหาวิธีเรียกเมธอดคลาสในคลาสฐานได้

ในตัวอย่างข้างต้นBase.do(a)พิมพ์BaseคลาสแทนDerivedคลาส


คำตอบ:


121

หากคุณใช้คลาสสไตล์ใหม่ (เช่นมาจากobjectใน Python 2 หรือเสมอใน Python 3) คุณสามารถทำได้super()ดังนี้

super(Derived, cls).do(a)

นี่คือวิธีที่คุณจะเรียกใช้โค้ดในเมธอดเวอร์ชันฐานของคลาสพื้นฐาน (เช่นprint cls, a) จากคลาสที่ได้รับโดยclsถูกตั้งค่าเป็นคลาสที่ได้รับ


8
เอ่อเอ่อ .. ทำไมมันไม่เคยเกิดขึ้นกับฉันเลยว่าฉันสามารถใช้วิธีการเรียนได้superด้วย
Sridhar Ratnakumar

ใช้งานได้เท่านั้น (เนื่องจากข้อ จำกัด ที่กำหนดโดย super) ถ้าฐานมาจากวัตถุใช่ไหม? คุณจะทำอย่างไรถ้าไม่เป็นเช่นนั้น?
ars-longa-vita-brevis

objectใช่นี้จะทำงานเฉพาะสำหรับการเรียนแบบใหม่ซึ่งเป็นผลมาจาก (อย่างน้อยใน Python 2 แต่ใน Py3 ฉันคิดว่าคลาสทั้งหมดเป็นรูปแบบใหม่ IIRC) ไม่งั้นคุณต้องทำBase.do(self, ...)ฉันคิดว่าด้วยเหตุนี้การเข้ารหัสชื่อของซูเปอร์คลาส
David Z

ข้างในDerived.do()ไม่clsเหมือนกับDerived?
Ray

@Ray ถ้ามันเป็นอินสแตนซ์Derivedแต่ไม่ใช่ของคลาสย่อยก็ใช่
David Z

15

นี่เป็นเวลานานแล้ว แต่ฉันคิดว่าฉันอาจพบคำตอบแล้ว เมื่อคุณตกแต่งเมธอดให้กลายเป็นคลาสเมธอด unbound ดั้งเดิมจะถูกเก็บไว้ในคุณสมบัติชื่อ '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
หมายเหตุ: วิธีนี้ใช้ได้กับคลาสแบบเก่าที่ super () ใช้ไม่ได้
Alex Q

2
นอกจากนี้ยังมี__func__ใน python 2.7 และ 3
dtheodor

-3

สิ่งนี้ใช้ได้กับฉัน:

Base.do('hi')

9
clsอาร์กิวเมนต์จะถูกผูกไว้กับBaseแทนDerived
Sridhar Ratnakumar

สิ่งที่เหมาะกับฉันคือสิ่งนี้ - ซึ่งดู (มาก) เหมือนคำตอบของ Ned: โดยที่ตัวเองได้มาจาก QGraphicsView ซึ่งมี paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.