පයිතන්ගේ සුපිරි () බහු උරුමය සමඟ ක්‍රියා කරන්නේ කෙසේද?


917

මම පයිතන් වස්තු දිශානත ක්‍රමලේඛනයේ බොහෝ සෙයින් අලුත් වන අතර මට එය තේරුම් ගැනීමට අපහසුය super() විශේෂයෙන් බහු උරුමයන් ක්‍රියාකාරීත්වය (නව විලාසිතාවේ පන්ති) අපහසුය.

උදාහරණයක් ලෙස ඔබට එවැනි දෙයක් තිබේ නම්:

class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print "that's it"

මට නොලැබෙන දෙය නම්: එසේ වනු ඇත Third() පන්තියට ඉදිකිරීම් ක්‍රම දෙකම උරුම වේද? ඔව් නම්, සුපිරි () සමඟ ධාවනය වන්නේ කුමන එකද සහ ඇයි?

ඔබට අනෙක් එක ධාවනය කිරීමට අවශ්‍ය නම් කුමක් කළ යුතුද? මම දන්නවා එයට පයිතන් ක්‍රම විභේදන අනුපිළිවෙලට ( MRO ) යම් සම්බන්ධයක් තිබෙනවා.


ඇත්ත වශයෙන්ම, super()ඕනෑම ප්‍රයෝජනයක් ඇති එකම අවස්ථාව බහු උරුමයයි . රේඛීය උරුමය භාවිතා කරන පන්ති සමඟ එය භාවිතා කිරීම මම නිර්දේශ නොකරමි.
බච්සෝ

10
Ach බැච්සෝ තාක්ෂණික වශයෙන් නිවැරදියි, එය කුඩා පොදු කාර්යයක් වන නමුත් සුපිරි () වඩා පයිතොනික් වන අතර කාලයත් සමඟ නැවත සාධකකරණයට සහ කේතයට වෙනස් වීමට ඉඩ සලසයි. ඔබට නම් කරන ලද පන්ති විශේෂිත ක්‍රමයක් අවශ්‍ය නම් මිස සුපිරි () භාවිතා කරන්න.
පෝල් විප්

2
මෙහි ඇති තවත් ගැටළුවක් super()නම්, එය සෑම උප පංතියකටම එය භාවිතා කිරීමට බල කරන අතර, භාවිතා නොකරන විට super(), එය උප පංතියේ සිටින සෑම කෙනෙකුටම තමාටම තීරණය කළ හැකිය. එය භාවිතා කරන සංවර්ධකයෙකු එය භාවිතා කළ බව නොදන්නේ නම් super()හෝ නොදන්නේ නම්, mro සමඟ ගැටලු ඇතිවිය හැකි අතර ඒවා සොයා ගැනීම ඉතා අපහසු වේ.
බච්සෝ

මෙහි සෑම පිළිතුරක්ම පාහේ එක් ආකාරයකින් හෝ වෙනත් ආකාරයකින් ව්‍යාකූල බව මට පෙනී ගොස් ඇත. ඒ වෙනුවට ඔබ සැබවින්ම මෙහි යොමු වනු ඇත .
matanster

Answers:


730

ගයිඩෝ විසින්ම ඔහුගේ බ්ලොග් පෝස්ට් ක්‍රමවේදය විසර්ජන නියෝගයෙන් මෙය සවිස්තරාත්මකව සවිස්තරාත්මකව දක්වා ඇත (මීට පෙර උත්සාහයන් දෙකක් ද ඇතුළුව) .

ඔබගේ උදාහරණයේ දී, Third()අමතනු First.__init__ඇත. පංතියේ දෙමව්පියන් වමේ සිට දකුණට ලැයිස්තුගත කර ඇති බැවින් පයිතන් සෑම ගුණාංගයක්ම සොයයි. මෙම අවස්ථාවේ දී, අපි සොයන්නෙමු __init__. එබැවින්, ඔබ අර්ථ දක්වන්නේ නම්

class Third(First, Second):
    ...

Python මීට උදාහරණ දෙස විසින් ආරම්භ වනු ඇත First, සහ, නම් Firstවූ විශේෂණය නැත, එසේ නම් එය දෙස ඇතSecond .

උරුමය මාර්ග තරණය කිරීමට පටන් ගත් විට මෙම තත්වය වඩාත් සංකීර්ණ වේ (නිදසුනක් ලෙස Firstඋරුම වී ඇත්නම්Second ). වැඩි විස්තර සඳහා ඉහත සබැඳිය කියවන්න, නමුත් කෙටියෙන් කිවහොත්, පයිතන් ළමා පන්තියේ සිටම ඇරඹෙන සෑම පන්තියක්ම උරුම ලැයිස්තුවේ දිස්වන අනුපිළිවෙල පවත්වා ගැනීමට උත්සාහ කරයි.

උදාහරණයක් ලෙස, ඔබට තිබුනේ නම්:

class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second"

class Third(First):
    def __init__(self):
        print "third"

class Fourth(Second, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print "that's it"

MRO වනු ඇත [Fourth, Second, Third, First].

මාර්ගය වන විට: පයිතන්ට සුහද ක්‍රමවේද විභේදන අනුපිළිවෙලක් සොයාගත නොහැකි නම්, එය පරිශීලකයා පුදුමයට පත් කළ හැකි හැසිරීම් වලට වැටීම වෙනුවට ව්‍යතිරේකයක් මතු කරයි.

නොපැහැදිලි MRO සඳහා උදාහරණයක් එක් කිරීමට සංස්කරණය කරන ලදි:

class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        print "third"

කළ යුතුයි Third'' ගේ MRO විය [First, Second]හෝ [Second, First]? පැහැදිලි අපේක්ෂාවක් නොමැති අතර, පයිතන් දෝෂයක් මතු කරයි:

TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution order (MRO) for bases Second, First

සංස්කරණය කරන්න: ඉහත උදාහරණ super()ඇමතුම් නොමැති බවට කිහිප දෙනෙක් තර්ක කරන බව මට පෙනේ , එබැවින් මට පැහැදිලි කිරීමට ඉඩ දෙන්න: උදාහරණවල කාරණය වන්නේ MRO ගොඩනඟා ඇති ආකාරය පෙන්වීමයි. ඔවුන් කරන්නේ නෑ "පළමු \ nsecond \ තෙවන" හෝ ඕනෑම දෙයක් මුද්රණය කිරීමට අදහස් කළේය. ඔබට - සහ, ඇත්ත වශයෙන්ම, උදාහරණය සමඟ සෙල්ලම් කළ යුතුය, super()ඇමතුම් එක් කළ යුතුය, සිදුවන්නේ කුමක්දැයි බලන්න, සහ පයිතන්ගේ උරුම ආකෘතිය පිළිබඳ ගැඹුරු අවබෝධයක් ලබා ගත යුතුය. නමුත් මෙහි මගේ ඉලක්කය වන්නේ එය සරලව තබාගෙන MRO ගොඩනගා ඇති ආකාරය පෙන්වීමයි. එය මා විසින් පැහැදිලි කළ පරිදි ගොඩනගා ඇත:

>>> Fourth.__mro__
(<class '__main__.Fourth'>,
 <class '__main__.Second'>, <class '__main__.Third'>,
 <class '__main__.First'>,
 <type 'object'>)

13
පළමු, දෙවන සහ තෙවන [ pastebin.com/ezTyZ5Wa ] හි ඔබ සුපිරි () ඇමතීමට පටන් ගත් විට එය වඩාත් සිත්ගන්නාසුළු (සහ, වඩාත් ව්‍යාකූල) වේ.
gatoatigrado

55
පළමු පන්තියේ සුපිරි ඇමතුම් නොමැතිකම මෙම පිළිතුර සමඟ විශාල ගැටළුවක් යැයි මම සිතමි. ප්‍රශ්නයට වැදගත් විවේචනාත්මක අවබෝධය නැති වන්නේ කෙසේද / ඇයි යන්න සාකච්ඡා නොකර.
සෑම් හාර්ට්මන්

3
මෙම පිළිතුර හුදෙක් වැරදිය. දෙමව්පියන්ගේ සුපිරි () ඇමතුම් නොමැතිව කිසිවක් සිදු නොවේ. less පණ නැති අයගේ පිළිතුර නිවැරදි ය.
සෙරින්

9
ErCerin මෙම උදාහරණයේ කාරණය වන්නේ MRO ඉදිකර ඇති ආකාරය පෙන්වීමයි. උදාහරණය "පළමු \ nse තත්පර \ තෙවන" හෝ වෙනත් ඕනෑම දෙයක් මුද්‍රණය කිරීමට අදහස් නොකෙරේ. MRO සැබවින්ම නිවැරදි ය: හතරවන .__ mro__ == (<class ' main .Fourth'>, <class ' main .Second'>, <class ' main .Tird'>, <class ' main .First'>, < 'object'> ටයිප් කරන්න)
rbp

2
මට පෙනෙන පරිදි, මෙම පිළිතුර OP හි එක් ප්‍රශ්නයක් මග හැරී ඇත, එය "සහ ඔබට අනෙක් ප්‍රශ්නය ක්‍රියාත්මක කිරීමට අවශ්‍ය නම් කුමක් කළ යුතුද?". මෙම ප්‍රශ්නයට පිළිතුර දැකීමට මා කැමතිය. අපි මූලික පන්තිය පැහැදිලිව නම් කළ යුතුද?
රේ

260

ඔබගේ කේතය සහ අනෙක් පිළිතුරු සියල්ලම දෝෂ සහිතය. ඔවුන් අතුරුදහන්super()සමුපකාර උප පංති වැඩ කිරීම සඳහා අවශ්‍ය වන පළමු පන්ති දෙකේ ඇමතුම් හැරී ඇත.

කේතයේ ස්ථාවර අනුවාදයක් මෙන්න:

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print("first")

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print("second")

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print("third")

මෙම super()ඇමතුම්, පළමු සහ දෙවන ද එය කිරීමට ඇති ඇයි වන එක් එක් පියවර, දී MRO ඉදිරි ක්රමය සම්බ එසේ ක්රියාත්මක අවසානයේ නතරSecond.__init__() .

මට ලැබෙන්නේ මෙයයි:

>>> Third()
second
first
third

96
මෙම පන්ති ආරම්භ කිරීම සඳහා විවිධ පරාමිතීන් අවශ්‍ය නම් කුමක් කළ යුතුද?
වසු පැටවා

3
"සමුපකාර උප පංතිය"
ක්වොන්ට් මෙට්‍රොපොලිස්

6
මේ විදිහට, ඒ , init මුල් උදාහරණයක් පළමු ඇමතුම් පමණි අතර, මේ දෙවර්ගයේ පදනම පන්ති ක්රම ක්රියාත්මක වනු ඇත init මෙම MRO හමු. "සමුපකාර උප පංතිය" යන යෙදුමෙන් එය ගම්‍ය වන බව මම අනුමාන කරමි, නමුත් පැහැදිලි කිරීමක් ප්‍රයෝජනවත් වනු ඇත ('පැහැදිලිව ගම්‍යතාවයට වඩා හොඳයි', ඔබ දන්නවා;))
Quant Metropolis

1
ඔව්, ඔබ විවිධ පරාමිතීන් සුපර් හරහා කැඳවන ක්‍රමයකට යොමු කරන්නේ නම්, එම ක්‍රමයේ සියලුම ක්‍රියාත්මක කිරීම් MRO වස්තුව දෙසට () දෙසට යන විට අනුකූල අත්සන් තිබිය යුතුය. මූල පද පරාමිතීන් හරහා මෙය සාක්ෂාත් කරගත හැකිය: ක්‍රමය භාවිතා කරන ක්‍රමයට වඩා වැඩි පරාමිතීන් භාර ගන්න, සහ අතිරේක ඒවා නොසලකා හරින්න. මෙය සාමාන්‍යයෙන් කැත ලෙස සලකනු ලබන අතර බොහෝ විට නව ක්‍රම එකතු කිරීම වඩා හොඳය, නමුත් init (ආසන්න වශයෙන්?) විශේෂ ක්‍රම නාමයක් ලෙස අද්විතීය නමුත් පරිශීලක අර්ථ දක්වන ලද පරාමිතීන් සමඟ ය.
පණ නැති

17
බහු උරුමයක් නිර්මාණය කිරීම පයිතන්හි ඇත්තෙන්ම නරක ය. එය ලබා ගන්නේ කවුරුන්ද යන්නත්, ව්‍යුත්පන්න කර ඇති වෙනත් පදනම් පංති කීයක්ද, කුමන අනුපිළිවෙලකටද යන්න මූලික පංති පාහේ දැන සිටිය යුතුය ... එසේ superනොමැතිනම් ධාවනය කිරීමට අසමත් වනු ඇත (පරාමිති නොගැලපීම නිසා), නැතහොත් එය අමතන්නේ නැත පදනම් කිහිපයක් (ඔබ superසබැඳිය බිඳෙන එක් පදනමක ලියා නැති නිසා )!
නවාස්

191

පයිතන්හි බහු උරුම ධූරාවලියක් තුළ සුපිරි () භාවිතා කරන්නේ කෙසේද යන්න ගැන කියවීමට පටන් ගත් විට, මට එය වහාම නොලැබුණු හෙයින්, පණ නැති පිළිතුර ටිකක් විස්තර කිරීමට මට අවශ්‍ය විය .

ඔබ තේරුම් ගත යුතු දෙය නම් , සම්පූර්ණ උරුමය ධූරාවලිය තුළ සන්දර්භය තුළ භාවිතා කළ ක්‍රම විභේදන ඇණවුම් කිරීමේ (MRO) ඇල්ගොරිතම අනුව ඊළඟ ක්‍රමය super(MyClass, self).__init__()සපයයි . __init__

මෙම අවසාන කොටස තේරුම් ගැනීමට ඉතා වැදගත් වේ. උදාහරණය නැවත සලකා බලමු:

#!/usr/bin/env python2

class First(object):
  def __init__(self):
    print "First(): entering"
    super(First, self).__init__()
    print "First(): exiting"

class Second(object):
  def __init__(self):
    print "Second(): entering"
    super(Second, self).__init__()
    print "Second(): exiting"

class Third(First, Second):
  def __init__(self):
    print "Third(): entering"
    super(Third, self).__init__()
    print "Third(): exiting"

ගයිඩෝ වැන් රොසුම් විසින් රචිත ක්‍රම විසර්ජන නියෝගය පිළිබඳ මෙම ලිපියට අනුව, විසඳීමේ අනුපිළිවෙල__init__ ගණනය කරනු ලබන්නේ (පයිතන් 2.3 ට පෙර) “ගැඹුරේ පළමු වමේ සිට දකුණට ගමන් කිරීම” භාවිතා කර ය:

Third --> First --> object --> Second --> object

අන්තිම එක හැර, සියලු අනුපිටපත් ඉවත් කිරීමෙන් පසුව, අපට ලැබෙන්නේ:

Third --> First --> Second --> object

එබැවින්, අපි Thirdපන්තියේ නිදසුනක් ක්ෂණිකව කළ විට කුමක් සිදුවේද යන්න අනුගමනය කිරීමට ඉඩ දෙන්න , උදා x = Third().

  1. MRO Third.__init__ක්‍රියාත්මක කරන්නන්ට අනුව .
    • මුද්රණ Third(): entering
    • ඉන්පසු super(Third, self).__init__()ක්‍රියාත්මක වන අතර MRO ප්‍රතිලාභ First.__init__ලෙස හැඳින්වේ.
  2. First.__init__ ක්‍රියාත්මක කරයි.
    • මුද්රණ First(): entering
    • ඉන්පසු super(First, self).__init__()ක්‍රියාත්මක වන අතර MRO ප්‍රතිලාභ Second.__init__ලෙස හැඳින්වේ.
  3. Second.__init__ ක්‍රියාත්මක කරයි.
    • මුද්රණ Second(): entering
    • ඉන්පසු super(Second, self).__init__()ක්‍රියාත්මක වන අතර MRO ප්‍රතිලාභ object.__init__ලෙස හැඳින්වේ.
  4. object.__init__ ක්‍රියාත්මක කරයි (එහි කේතයේ මුද්‍රණ ප්‍රකාශ නොමැත)
  5. ක්‍රියාත්මක කිරීම නැවත Second.__init__මුද්‍රණය වන ස්ථානයට යයිSecond(): exiting
  6. ක්‍රියාත්මක කිරීම නැවත First.__init__මුද්‍රණය වන ස්ථානයට යයිFirst(): exiting
  7. ක්‍රියාත්මක කිරීම නැවත Third.__init__මුද්‍රණය වන ස්ථානයට යයිThird(): exiting

තෙවන () ක්ෂණික කිරීම ප්‍රති results ල ලැබීමට හේතුව මෙයින් විස්තර කෙරේ:

Third(): entering
First(): entering
Second(): entering
Second(): exiting
First(): exiting
Third(): exiting

සංකීර්ණ අවස්ථාවන්හිදී හොඳින් ක්‍රියා කිරීම සඳහා MRO ඇල්ගොරිතම පයිතන් 2.3 සිට වැඩි දියුණු කර ඇත, නමුත් මම සිතන්නේ “ගැඹුරේ පළමු වමේ සිට දකුණට ගමන් කිරීම” + “අන්තිමයන් සඳහා අනුපිටපත් ඉවත් කිරීම” තවමත් බොහෝ අවස්ථාවන්හිදී ක්‍රියාත්මක වන බවයි (කරුණාකර) මෙය එසේ නොවේ නම් අදහස් දක්වන්න). ගයිඩෝ විසින් බ්ලොග් සටහන කියවීමට වග බලා ගන්න!


8
ඇතුළත: ඇයි මම තවමත් තේරෙන්නේ නැහැ init (පළමු, ස්වයං) .__ init __ () ආමන්ත්රණය සුපිරි පළමු වන init බව දේ MRO ආඥාවන් නිසා, දෙවන ක!
user389955

38 user389955 නිර්මාණය කරන ලද වස්තුව තුන්වන වර්ගයට අයත් වන අතර එය සියලු ආරම්භක ක්‍රම ඇත. එබැවින් සෑම සුපිරි ඇමතුමකින්ම MRO විසින් සියළුම අනුපිළිවෙලින් නිශ්චිත අනුපිළිවෙලකට ලැයිස්තුවක් නිර්මාණය කරයි යැයි ඔබ සිතන්නේ නම්, ඔබ අවසානය දක්වා එක් පියවරක් ඉදිරියට යයි.
ශ්‍රීකුමාර් ආර්

16
පියවර 3 ට වැඩි පැහැදිලි කිරීමක් අවශ්‍ය යැයි මම සිතමි: එයින් Thirdඋරුම නොවූයේ නම් Second, පසුව super(First, self).__init__ඇමතුමක් object.__init__ලබා දී ආපසු පැමිණි පසු “පළමුව” මුද්‍රණය කෙරේ. නමුත් නිසා Thirdදෙකම අනුන Firstසහ Secondඒ වෙනුවට ඉල්ලා වඩා, object.__init__පසු First.__init__පමණක් අවසන් ඇමතුමක් බව MRO ආඥාවන් object.__init__, කල් තබා ගන්නා අතර, මුද්රිත ප්රකාශන වල Firstහා Secondතෙක් පැමිණ නැත object.__init__ප්රතිලාභ. සිට Secondකැඳවීමට අවසන් විය object.__init__, එය තුල නැවත Secondඇති ආපසු ඒමට පෙර First.
මවුන්ටන්

1
සිත් ගන්නා සුළු PyCharm මේ සියල්ල (එහි ඉඟි සාකච්ඡාව පරාමිතීන් අධි ඇමතුම් සඳහා එක්ක යන්න ඇති කිරීම පිළිබඳව දැන ගැනීමට පෙනේ. එය හඳුනා එසේ එය, යෙදවුම් covariance සමහර සංකල්පය ඇති List[subclass]ලෙස List[superclass]නම් subclassකිරීමේ උපපංතිය ඇත superclass( Listඑම පැමිණෙන්නේ typingපී.ඊ.පී. 483 මොඩියුලය iirc).
රෙබ් කැබින්

කදිම තනතුරක් නමුත් ඉදිකිරීම්කරුවන්ගේ තර්ක සම්බන්ධයෙන් මට තොරතුරු මග හැරී ඇත, එනම් දෙවන හා පළමුව පැහැදිලි තර්ක බලාපොරොත්තු වන්නේ නම් කුමක් සිදුවේද? පළමු ඉදිකිරීම්කරුට සමහර තර්ක සැකසීමට සිදු වන අතර ඉතිරි කොටස දෙවන දෙසට යොමු කළ යුතුය. ඒක හරිද? දෙවනුව සඳහා අවශ්‍ය තර්ක ගැන පළමුව දැනගත යුතු බව මට නිවැරදි නැත.
ක්‍රිස්ටියන් කේ.

60

මෙය දියමන්ති ගැටලුව ලෙස හැඳින්වේ , පිටුවට පයිතන් පිළිබඳ සටහනක් ඇත, නමුත් කෙටියෙන් කිවහොත්, පයිතන් විසින් සුපිරි පන්තියේ ක්‍රම වමේ සිට දකුණට අමතනු ඇත.


මෙය දියමන්ති ගැටළුව නොවේ. දියමන්ති ගැටලුවට පන්ති හතරක් සම්බන්ධ වන අතර OP හි ප්‍රශ්නයට සම්බන්ධ වන්නේ තුනක් පමණි.
ඉයන් ගුඩ්ෆෙලෝ

154
objectසිව්වන
GP89

29

මෙය ආරම්භ කිරීම සඳහා විවිධ විචල්‍යයන් සමඟ බහු උරුමයක් තිබීම සහ එකම ක්‍රියාකාරී ඇමතුමකින් බහු මිශ්‍රණ තිබීම පිළිබඳ ගැටළුව විසඳීමට මම කටයුතු කළ ආකාරයයි. සම්මත ** ක්වාර්ග් වලට විචල්‍යයන් පැහැදිලිව එක් කිරීමට සහ සුපිරි ඇමතුම් සඳහා අවසාන ලක්ෂ්‍යයක් ලෙස මික්ස්ඉන් අතුරු මුහුණතක් එක් කිරීමට මට සිදු විය.

මෙහි Aයනු දීර්ඝ පදනම පන්තියේ හා Bහා Cකාර්යය ලබා දෙකම කරන MixIn පන්ති f. Aහා Bදෙකම පරාමිතිය බලාපොරොත්තු vඔවුන්ගේ __init__හා Cබලාපොරොත්තු w. ශ්‍රිතය fඑක් පරාමිතියක් ගනී y. Qපන්ති තුනෙන්ම උරුම වේ. සහ MixInFසඳහා මික්සින් අතුරුමුහුණත වේ .BC


class A(object):
    def __init__(self, v, *args, **kwargs):
        print "A:init:v[{0}]".format(v)
        kwargs['v']=v
        super(A, self).__init__(*args, **kwargs)
        self.v = v


class MixInF(object):
    def __init__(self, *args, **kwargs):
        print "IObject:init"
    def f(self, y):
        print "IObject:y[{0}]".format(y)


class B(MixInF):
    def __init__(self, v, *args, **kwargs):
        print "B:init:v[{0}]".format(v)
        kwargs['v']=v
        super(B, self).__init__(*args, **kwargs)
        self.v = v
    def f(self, y):
        print "B:f:v[{0}]:y[{1}]".format(self.v, y)
        super(B, self).f(y)


class C(MixInF):
    def __init__(self, w, *args, **kwargs):
        print "C:init:w[{0}]".format(w)
        kwargs['w']=w
        super(C, self).__init__(*args, **kwargs)
        self.w = w
    def f(self, y):
        print "C:f:w[{0}]:y[{1}]".format(self.w, y)
        super(C, self).f(y)


class Q(C,B,A):
    def __init__(self, v, w):
        super(Q, self).__init__(v=v, w=w)
    def f(self, y):
        print "Q:f:y[{0}]".format(y)
        super(Q, self).f(y)

MRO යනු උරුමය සමඟ කාර්යයන් හරහා විවිධ තර්ක සමඟ කටයුතු නොකරමින් තනිවම ප්‍රමාණවත් මාතෘකාවක් වන බැවින් මෙය වෙනම ප්‍රශ්නෝත්තර පිළිතුරක් විය යුතු යැයි මම සිතමි. (බහු උරුමය ඒ පිළිබඳ විශේෂ අවස්ථාවකි).
පණ නැති

8
න්‍යායාත්මකව, ඔව්. ප්‍රායෝගිකව, පයිතන්හි දියමන්ති උරුමය මට හමු වූ සෑම අවස්ථාවකම මෙම තත්වය මතු වී ඇත, එබැවින් මම එය මෙහි එකතු කළෙමි. දියමන්ති උරුමය පිරිසිදුව වළක්වා ගත නොහැකි සෑම අවස්ථාවකම මම යන්නේ මෙහි සිටය. අනාගත මා සඳහා අමතර සබැඳි කිහිපයක් මෙන්න: rhettinger.wordpress.com/2011/05/26/super-considered-super code.activestate.com/recipes/…
brent.payne

අපට අවශ්‍ය වන්නේ අර්ථාන්විත අර්ථවත් පරාමිති නාම සහිත වැඩසටහන් ය. නමුත් මෙම උදාහරණයේ දී සියලු පරාමිතීන් පාහේ නිර්නාමිකව නම් කර ඇති අතර එමඟින් මුල් ක්‍රමලේඛකයාට කේතය ලේඛනගත කිරීම සහ තවත් ක්‍රමලේඛකයෙකුට කේතය කියවීම වඩාත් අපහසු වනු ඇත.
ආතර්

විස්තරාත්මක නම් සහිත
ගිතුබ් රිපෝ වෙත ඉල්ලීමක්

@ brent.payne මම හිතන්නේ ආතර් අදහස් කළේ ඔබේ සම්පූර්ණ ප්‍රවේශය රඳා පවතින්නේ නම් කරන ලද පරාමිතීන් වෙනුවට args/ භාවිතා කිරීම මත kwargsබවයි.
උපරිම

27

මෙය ප්‍රශ්නයට කෙලින්ම පිළිතුරු නොදෙන බව මට වැටහී ඇත super(), නමුත් එය බෙදා ගැනීමට ප්‍රමාණවත් යැයි මට හැඟේ.

උරුම වූ සෑම පන්තියක්ම කෙලින්ම ඇමතීමට ක්‍රමයක් ද ඇත:


class First(object):
    def __init__(self):
        print '1'

class Second(object):
    def __init__(self):
        print '2'

class Third(First, Second):
    def __init__(self):
        Second.__init__(self)

ඔබ එය මේ ආකාරයෙන් කරන්න නම්, ඔබ මම හොඳට ඉන්නේ ලෙස අතින් එක් එක් කෝල් කරන්නම්, එම සාධාරණ සටහනක් Firsts '' __init__()නමින් කළ නොහැකි වනු ඇත.


5
ඔබ එක් එක් උරුම පන්තියට කතා නොකළ නිසා එය නොකියනු ඇත. ප්රශ්නය නොව නැති බව Firstහා Secondදෙකම තවත් පන්ති උරුම පසුව (න් ආරම්භ වන දියමන්ති ලක්ෂ්යය) මෙම පොදු පන්ති දෙවරක් ලෙස හැඳින්වේ එය සෘජුවම ඉල්ලා ඇත. සුපිරි මෙය වළක්වයි.
ට්‍රයිලරියන්

Ri ට්‍රයිලරියන් ඔව්, මට විශ්වාසයි එය එසේ නොවන බව. කෙසේ වෙතත්, මම නිශ්චිතවම දැන නොසිටි අතර එය ඉතා අසීරු වුවද මම එය කළාක් මෙන් ප්‍රකාශ කිරීමට මට අවශ්‍ය නොවීය. objectදෙවරක් කැඳවීම ගැන එය හොඳ කරුණකි . මම ඒ ගැන හිතුවේ නැහැ. මට අවශ්‍ය වූයේ ඔබ මව් පංති කෙලින්ම අමතන්න.
සීඕක්ස්

අවාසනාවකට මෙන්, init කිසියම් පෞද්ගලික ක්‍රමයකට ප්‍රවේශ වීමට උත්සාහ කරන්නේ නම් මෙය කැඩී යයි :(
එරික් ඇරොනෙස්ටි

24

සමස්ත

සෑම දෙයක්ම පැවත එන්නේ යැයි උපකල්පනය කර object(එය එසේ නොවේ නම් ඔබ තනිවම සිටී), පයිතන් ඔබේ පන්තියේ උරුමය ගස මත පදනම්ව ක්‍රම විභේදන නියෝගයක් (MRO) ගණනය කරයි. MRO දේපල 3 ක් තෘප්තිමත් කරයි:

  • පංතියක දරුවන් දෙමව්පියන් ඉදිරියේ පැමිණේ
  • වම් දෙමව්පියන් නිවැරදි දෙමව්පියන් ඉදිරියේ පැමිණේ
  • පංතියක් MRO හි එක් වරක් පමණක් දිස් වේ

එවැනි ඇණවුම් කිරීමක් නොමැති නම්, පයිතන් දෝෂ. මෙහි අභ්‍යන්තර ක්‍රියාකාරිත්වය පංති පරම්පරාවේ C3 ලයිනරීකරණයකි. ඒ පිළිබඳ සියල්ල මෙතැනින් කියවන්න: https://www.python.org/download/releases/2.3/mro/

මේ අනුව, පහත උදාහරණ දෙකෙහිම, එය:

  1. ළමා
  2. වම
  3. හරි
  4. දෙමාපිය

ක්‍රමයක් හැඳින්වූ විට, එම්ආර්ඕ හි එම ක්‍රමයේ පළමු සිදුවීම ලෙස හැඳින්වේ. එම ක්‍රමය ක්‍රියාත්මක නොකරන ඕනෑම පන්තියක් මඟ හැරී ඇත. superඑම ක්‍රමය තුළ ඇති ඕනෑම ඇමතුමක් MRO හි එම ක්‍රමයේ ඊළඟ සිදුවීම ලෙස හැඳින්වේ. එහි ප්‍රති, ලයක් වශයෙන්, ඔබ උරුමයෙන් පන්ති තබන්නේ කුමන අනුපිළිවෙලටද, සහ ඔබ ඇමතුම් ලබා දුන් ස්ථානයටද වැදගත් වේsuper ක්‍රමවේදයන්ට ඇතුළත් වේ.

superඑක් එක් ක්රමයේ පළමු සමඟ

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        print "parent"

class Left(Parent):
    def __init__(self):
        super(Left, self).__init__()
        print "left"

class Right(Parent):
    def __init__(self):
        super(Right, self).__init__()
        print "right"

class Child(Left, Right):
    def __init__(self):
        super(Child, self).__init__()
        print "child"

Child() නිමැවුම්:

parent
right
left
child

සමග superඑම එක් එක් ක්රමය පසුගිය

class Parent(object):
    def __init__(self):
        print "parent"
        super(Parent, self).__init__()

class Left(Parent):
    def __init__(self):
        print "left"
        super(Left, self).__init__()

class Right(Parent):
    def __init__(self):
        print "right"
        super(Right, self).__init__()

class Child(Left, Right):
    def __init__(self):
        print "child"
        super(Child, self).__init__()

Child() නිමැවුම්:

child
left
right
parent

මම ඔබට ප්රවේශ විය හැකි බව දකින්න Leftභාවිතා super()සිට Child. මට Rightඇතුළතින් ප්‍රවේශ වීමට අවශ්‍ය යැයි සිතමු Child. ප්රවේශ කිරීමට ක්රමයක් තිබේද Rightසිට Childසුපිරි භාවිතා? නැත්නම් මම කෙලින්ම Rightඇතුළතින් කතා කළ superයුතුද?
alpha_989

4
class alpha_989 ඔබට කිසියම් පන්තියක ක්‍රමයට පමණක් ප්‍රවේශ වීමට අවශ්‍ය නම්, ඔබ සුපිරි භාවිතා කරනවාට වඩා එම පන්තිය කෙලින්ම යොමු කළ යුතුය. සුපර් යනු නිශ්චිත පන්තියේ ක්‍රමයකට නොපැමිණීම, උරුමයේ දාමය අනුගමනය කිරීමයි.
සැග්ස්

1
'පංතියක් MRO හි එක් වරක් පමණක් දිස්වේ' යනුවෙන් පැහැදිලිව සඳහන් කිරීම ගැන ස්තූතියි. මෙය මගේ ගැටලුව විසඳීය. බහු උරුමය ක්‍රියාත්මක වන ආකාරය දැන් මට අවසාන වශයෙන් වැටහී ඇත. MRO හි ගුණාංග සඳහන් කිරීමට යමෙකුට අවශ්‍ය විය!
තුෂාර් වජිරානි

19

ගැන @ calfzhou ගේ අදහස් , ඔබ සාමාන්යයෙන් ලෙස, භාවිතා කළ හැකි, **kwargs:

මාර්ගගත ධාවන උදාහරණය

class A(object):
  def __init__(self, a, *args, **kwargs):
    print("A", a)

class B(A):
  def __init__(self, b, *args, **kwargs):
    super(B, self).__init__(*args, **kwargs)
    print("B", b)

class A1(A):
  def __init__(self, a1, *args, **kwargs):
    super(A1, self).__init__(*args, **kwargs)
    print("A1", a1)

class B1(A1, B):
  def __init__(self, b1, *args, **kwargs):
    super(B1, self).__init__(*args, **kwargs)
    print("B1", b1)


B1(a1=6, b1=5, b="hello", a=None)

ප්‍රති ult ලය:

A None
B hello
A1 6
B1 5

ඔබට ඒවා ස්ථානීයව භාවිතා කළ හැකිය:

B1(5, 6, b="hello", a=None)

නමුත් ඔබ MRO මතක තබා ගත යුතුයි, එය ඇත්තෙන්ම අවුල් සහගතයි. මූල පද පමණක් පරාමිතීන් භාවිතා කිරීමෙන් ඔබට මෙය වළක්වා ගත හැකිය :

class A(object):
  def __init__(self, *args, a, **kwargs):
    print("A", a)

etcetera.

මට ටිකක් කරදර කාරී විය හැකි නමුත්, මිනිසුන් භාවිතා කිරීමට සෑම අවස්ථාවකම අමතක වූ බවත්, ඔවුන් ක්‍රමවේදයක් අභිබවා *argsයන **kwargsවිටත්, මෙම 'මැජික් විචල්‍යයන්' භාවිතා කිරීම ඇත්තෙන්ම ප්‍රයෝජනවත් හා බුද්ධිමත් භාවිතයන්ගෙන් එකක් බව මම දුටුවෙමි .


1
ඇවැත්නි, එය ඇත්තෙන්ම කැතයි. ඔබට ඇමතිය යුත්තේ කුමන විශේෂිත සුපිරි පන්තියදැයි ඔබට කිව නොහැකි වීම ලැජ්ජාවකි. කෙසේ වෙතත්, මෙය මට සංයුතිය භාවිතා කිරීමට සහ වසංගතය වැනි බහු උරුමයන් මග හැරීමට ඊටත් වඩා දිරිගැන්වීමක් ලබා දෙයි.
ටොම් බස්බි

ටොම්බස්බි: හොඳයි, මම එකඟයි. න්යාය තුල, ඔබ අර්ථ දැක්විය හැකි __new__එය තුල හා කතා B.__new__()උදාහරණයක් ලෙස, සහ, __init__ඇමතුමක් B.__init__(). නමුත් එය අතිරික්තයකි ...
මාකෝ සුල්ලා

15

තවම ආවරණය නොවූ තවත් කරුණක් වන්නේ පන්ති ආරම්භ කිරීම සඳහා පරාමිතීන් සම්මත කිරීමයි. ගමනාන්තයේ සිටsuper උප පංතිය මත රඳා පවතින පරාමිතීන් පසු කිරීමට ඇති එකම හොඳ ක්‍රමය ඒවා සියල්ලම එකට ඇසුරුම් කිරීමයි. එකම පරාමිති නාමය විවිධ අර්ථයන් නොතිබීමට වගබලා ගන්න.

උදාහරණයක්:

class A(object):
    def __init__(self, **kwargs):
        print('A.__init__')
        super().__init__()

class B(A):
    def __init__(self, **kwargs):
        print('B.__init__ {}'.format(kwargs['x']))
        super().__init__(**kwargs)


class C(A):
    def __init__(self, **kwargs):
        print('C.__init__ with {}, {}'.format(kwargs['a'], kwargs['b']))
        super().__init__(**kwargs)


class D(B, C): # MRO=D, B, C, A
    def __init__(self):
        print('D.__init__')
        super().__init__(a=1, b=2, x=3)

print(D.mro())
D()

ලබා දෙයි:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D.__init__
B.__init__ 3
C.__init__ with 1, 2
A.__init__

__init__පරාමිතීන් වඩාත් direct ජුව පැවරීම සඳහා සුපිරි පන්තිය කෙලින්ම කැඳවීම පෙළඹවීමක් වන නමුත් යමක් තිබේ නම් එය අසාර්ථක වේsuper සුපිරි පන්තියක ඇමතුමක් තිබේ නම් සහ / හෝ MRO වෙනස් වී එය ක්‍රියාත්මක කිරීම මත පදනම්ව A පන්තිය කිහිප වතාවක් හැඳින්විය හැකිය.

නිගමනය කිරීම සඳහා: සමුපකාර උරුමය සහ ආරම්භ කිරීම සඳහා සුපිරි සහ විශේෂිත පරාමිතීන් ඉතා හොඳින් ක්‍රියා නොකරයි.


5
class First(object):
  def __init__(self, a):
    print "first", a
    super(First, self).__init__(20)

class Second(object):
  def __init__(self, a):
    print "second", a
    super(Second, self).__init__()

class Third(First, Second):
  def __init__(self):
    super(Third, self).__init__(10)
    print "that's it"

t = Third()

ප්‍රතිදානය වේ

first 10
second 20
that's it

තෙවන වෙත අමතන්න () තෙවනුවෙහි අර්ථ දක්වා ඇති init සොයා ගනී . ඒ සාමාන්ය සැඟවෙයි සුපිරි කිරීමට ඇමතුමක් ආරම්භ කරමින් ප්රථම අර්ථ. MRO = [පළමු, දෙවන]. පළමුව අර්ථ දක්වා ඇති සුපිරි in init වෙත අමතන්න, MRO සෙවීම දිගටම කරගෙන යන අතර init සොයා ගනී දෙවන අර්ථ, හා සුපිරි ඕනෑම ඇමතුමක් පෙරනිමි වස්තුව පහර වැදෙනු ඇත init . මෙම උදාහරණය සංකල්පය පැහැදිලි කරයි යැයි මම බලාපොරොත්තු වෙමි.

ඔබ මුල සිට සුපිරි අමතන්නේ නැත්නම්. දාමය නතර වන අතර ඔබට පහත ප්‍රතිදානය ලැබෙනු ඇත.

first 10
that's it

1
එයට හේතුව පළමු පන්තියේදී ඔබ මුලින්ම 'මුද්‍රණය' ලෙසත් පසුව 'සුපිරි' ලෙසත් හැඳින්වූ බැවිනි.
පාෂාණ qi

2
එය ඇමතුම් නියෝගය විදහා දැක්වීමටයි
සේරාජ් අහමඩ්

4

ඉගෙනීමේ පිතොන්ටෙහාර්ඩ්වේ හි මම සුපිරි () නමින් යමක් ඉගෙන ගනිමි. සුපිරි () ශ්‍රිතය ඇමතීමෙන් උරුමය දෙමාපියන් සහ සහෝදර සහෝදරියන් හරහා ගමන් කිරීමට සහ වඩාත් පැහැදිලිව දැකීමට ඔබට උපකාරී වේ. මම තවමත් ආරම්භකයකු වන නමුත් python2.7 හි මෙම සුපිරි () භාවිතා කිරීම පිළිබඳ මගේ අත්දැකීම් බෙදා ගැනීමට මම කැමතියි.

ඔබ මෙම පිටුවේ ඇති අදහස් කියවා ඇත්නම්, ඔබ විසින් ලියන ලද ශ්‍රිතය වන ක්‍රම නිරාකරණ නියෝගය (MRO) ගැන ඔබට අසන්නට ලැබෙනු ඇත, සෙවීම සහ ක්‍රියාත්මක කිරීම සඳහා MRO ගැඹුරු-පළමු-වමේ සිට දකුණට යෝජනා ක්‍රමය භාවිතා කරනු ඇත. ඔබට ඒ පිළිබඳව වැඩි දුර පර්යේෂණ කළ හැකිය.

සුපිරි () ශ්‍රිතය එක් කිරීමෙන්

super(First, self).__init__() #example for class First.

එක් එක් සහ ඔවුන් සියල්ලන්ම එකතු කිරීමෙන් ඔබට සුපිරි () සමඟ විවිධ අවස්ථා සහ 'පවුල්' සම්බන්ධ කළ හැකිය. තවද එය ක්‍රම ක්‍රියාත්මක කරනු ඇත, ඒවා හරහා ගොස් ඔබ මග හැරී නැති බවට වග බලා ගන්න! කෙසේ වෙතත්, පෙර හෝ පසුව ඒවා එකතු කිරීමෙන් වෙනසක් සිදු වේ ඔබ ඉගෙනීමේ ව්‍යායාම ව්‍යායාම කර ඇත්දැයි ඔබ දැන ගනු ඇත 44. විනෝදය ආරම්භ කිරීමට ඉඩ දෙන්න !!

පහත උදාහරණය ගෙන, ඔබට පිටපත් කර ඇලවිය හැකි අතර එය ක්‍රියාත්මක කිරීමට උත්සාහ කරන්න:

class First(object):
    def __init__(self):

        print("first")

class Second(First):
    def __init__(self):
        print("second (before)")
        super(Second, self).__init__()
        print("second (after)")

class Third(First):
    def __init__(self):
        print("third (before)")
        super(Third, self).__init__()
        print("third (after)")


class Fourth(First):
    def __init__(self):
        print("fourth (before)")
        super(Fourth, self).__init__()
        print("fourth (after)")


class Fifth(Second, Third, Fourth):
    def __init__(self):
        print("fifth (before)")
        super(Fifth, self).__init__()
        print("fifth (after)")

Fifth()

එය ක්‍රියාත්මක වන්නේ කෙසේද? පස්වන () හි උදාහරණය මේ ආකාරයට සිදුවනු ඇත. සෑම පියවරක්ම සුපිරි ශ්‍රිතය එකතු කළ පන්තියේ සිට පන්තියට යයි.

1.) print("fifth (before)")
2.) super()>[Second, Third, Fourth] (Left to right)
3.) print("second (before)")
4.) super()> First (First is the Parent which inherit from object)

දෙමව්පියන් හමු වූ අතර එය තෙවන හා සිව්වන දක්වා ඉදිරියට යනු ඇත !!

5.) print("third (before)")
6.) super()> First (Parent class)
7.) print ("Fourth (before)")
8.) super()> First (Parent class)

දැන් සුපිරි () සහිත සියලුම පන්ති වලට ප්‍රවේශ වී ඇත! මව් පංතිය සොයාගෙන ක්‍රියාත්මක කර ඇති අතර දැන් එය කේත නිම කිරීම සඳහා උරුමයන්හි ක්‍රියාකාරිත්වය දිග හැරේ.

9.) print("first") (Parent)
10.) print ("Fourth (after)") (Class Fourth un-box)
11.) print("third (after)") (Class Third un-box)
12.) print("second (after)") (Class Second un-box)
13.) print("fifth (after)") (Class Fifth un-box)
14.) Fifth() executed

ඉහත වැඩසටහනේ ප්‍රති come ල:

fifth (before)
second (before
third (before)
fourth (before)
first
fourth (after)
third (after)
second (after)
fifth (after)

සුපිරි () එකතු කිරීමෙන් මට පයිතන් මගේ කේතීකරණය ක්‍රියාත්මක කරන්නේ කෙසේද යන්න පැහැදිලිව දැක ගැනීමටත්, මා අදහස් කළ ක්‍රමයට උරුමයට ප්‍රවේශ විය හැකි බවටත් වග බලා ගන්න.


සවිස්තරාත්මක නිරූපණයට ස්තූතියි!
තුෂාර් වජිරානි

3

IonsVisionscaper ඉහළින් පවසන දේට එක් කිරීමට මම කැමතියි :

Third --> First --> object --> Second --> object

මෙම අවස්ථාවෙහිදී පරිවර්තකයා වස්තු පන්තිය පෙරහන් නොකරන්නේ එහි අනුපිටපත් නිසා නොව, දෙවනුව හිස් ස්ථානයක දිස්වන නිසාත්, ධූරාවලි උප කුලකයක වලිග ස්ථානයේ නොපෙන්වන නිසාත් ය. වස්තුව වලිග ස්ථානවල පමණක් දිස්වන අතර ප්‍රමුඛතාවය තීරණය කිරීම සඳහා සී 3 ඇල්ගොරිතමයේ ප්‍රබල ස්ථානයක් ලෙස නොසැලකේ.

C, L (C) පන්තියේ රේඛීයකරණය (mro) යනු

  • පංතිය සී
  • ප්ලස් ඒකාබද්ධ කිරීම
    • එහි දෙමව්පියන්ගේ රේඛීයකරණය P1, P2, .. = L (P1, P2, ...) සහ
    • එහි දෙමව්පියන්ගේ ලැයිස්තුව P1, P2, ..

රේඛීය ඒකාබද්ධ කිරීම සිදු කරනුයේ ලැයිස්තු ප්‍රධානියා ලෙස පෙනෙන පොදු පංති තෝරා ගැනීමෙන් මිස ඇණවුමේ කාරණා නිසා වලිගය නොවේ (පහත පැහැදිලි වනු ඇත)

තෙවන රේඛීයකරණය පහත පරිදි ගණනය කළ හැකිය:

    L(O)  := [O]  // the linearization(mro) of O(object), because O has no parents

    L(First)  :=  [First] + merge(L(O), [O])
               =  [First] + merge([O], [O])
               =  [First, O]

    // Similarly, 
    L(Second)  := [Second, O]

    L(Third)   := [Third] + merge(L(First), L(Second), [First, Second])
                = [Third] + merge([First, O], [Second, O], [First, Second])
// class First is a good candidate for the first merge step, because it only appears as the head of the first and last lists
// class O is not a good candidate for the next merge step, because it also appears in the tails of list 1 and 2, 
                = [Third, First] + merge([O], [Second, O], [Second])
// class Second is a good candidate for the second merge step, because it appears as the head of the list 2 and 3
                = [Third, First, Second] + merge([O], [O])            
                = [Third, First, Second, O]

මේ අනුව පහත දැක්වෙන කේතයේ සුපිරි () ක්‍රියාත්මක කිරීම සඳහා:

class First(object):
  def __init__(self):
    super(First, self).__init__()
    print "first"

class Second(object):
  def __init__(self):
    super(Second, self).__init__()
    print "second"

class Third(First, Second):
  def __init__(self):
    super(Third, self).__init__()
    print "that's it"

මෙම ක්‍රමය විසඳන්නේ කෙසේද යන්න පැහැදිලි වේ

Third.__init__() ---> First.__init__() ---> Second.__init__() ---> 
Object.__init__() ---> returns ---> Second.__init__() -
prints "second" - returns ---> First.__init__() -
prints "first" - returns ---> Third.__init__() - prints "that's it"

"ඒ වෙනුවට දෙවැන්න හිස් ස්ථානයක දිස්වන අතර ධූරාවලි උප කුලකයක වලිග ස්ථානයේ නොපෙන්වයි." හිස හෝ වලිගයේ පිහිටීම යනු කුමක්ද, ධූරාවලියක් යනු කුමක්ද යන්න හෝ ඔබ යොමු කරන්නේ කුමන උප කුලකයද යන්න පැහැදිලි නැත.
තැඹිලි ෂර්බෙට්

වලිග පිහිටීම යන්නෙන් අදහස් කරන්නේ පන්ති ධූරාවලිය තුළ ඉහළ මට්ටමක පවතින අතර අනෙක් අතට. මූලික පන්තියේ 'වස්තුව' වලිගයේ අවසානයේ ඇත. Mro ඇල්ගොරිතම අවබෝධ කර ගැනීමේ යතුර නම්, 'දෙවන' 'පළමු' හි සුපිරි ලෙස දිස්වන ආකාරයයි. අපි සාමාන්‍යයෙන් එය 'වස්තු' පන්තිය යැයි උපකල්පනය කරමු. එය සත්‍යයකි, නමුත්, 'පළමු' පන්තියේ ඉදිරිදර්ශනය තුළ පමණි. කෙසේ වෙතත්, 'තෙවන' පන්ති දෘෂ්ටිකෝණයෙන් බලන විට, 'පළමු' සඳහා ධූරාවලිය අනුපිළිවෙල වෙනස් වන අතර ඉහත පෙන්වා ඇති පරිදි ගණනය කෙරේ. mro ඇල්ගොරිතම සියලු බහු උරුම පංති සඳහා මෙම ඉදිරිදර්ශනය (හෝ ධූරාවලිය උප කුලකයක්) නිර්මාණය කිරීමට උත්සාහ කරයි
supi

3

පයිතන් 3.5+ උරුමය අනාවැකි කිව හැකි අතර මට ඉතා හොඳයි. කරුණාකර මෙම කේතය දෙස බලන්න:

class Base(object):
  def foo(self):
    print("    Base(): entering")
    print("    Base(): exiting")


class First(Base):
  def foo(self):
    print("   First(): entering Will call Second now")
    super().foo()
    print("   First(): exiting")


class Second(Base):
  def foo(self):
    print("  Second(): entering")
    super().foo()
    print("  Second(): exiting")


class Third(First, Second):
  def foo(self):
    print(" Third(): entering")
    super().foo()
    print(" Third(): exiting")


class Fourth(Third):
  def foo(self):
    print("Fourth(): entering")
    super().foo()
    print("Fourth(): exiting")

Fourth().foo()
print(Fourth.__mro__)

නිමැවුම්:

Fourth(): entering
 Third(): entering
   First(): entering Will call Second now
  Second(): entering
    Base(): entering
    Base(): exiting
  Second(): exiting
   First(): exiting
 Third(): exiting
Fourth(): exiting
(<class '__main__.Fourth'>, <class '__main__.Third'>, <class '__main__.First'>, <class '__main__.Second'>, <class '__main__.Base'>, <class 'object'>)

ඔබට පෙනෙන පරිදි, එය උරුම වූ සෑම අනුපිළිවෙලකටම එක් වරකට උරුම වූ දාමයක් සඳහා හරියටම එක් වරක් foo ලෙස හැඳින්වේ. ඇමතීමෙන් ඔබට එම ඇණවුම ලබා ගත හැකිය . mro :

හතරවන -> තෙවන -> පළමු -> දෙවන -> පදනම -> වස්තුව


2

සමහර විට තවමත් එකතු කළ හැකි යමක් තිබේ, ජැන්ගෝ රෙස්ට් ෆ්‍රේම්වර්ක් සමඟ කුඩා උදාහරණයක්, සහ සැරසිලි කරන්නන්. මෙය ව්‍යංග ප්‍රශ්නයට පිළිතුරක් සපයයි: "මට කෙසේ හෝ මෙය අවශ්‍ය වන්නේ ඇයි?"

පැවසූ පරිදි: අපි ජැන්ගෝ රෙස්ට් ෆ්‍රේම්වර්ක් සමඟ සිටින අතර, අපි සාමාන්‍ය අදහස් භාවිතා කරන අතර, අපගේ දත්ත ගබඩාවේ ඇති සෑම වර්ගයකම වස්තු සඳහා අපට පෙනෙන්නේ එක් දර්ශන පන්තියක් වස්තු ලැයිස්තු සඳහා GET සහ POST සපයන අතර තවත් දර්ශන පන්තියක් GET සපයයි , තනි වස්තු සඳහා PUT සහ DELETE.

දැන් POST, PUT, සහ DELETE අපට ජැන්ගෝගේ login_required සමඟ සැරසීමට අවශ්‍යයි. මෙය පන්ති දෙකටම ස්පර්ශ වන ආකාරය සැලකිල්ලට ගන්න, නමුත් එක් එක් පන්තියේ සියලුම ක්‍රම නොවේ.

විසඳුමකට බහු උරුමයන් හරහා යා හැකිය.

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required

class LoginToPost:
    @method_decorator(login_required)
    def post(self, arg, *args, **kwargs):
        super().post(arg, *args, **kwargs)

ඒ හා සමානව අනෙක් ක්රම සඳහා.

මගේ කොන්ක්‍රීට් පංතිවල උරුම ලැයිස්තුවේ, මම මගේ LoginToPostපෙර ListCreateAPIViewසහ LoginToPutOrDeleteපෙර එකතු කරමි RetrieveUpdateDestroyAPIView. මගේ කොන්ක්‍රීට් පංති getඅනවසරයෙන් පවතිනු ඇත.


1

මගේ අනාගත යොමු කිරීම සඳහා මෙම පිළිතුර පළ කිරීම.

පයිතන් බහුවිධ උරුමය දියමන්ති ආකෘතියක් භාවිතා කළ යුතු අතර ක්‍රියාකාරී අත්සන ආකෘතියේ වෙනස් නොවිය යුතුය.

    A
   / \
  B   C
   \ /
    D

නියැදි කේත ස්නිපටය වනුයේ; -

class A:
    def __init__(self, name=None):
        #  this is the head of the diamond, no need to call super() here
        self.name = name

class B(A):
    def __init__(self, param1='hello', **kwargs):
        super().__init__(**kwargs)
        self.param1 = param1

class C(A):
    def __init__(self, param2='bye', **kwargs):
        super().__init__(**kwargs)
        self.param2 = param2

class D(B, C):
    def __init__(self, works='fine', **kwargs):
        super().__init__(**kwargs)
        print(f"{works=}, {self.param1=}, {self.param2=}, {self.name=}")

d = D(name='Testing')

මෙන්න A පන්තිය object


1
Aයුතු දැනුම්දිම __init__. Aමෙම ක්‍රමය "නව නිපැයුමක්" __init__නොකළ නිසා වෙනත් පංතියක් Aමීට පෙර එහි MRO හි තිබිය හැකි යැයි සිතිය නොහැකිය . කාගේ එකම පන්තියේ __init__ක්රමය කරන්නේ නැත (හා නොකළ යුතු) ඇමතුම් super().__init__වේ object.
චෙප්නර්

ඔව්. ඒ නිසා තමයි මම ඒ ලිව්වේ objectසමහරවිට මම හිතන්නේ class A (object) : ඒ වෙනුවට ලිවිය යුතුයි
අඛිල් නාඩ් පීසී

Aobjectඔබ එයට පරාමිතියක් එකතු කරන්නේ නම් විය නොහැක __init__.
චෙප්නර්

0

super().Foo()උප පංතියකින් ඇමතුමක් සලකා බලන්න . මෙම ක්රමය යෝජනාව නියමය (MRO) ක්රමය ක්රමය ඇමතුම් විසඳා ඇති අනුපිළිවෙළ වේ.

1 වන අවස්ථාව: තනි උරුමය

මෙහි දී, සුපිරි (). Foo () ධූරාවලිය තුළ සොයා බලනු ඇති අතර ආසන්නතම ක්‍රියාත්මක කිරීම සලකා බලනු ඇත, සොයාගත හොත්, ව්‍යතිරේකයක් මතු කරයි. “ යනු අ " සම්බන්ධතාවයක් සෑම විටම පැමිණෙන ඕනෑම උප පංතියක් සහ ධූරාවලිය තුළ එහි සුපිරි පන්තිය අතර සත්‍ය වේ. නමුත් මෙම කතාව සැමවිටම බහු උරුමයේ සමාන නොවේ.

2 වන අවස්ථාව: බහු උරුමය

මෙන්න, සුපිරි (). ෆූ () ක්රියාත්මක කිරීම සඳහා සොයමින් අතර, රාව සෑම සංචාරය පන්තියේ හෝ නොහැකි විය හැක හැක යනු සම්බන්ධයෙන්. පහත උදාහරණ සලකා බලන්න:

class A(object): pass
class B(object): pass
class C(A): pass
class D(A): pass
class E(C, D): pass
class F(B): pass
class G(B): pass
class H(F, G): pass
class I(E, H): pass

මෙන්න, Iධූරාවලියේ පහළම පන්තියයි. ධූරාවලිය රූප සටහන සහ MRO සඳහා Iවනු ඇත

රූප විස්තරය මෙහි ඇතුළත් කරන්න

(MRO පෙන්වන රතු අංක)

MRO යනු I E C D A H F G B object

X පංතියකට පිවිසෙන්නේ එහි උරුම වී ඇති සියළුම උප පංති නැරඹීමට පැමිණියහොත් පමණක් බව සලකන්න (එනම්, ඔබ තවමත් නරඹා නැති පහළ පන්තියකින් ඊතලයක් ඇති පන්තියකට ඔබ කිසි විටෙකත් නොයා යුතුය) .

මෙන්න, පන්ති සංචාරය පසුව සටහනක් C, Dනමුත් ගොස් ඇත Cහා Dනැත යනු ඔවුන් අතර සම්බන්ධතාවය (නමුත්, ඒ දෙක ම සමඟ ඇති A). super()තනි උරුමයට වඩා වෙනස් වන්නේ මෙහිදීය .

තරමක් සංකීර්ණ උදාහරණයක් සලකා බලන්න:

රූප විස්තරය මෙහි ඇතුළත් කරන්න

(MRO පෙන්වන රතු අංක)

MRO යනු I E C H D A F G B object

මෙම අවස්ථාවේ දී අප සිට ඉදිරියට Iකිරීමට Eකිරීමට C. මීලඟ පියවර වනු ඇත්තේ A, නමුත් අපි තවම පැමිණ නැත D, උප පංතියක් A. Dකෙසේ වෙතත්, අපට සංචාරය කළ නොහැක , මන්ද අප තවම සංචාරය කර නොමැති නිසා H, උප පංතියක් D. Hසංචාරය කිරීමට ඊළඟ පන්තිය ලෙස කොළ . මතක තබා ගන්න, අපි ධූරාවලිය තුළ ඉහළට යාමට උත්සාහ කරමු, හැකි නම්, එබැවින් අපි එහි වම්පස සුපිරි පන්තියට පිවිසෙමු D. පසු Dඅපි සංචාරය A, නමුත් අපි සංචාරය කිරීමට තවමත් ඇති නිසා අපි වස්තුවක් දක්වා යන්න බැහැ F, Gසහ B. මෙම පංති පිළිවෙලින් MRO සඳහා වට කර ඇත I.

MRO හි එක් පන්තියකට වඩා කිහිප වතාවක් පෙනී සිටිය නොහැකි බව සලකන්න.

උරුමයේ ධූරාවලිය තුළ සුපිරි () බලන ආකාරය මෙයයි.

සම්පත් සඳහා බැර: රිචඩ් එල් හැල්ටර්මන් පයිතන් ක්‍රමලේඛනයේ මූලධර්ම

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.