Memanggil metode kelas kelas dasar dengan Python

105

Perhatikan kode berikut:

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

Dari Derived.do, bagaimana cara menelepon Base.do?

Saya biasanya akan menggunakan superatau bahkan nama kelas dasar secara langsung jika ini adalah metode objek normal, tetapi tampaknya saya tidak dapat menemukan cara untuk memanggil metode kelas di kelas dasar.

Dalam contoh di atas, Base.do(a)mencetak Basekelas, bukan Derivedkelas.

Sridhar Ratnakumar
sumber

Jawaban:

121

Jika Anda menggunakan kelas gaya baru (yaitu berasal dari objectPython 2, atau selalu dengan Python 3), Anda dapat melakukannya dengan super()seperti ini:

super(Derived, cls).do(a)

Ini adalah bagaimana Anda akan memanggil kode dalam versi kelas dasar dari metode (yaitu print cls, a), dari kelas turunan, dengan clsdisetel ke kelas turunan.

David Z
sumber
8
uh uh .. kenapa tidak pernah terpikir olehku bahwa aku bisa menggunakan supermetode kelas juga.
Sridhar Ratnakumar
ini hanya berfungsi (karena batasan yang diberlakukan oleh super) jika alasnya berasal dari objek, bukan? apa yang kamu lakukan jika bukan itu masalahnya?
ars-longa-vita-brevis
Ya, ini hanya berfungsi untuk kelas gaya baru, yang berasal dari object. (setidaknya di Python 2, tetapi di Py3 saya pikir semua kelas bergaya baru, IIRC) Jika tidak, Anda harus melakukannya Base.do(self, ...), saya pikir, dengan demikian meng -hard-coding nama superclass.
David Z
Di dalam Derived.do(), bukankah clssama dengan Derived?
Ray
@Ray Jika ini sebenarnya adalah turunan dari Derivedtetapi bukan dari subkelas, maka ya.
David Z
15

ini sudah lama, tetapi saya pikir saya mungkin telah menemukan jawabannya. Saat Anda mendekorasi metode untuk menjadi metode kelas, metode tak terikat asli disimpan di properti bernama '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')
Nikolas
sumber
2
Catatan: Pendekatan ini berfungsi untuk kelas gaya lama di mana super () tidak berfungsi
Alex Q
2
Juga tersedia seperti __func__pada python 2.7 dan 3
dtheodor
-3

Ini bekerja untuk saya:

Base.do('hi')
Ned Batchelder
sumber
9
The clsArgumen kemudian akan terikat BasebukanDerived
Sridhar Ratnakumar
apa yang berhasil bagi saya adalah ini - yang terlihat (sangat) seperti jawaban Ned: di mana self berasal dari QGraphicsView yang memiliki paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
pengguna192127