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 __
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 bahasamenggunakan 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
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:
Apabila contoh subkelas memanggil kaedah
__init__()
, ia mencari kaedahB
daripada subkelaspub()
itu sendiri jelas wujud, jadi kaedahB
kelaspub()
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 dalamB
kelas, dan sesetengahnya hanya mempunyai_B__priv()
, jadiA
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:
Lakukan secara manual namakan mangling:
B
di sini mewarisi semua sifatA
termasuk:__init__
_A__priv
public
dan
B
mentakrifkan diri mereka sendiri:_B__priv
public
(A
'spublic
ditimpa di sini)Jadi akhirnya anda akan melihat
dir(b)
yang mengandungi:__init__
(diwarisi daripadaA
)_A__priv
(diwarisi daripadaA
)_B__priv
(takrifan anda sendiri)public
(takrifan anda sendiri)Akhir sekali, apabila
__init__
dipanggil,_A__priv
akan dipanggil danB
mempunyai kaedah ini di dalamSaya 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:
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):
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 bahasamenggunakan
const
untuk Menandai pemalar. kita juga boleh bergantung hanya pada konsensus pemalar menggunakan penamaan huruf besar untuk mengelakkan situasi yang tidak dijangkaNota 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