关于python的继承的一个疑问
迷茫
迷茫 2017-04-18 10:28:50
0
3
894

如图所示,B 类继承了 A 类;

当实例化对象时,B 类中没有构造函数, 应该调用父类的构造函数 __init__

但是里边的 self.__pirv() 为啥调用到父类 A__priv, 而 self.pub() 又调到 B 中的 pub

求解?

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

membalas semua(3)
左手右手慢动作

Dalam Python, nama kaedah yang bermula dari __ bukan peribadi __ bermaksud untuk membiarkan Python melakukan nama mangling. Anda tidak seharusnya menulis ganti menggunakan kaedah ini. Jika anda mahu subkelas menimpa kaedah, anda hanya boleh menggunakan _, bukan __

大家讲道理

Setelah memikirkan soalan ini seketika, inilah pemahaman saya:

class A(object):
    def __init__(self):
        self.__priv()  # _A__priv()
        self.pub()

    def __priv(self):
        print("private A")

    def pub(self):
        print("public A")


class B(A):
    def __init__(self):
        self.__priv()    # 调用_B__priv()对比
        super(B, self).__init__()  # 在这里显式调用父类的`__init__()`方法

    def __priv(self):
        print("private B")

    def pub(self):
        print("public B")


if __name__ == '__main__':
    b = B()

Apabila contoh subkelas memanggil kaedah __init__(), ia mencari kaedah B daripada subkelas pub() itu sendiri jelas wujud, jadi kaedah B kelas pub() itu sendiri akan dipanggil; walau bagaimanapun, dalam Apabila memanggil kaedah __priv(), disebabkan penyesuaian nama Python ahli persendirian, apa yang sebenarnya anda panggil ialah kaedah _A__priv(), dan tiada kaedah sedemikian dalam B kelas, dan sesetengahnya hanya mempunyai _B__priv() , jadi A dalam kelas induk _A__priv() dipanggil, menghasilkan keputusan ini. Ini pemahaman peribadi saya, mohon betulkan jika saya salah, terima kasih.

巴扎黑

Bagi masalah itu sendiri, @Xavier dan @Christoph telah menjelaskannya secara terperinci


Jika anda masih tidak faham, anda boleh mencuba ini:

Kod asal:

class A:
    def __init__(self):
        self.__priv() # 等等改成 self._A__priv()
        self.public()
    def __priv(self): # 等等改成 def _A__priv(self):
        print('private of A')
    def public(self):
        print('public of A')
        
class B(A):
    def __priv(self): # 等等改成 self._B__priv(self):
        print('private of B')
    def public(self):
        print('public of B')
        
b = B()

Lakukan secara manual namakan mangling:

class A:
    def __init__(self):
        self._A__priv()
        self.public()
    def _A__priv(self):
        print('private of A')
    def public(self):
        print('public of A')
        
class B(A):
    def _B__priv(self):
        print('private of B')
    def public(self):
        print('public of B')
        
b = B()

B di sini mewarisi semua sifat A termasuk:

  • __init__

  • _A__priv

  • public

dan B mentakrifkan diri mereka sendiri:

  • _B__priv

  • public (A's public ditimpa di sini)

Jadi akhirnya anda akan melihat dir(b) yang mengandungi:

  • __init__ (diwarisi daripada A)

  • _A__priv (diwarisi daripada A)

  • _B__priv (takrifan anda sendiri)

  • public (takrifan anda sendiri)

Akhir sekali, apabila __init__ dipanggil, _A__priv akan dipanggil dan B mempunyai kaedah ini di dalam


Saya ingin menambah bahawa Python itu sendiri tidak mempunyai mekanisme peribadi yang sebenar, kerana orang yang memahami name mangling boleh mengakses atribut bermula dengan garis bawah berganda Sebagai contoh, saya boleh menulis dengan mudah:

a = A()
a._A__priv() # 防都防不住

Ringkasnya, mekanisme ini ialah:

  • Mekanisme anti-bodoh bukan mekanisme anti-penjahat,

  • Mekanisme untuk mencegah akses secara tidak sengaja, bukan mekanisme untuk menghalang akses yang disengajakan

Tetapi tidak semua orang berpendapat mekanisme ini bagus (saya secara peribadi tidak menyukainya. Menggunakan garis bawah berganda untuk memulakan nama adalah menyusahkan dan tidak begitu membantu), jadi anda boleh menemuinya dalam banyak kod python: Orang sering gunakan A single bottom line kaedah perlindungan pada mulanya, pendekatan ini adalah amalan yang diiktiraf (Nota 1), ia sudah cukup untuk mengelakkan orang bodoh untuk pengaturcara yang berpengalaman sedikit, dan tidak akan ada kesan tambahan atau situasi yang tidak dijangka Kejadian

Ian Bicking mempunyai petikan yang mengatakan ini (Ian Bicking ialah pakar Python, saya melihat petikan ini dalam Fluent Python Luciano Ramalho):

Jangan sekali-kali menggunakan dua baris asas di hadapannya. Ini sangat mementingkan diri sendiri, dan jika anda tidak mahu mencipta konflik nama (Nota 2), anda boleh membentuk semula nama secara eksplisit (cth: _MyThing_blahblah). Perkara Penting Ini adalah perkara yang sama seperti menggunakan garis bawah berganda, tetapi ia adalah umum, manakala garis bawah berganda ialah tingkah laku peribadi.

Jadi cadangan saya ialah, menggunakan _priv akan menjadi pilihan yang lebih baik.


Nota 1: Atribut yang bermula dengan garis bawah tunggal tidak mempunyai sebarang sifat istimewa Ia hanyalah teknik simbolik yang bergantung pada konsensus pengaturcara Python, sama seperti beberapa bahasa​​​menggunakan const untuk Menandai pemalar. kita juga boleh bergantung hanya pada konsensus pemalar menggunakan penamaan huruf besar untuk mengelakkan situasi yang tidak dijangka

Nota 2: Sebab anda ingin melindungi atribut dengan sifat peribadi ialah sebab yang paling biasa ialah akses tidak sengaja yang disebabkan oleh konflik nama


Soalan yang saya jawab: Python-QA

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan