පයිතන් හි පැරණි විලාසිතාවන් සහ නව විලාසිතාවන් අතර ඇති වෙනස කුමක්ද?


1005

පයිතන් හි පැරණි විලාසිතාවන් සහ නව විලාසිතාවන් අතර ඇති වෙනස කුමක්ද? මා එකක් හෝ වෙනත් එකක් භාවිතා කළ යුත්තේ කවදාද?

Answers:


564

සිට නව පන්නයේ හා සම්භාව්ය පන්ති :

පයිතන් 2.1 දක්වා, පැරණි විලාසිතාවේ පන්ති පරිශීලකයාට ලබා ගත හැකි එකම රසය විය.

(පැරණි විලාසිතාවේ) පන්තියේ සංකල්පය වර්ගය පිළිබඳ සංකල්පයට සම්බන්ධ නොවේ: xපැරණි විලාසිතාවේ පන්තියක නිදසුනක් x.__class__ නම්, පංතිය නම් කරයි x, නමුත් type(x)සෑම විටම <type 'instance'>.

මෙයින් පිළිබිඹු වන්නේ සියළුම පැරණි විලාසිතාවන්, ඔවුන්ගේ පන්තියෙන් ස්වාධීනව, නිදසුනක් ලෙස හැඳින්වෙන තනි බිල්ට් වර්ගයකින් ක්‍රියාත්මක වන බවයි.

පංතිය සහ වර්ගය පිළිබඳ සංකල්ප ඒකාබද්ධ කිරීම සඳහා පයිතන් 2.2 හි නව විලාසිතාවේ පන්ති හඳුන්වා දෙන ලදී . නව විලාසිතාවේ පංතියක් යනු හුදෙක් පරිශීලකයා විසින් නිර්වචනය කරන ලද වර්ගයකි.

X යනු නව විලාසිතාවේ පන්තියක නිදසුනක් නම්, type(x)එය සාමාන්‍යයෙන් සමාන වේ x.__class__(මෙය සහතික කර නොතිබුණද - ආපසු ලබා දුන් අගය ඉක්මවා යාමට නව විලාසිතාවේ පන්ති අවස්ථාවක් සඳහා අවසර දෙනු ලැබේ x.__class__).

නව විලාසිතාවේ පන්ති හඳුන්වාදීම සඳහා ඇති ප්‍රධාන පෙළඹවීම වන්නේ පූර්ණ මෙටා-ආකෘතියක් සහිත ඒකාබද්ධ වස්තු ආකෘතියක් සැපයීමයි .

බොහෝ බිල්ට් වර්ග උප වර්ගීකරණය කිරීමේ හැකියාව හෝ ගණනය කළ ගුණාංග සක්‍රීය කරන “විස්තර කරන්නන්” හඳුන්වාදීම වැනි ක්ෂණික ප්‍රතිලාභ ගණනාවක් ද එයට ඇත.

අනුකූලතා හේතූන් මත, පන්ති පෙරනිමියෙන් තවමත් පැරණි විලාසිතාවකි .

නව විලාසිතාවේ පන්ති නිර්මාණය කරනු ලබන්නේ මව් පංතියක් ලෙස තවත් නව විලාසිතාවේ පන්තියක් (එනම් වර්ගයක්) හෝ වෙනත් දෙමව්පියන්ට අවශ්‍ය නොවන්නේ නම් “ඉහළ මට්ටමේ” වස්තුවක් නියම කිරීමෙනි.

නව විලාසිතාවේ පන්ති වල හැසිරීම පැරණි ආකාරයේ පන්ති වලට වඩා වැදගත් තොරතුරු ගණනාවකින් වෙනස් වේ.

විශේෂ ක්‍රම භාවිතා කරන ආකාරය මෙන් මෙම වෙනස්කම් සමහරක් නව වස්තු ආකෘතියට මූලික වේ. අනෙක් ඒවා නම්, බහු උරුමයන් සම්බන්ධයෙන් ක්‍රම විසර්ජන අනුපිළිවෙල වැනි අනුකූලතා අවශ්‍යතා සඳහා පෙර ක්‍රියාත්මක කළ නොහැකි “නිවැරදි කිරීම්” ය.

පයිතන් 3 හි ඇත්තේ නව විලාසිතාවේ පන්ති පමණි .

ඔබ උප objectපංතියෙන් හෝ නැතත්, පයිතන් 3 හි පන්ති නව විලාසිතාවකි.


41
මෙම වෙනස්කම් කිසිවක් නව විලාසිතාවේ පන්ති භාවිතා කිරීමට බලවත් හේතු ලෙස පෙනෙන්නේ නැත, නමුත් සෑම කෙනෙකුම පවසන්නේ ඔබ සැමවිටම නව විලාසිතාව භාවිතා කළ යුතු බවයි. මා කළ යුතු ආකාරයට තාරා ටයිප් කිරීම භාවිතා කරන්නේ නම්, මම කිසි විටෙකත් භාවිතා කිරීමට අවශ්‍ය නැත type(x). මා විසින් සාදන ලද වර්ගයක් උප වර්ගීකරණය නොකරන්නේ නම්, නව විලාසිතාවේ පන්ති මට දැකිය හැකි කිසිදු වාසියක් නොපෙනේ. අවාසියක් ඇත, එය අතිරේක ටයිප් කිරීම (object)වේ.
පුනරාවර්තන

79
super()පැරණි විලාසිතාවේ පන්තිවල වැඩ නොකරන්න වැනි සමහර විශේෂාංග . එම ලිපියේ සඳහන් වන පරිදි, MRO වැනි මූලික විසඳුම් සහ විශේෂ ක්‍රම තිබේ, එය භාවිතා කිරීමට හොඳ හේතුවක් නොවේ.
ජෝන් ඩෝ

22
Er පරිශීලකයා: පැරණි විලාසිතාවේ පන්ති 2.1 හි සිදු වූවාක් මෙන් 2.7 ට සමාන ලෙස හැසිරේ - සහ, ස්වල්ප දෙනෙකුට විවාදාත්මක මතක ඇති නිසාත්, ප්‍රලේඛනය තවදුරටත් ඒවායින් වැඩි ප්‍රමාණයක් සාකච්ඡා නොකරන නිසාත්, ඒවා ඊටත් වඩා නරක ය. ඉහත ප්‍රලේඛන උපුටා දැක්වීම කෙලින්ම මෙසේ කියයි: පැරණි ආකාරයේ පන්තිවල ක්‍රියාත්මක කළ නොහැකි “නිවැරදි කිරීම්” තිබේ. පයිතන් 2.1 සිට වෙන කිසිවෙකු සමඟ ගනුදෙනු කර නැති, සහ ලියකියවිලි තවදුරටත් පැහැදිලි නොකරන, ඔබ පරණ පන්ති පන්ති භාවිතා නොකරන්න.
abarnert

11
ඔබ පැරණි විලාසිතාවේ පන්ති 2.7 හි භාවිතා කරන්නේ නම් ඔබට පැකිලීමට ඉඩ ඇති උදාහරණයකි: bugs.python.org/issue21785
KT.

5
පුදුම වන ඕනෑම කෙනෙකුට, පයිතන් 3 හි ඇති වස්තුවෙන් පැහැදිලිවම උරුම වීමට හොඳ හේතුවක් වන්නේ එය පයිතන්හි බහු සංස්කරණ පහසු කිරීම පහසු කිරීමයි.
jpmc26

309

ප්‍රකාශය අනුව:

නව විලාසිතාවේ පන්ති උරුම වන්නේ වස්තුවෙන් හෝ වෙනත් නව විලාසිතාවේ පන්තියකිනි.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

පැරණි පන්තියේ පන්ති නැත.

class OldStyleClass():
    pass

පයිතන් 3 සටහන:

පයිතන් 3 පැරණි විලාසිතාවේ පන්ති සඳහා සහය නොදක්වයි, එබැවින් ඉහත සඳහන් කළ ආකෘති පත්‍ර නව විලාසිතාවේ පන්තියක ප්‍රති results ල ලබා දේ.


24
නව විලාසිතාවේ පන්තියක් වෙනත් නව පන්තියේ පන්තියකින් උරුම වන්නේ නම්, දීර් extension කිරීමෙන් එය උරුම වේ object.
aaronasterling

2
මෙය පැරණි විලාසිතාවේ පයිතන් පන්තියේ වැරදි උදාහරණයක් ද? class AnotherOldStyleClass: pass
අන්කූර් අගර්වාල්

11
@abc මම එය විශ්වාස කරන class A: passඅතර class A(): passඑය තදින්ම සමාන ය. පළමුවැන්නෙහි අර්ථය “A කිසිදු මව් පංතියකට උරුම නොවේ” සහ දෙවැන්නෙහි අර්ථය මව් පන්තියක උරුමයක් ” යන්නයි . බොහෝ සමාන බව, not isසහis not
eyquem

5
3.X සඳහා පැති සටහනක් සේම, “වස්තුව” හි උරුමය ස්වයංක්‍රීයව උපකල්පනය කෙරේ (එයින් අදහස් වන්නේ 3.X හි “වස්තුව” උරුම කර ගැනීමට අපට ක්‍රමයක් නොමැති බවයි). පසුගාමී අනුකූලතා හේතුව නිසා “(වස්තුව)” එහි තබා ගැනීම නරක නැත.
යෝ හ්සියාඕ

1
අපි උරුම වූ පංති පිළිබඳ තාක්‍ෂණික තොරතුරු ලබා ගැනීමට යන්නේ නම්, මෙම පිළිතුර ඔබ පැරණි ශෛලියේ පන්තියකින් උරුම කර ගැනීමෙන් තවත් පැරණි විලාසිතාවේ පන්තියක් නිර්මාණය කරන බව සටහන් කළ යුතුය. (ලියා ඇති පරිදි, මෙම පිළිතුර පරිශීලකයාට පැරණි විලාසිතාවේ පන්තියකින් උරුම විය හැකිදැයි ප්‍රශ්න කරයි. ඔබට හැකිය.)
jpmc26

226

පැරණි සහ නව විලාසිතාවේ පන්ති අතර වැදගත් හැසිරීම් වෙනස් වේ

  • සුපිරි එකතු කරන ලදි
  • MRO වෙනස් විය (පහත විස්තර කර ඇත)
  • විස්තර එකතු කරන ලදි
  • Exception(පහත උදාහරණයෙන්) ව්‍යුත්පන්න නොවන්නේ නම් නව විලාසිතාවේ පන්ති වස්තු මතු කළ නොහැක.
  • __slots__ එකතු කරන ලදි

MRO (ක්‍රම නිරාකරණ නියෝගය) වෙනස් කරන ලදි

එය වෙනත් පිළිතුරු වල සඳහන් කර ඇති නමුත් සම්භාව්‍ය MRO සහ C3 MRO අතර වෙනස පිළිබඳ ස්ථිර උදාහරණයක් මෙහි දැක්වේ (නව විලාසිතාවේ පන්තිවල භාවිතා වේ).

ප්‍රශ්නය වන්නේ බහු උරුමයන් තුළ ගුණාංග (ක්‍රම සහ සාමාජික විචල්‍යයන් ඇතුළුව) සෙවීමේ අනුපිළිවෙලයි.

ක්ලැසික් පංති වමේ සිට දකුණට ගැඹුරින් පළමු සෙවුම කරයි. පළමු තරගය නවත්වන්න. ඔවුන්ට __mro__ගුණාංගයක් නොමැත.

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

නව ශෛලියේ පන්ති MRO තනි ඉංග්‍රීසි වාක්‍යයකින් සංස්ලේෂණය කිරීමට වඩාත් සංකීර්ණ වේ. එය මෙහි විස්තරාත්මකව විස්තර කෙරේ . එහි එක් ගුණාංගයක් නම්, මූලික පංතියක් සෙවීම එහි ව්‍යුත්පන්න පංති සියල්ලටම පසුව පමණි. __mro__සෙවුම් අනුපිළිවෙල පෙන්වන ගුණාංගය ඔවුන් සතුව ඇත .

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

ව්‍යුත්පන්න නොවන්නේ නම් නව විලාසිතාවේ පන්ති වස්තු මතු කළ නොහැක Exception

පයිතන් 2.5 ක් පමණ බොහෝ පන්ති මතු කළ හැකි අතර පයිතන් 2.6 පමණ මෙය ඉවත් කරන ලදී. පයිතන් 2.7.3 හි:

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False

8
පැහැදිලි සාරාංශයක්, ස්තූතියි. ඔබ "ඉංග්‍රීසියෙන් පැහැදිලි කිරීම අසීරු" යැයි පැවසූ විට, ඔබ සිතන්නේ පෙර-ඇණවුම් ගැඹුර-පළමු සෙවුම භාවිතා කරන පැරණි විලාසිතාවේ පන්තියට වඩා ඔබ පෝස්ටර් ඇණවුම් ගැඹුර-පළමු සෙවුම විස්තර කරන බවයි. (පූර්ව ඇණවුම යන්නෙන් අදහස් කරන්නේ අපගේ පළමු දරුවාට පෙර අප අපවම සෙවීමයි.
ස්ටීව් කාටර්

40

පැරණි ශෛලියේ පන්ති තවමත් ගුණාංග සෙවීම සඳහා තරමක් වේගවත් ය. මෙය සාමාන්‍යයෙන් වැදගත් නොවේ, නමුත් කාර්ය සාධන සංවේදී පයිතන් 2.x කේතයට එය ප්‍රයෝජනවත් විය හැකිය:

[3]: A පන්තිය:
   ...: def __init __ (ස්වයං):
   ...: self.a = 'ආයුබෝවන්'
   ...:

[4] තුළ: B පන්තිය (වස්තුව):
   ...: def __init __ (ස්වයං):
   ...: self.a = 'ආයුබෝවන්'
   ...:

[6] තුළ: aobj = A ()
[7] තුළ: bobj = B ()

[8] තුළ:% timeit aobj.a
ලූප 10000000 ක්, හොඳම ලූපයකට 3: 78.7 එන්

[10] තුළ:% timeit bobj.a
ලූප 10000000 ක්, හොඳම ලූපයකට 3: 86.9 එන්

5
ඔබ ප්‍රායෝගිකව දුටු උනන්දුව, මම කියවූයේ මෙය නව විලාසිතාවේ පංති, උදාහරණ ආ ict ාවෙහි ගුණාංගය සොයාගත් පසු, එය විස්තරයක් ද යන්න සොයා බැලීමට අමතර සොයා බැලීමක් කළ යුතු බැවිනි. අගය ආපසු ලබා ගැනීම සඳහා ආයාචනා කළ යුතු ක්‍රමයක් ලබා ගන්න . පැරණි ශෛලියේ පංති එකතු කළ ගණනය කිරීම් නොමැතිව සොයාගත් වස්තුව සරල ලෙස ආපසු එවයි (නමුත් පසුව විස්තර කරන්නන්ට සහාය නොදක්වයි). ඔබට වඩා, මෙම විශිෂ්ට පශ්චාත් ගයිඩෝ විසින් කියවිය හැකි python-history.blogspot.co.uk/2010/06/... , පිළිබඳව විශේෂයෙන් කොටස මඳබව
xuloChavez

1
CPython 2.7.2 සමඟ සත්‍ය බවක් නොපෙනේ:%timeit aobj.a 10000000 loops, best of 3: 66.1 ns per loop %timeit bobj.a 10000000 loops, best of 3: 53.9 ns per loop
බෙනඩික්ට් වෝල්ඩ්වොගල්

1
මා වෙනුවෙන් x86-64 ලිනක්ස් හි CPython 2.7.2 හි aobj සඳහා තවමත් වේගවත්ය.
xioxox

41
කාර්ය සාධන සංවේදී යෙදුම් සඳහා පිරිසිදු පයිතන් කේතය මත රඳා සිටීම බොහෝ විට නරක අදහසකි. කිසිවෙකු පවසන්නේ නැත: "මට වේගවත් කේතයක් අවශ්‍යයි, එබැවින් මම පැරණි විලාසිතාවේ පයිතන් පන්ති භාවිතා කරමි." නැම්පි පිරිසිදු පයිතන් ලෙස ගණන් ගන්නේ නැත.
පිලිප් ක්ලවුඩ්

IPython 2.7.6 හි ද මෙය සත්‍ය නොවේ. '' '' 477 ns එදිරිව 456 ns
ලූපයකට

37

ගයිඩෝ විසින් නව ශෛලියේ පන්ති පිළිබඳ අභ්‍යන්තර කතාව ලියා ඇති අතර එය පයිතන්හි නව විලාසිතාවන් සහ පැරණි විලාසිතාවන් පිළිබඳ පංතිය පිළිබඳ විශිෂ්ට ලිපියකි.

පයිතන් 3 සතුව ඇත්තේ නව විලාසිතාවේ පන්තියක් පමණි. ඔබ 'පැරණි විලාසිතාවේ පන්තියක්' ලිවුවද, එය ව්‍යංගයෙන් ව්‍යුත්පන්න කර ඇත object.

නව විලාසිතාවේ පන්තිවල පැරණි විලාසිතාවේ පන්ති නොමැති සමහර උසස් අංග ඇත super, එනම් නව C3 mro , සමහර ඉන්ද්‍රජාලික ක්‍රම යනාදිය.


24

මෙන්න ඉතා ප්‍රායෝගික, සත්‍ය / ව්‍යාජ වෙනසක්. පහත දැක්වෙන කේතයේ අනුවාද දෙක අතර ඇති එකම වෙනස වන්නේ දෙවන අනුවාදයේ පුද්ගලයාට වස්තුවෙන් උරුම වීමයි . ඒ හැර, අනුවාද දෙක සමාන වේ, නමුත් වෙනස් ප්‍රති results ල සමඟ:

  1. පැරණි පන්තියේ පන්ති

    class Person():
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed1 is ahmed2
    print ahmed1
    print ahmed2
    
    
    >>> False
    <__main__.Person instance at 0xb74acf8c>
    <__main__.Person instance at 0xb74ac6cc>
    >>>
    
  2. නව විලාසිතාවේ පන්ති

    class Person(object):
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed2 is ahmed1
    print ahmed1
    print ahmed2
    
    >>> True
    <__main__.Person object at 0xb74ac66c>
    <__main__.Person object at 0xb74ac66c>
    >>>

2
'_names_cache' කරන්නේ කුමක්ද? ඔබට යොමු කිරීමක් බෙදා ගත හැකිද?
Muatik

4
_names_cacheඔබ යන සෑම නමක්ම හැඹිලි (අනාගත නැවත ලබා ගැනීම සඳහා ගබඩා කරයි) ශබ්දකෝෂයකි Person.__new__. Setdefault ක්‍රමය (ඕනෑම ශබ්ද කෝෂයක අර්ථ දක්වා ඇත) තර්ක දෙකක් ගනී: යතුරක් සහ අගයක්. යතුර නියෝගයේ තිබේ නම්, එය එහි වටිනාකම නැවත ලබා දෙනු ඇත. එය ආ ict ාවේ නොමැති නම්, එය පළමුව එය දෙවන තර්කය ලෙස සම්මත අගයට සකසා පසුව එය ආපසු ලබා දෙනු ඇත.
ychaouche

4
භාවිතය වැරදිය. අදහස නම් නව වස්තුවක් දැනටමත් තිබේ නම් එය ගොඩනඟා නොගැනීමයි, නමුත් ඔබේ නඩුවේදී __new__()එය සැමවිටම හැඳින්වෙන අතර එය සෑම විටම නව වස්තුවක් සාදයි, පසුව එය විසි කරයි. මෙම අවස්ථාවේ දී a ifවඩා සුදුසු වේ .setdefault().
අමිත් උපාධ්‍යා

එහෙත්, නිමැවුමේ වෙනස එනම් පැරණි විලාසිතාවේ පන්තියේ අවස්ථා දෙක එකිනෙකට වෙනස් වූ බව මට වැටහී නැත. මේ අනුව අවස්ථා දෙක වැරදිය. නමුත් නව විලාසිතාවේ පන්තියේදී අවස්ථා දෙකම එක හා සමාන වේ. කෙසේද ? පැරණි විලාසිතාවේ පන්තියේ නොතිබූ අවස්ථා දෙක එක හා සමාන වූ නව විලාසිතාවේ පන්තියේ වෙනස කුමක්ද?
පබිත්‍රා පටි

1
Ab පබිට්‍රපති: එය මෙහි ලාභ නිරූපණයකි. __new__ඇත්ත වශයෙන්ම පැරණි විලාසිතාවේ පන්ති සඳහා දෙයක් නොවේ, එය නිදසුනක් ලෙස ඉදිකිරීමේදී භාවිතා නොවේ (එය අහඹු නමක් පමණක් වන අතර එය අර්ථ දැක්වීම වැනි විශේෂයි __spam__). එබැවින් පැරණි ශෛලියේ පන්තියක් තැනීම පමණක් අවශ්‍ය __init__වන අතර නව ශෛලියේ ඉදිකිරීම් __new__(නම අනුව සිංගල්ටන් උදාහරණයට සමපාත වේ) ඉදිකිරීමට හා __init__එය ආරම්භ කිරීමට ඉල්ලා සිටී.
ෂැඩෝ රේන්ජර්

10

නව විලාසිතාවේ පංති උරුම වී ඇති objectඅතර ඒවා පයිතන් 2.2 සිට ලිවිය යුතුය (එනම් class Classname(object):ඒ වෙනුවට class Classname:). මූලික වෙනස වන්නේ වර්ග සහ පංති ඒකාබද්ධ කිරීමයි. මෙහි ඇති හොඳ අතුරු ප්‍රති is ලය නම්, එය ඔබට ගොඩනංවන ලද වර්ග වලින් උරුම වීමට ඉඩ සලසයි.

වැඩි විස්තර සඳහා ඩෙස්ක්‍රින්ට්‍රෝ කියවන්න .


8

නව විලාසිතාවේ පන්ති පන්තියක් ඇති super(Foo, self)තැන භාවිතා කළ හැකි අතර Fooඑය selfනිදසුනකි.

super(type[, object-or-type])

දෙමව්පියන්ට හෝ සහෝදර සහෝදරියකට ක්‍රම ඇමතුම් ලබා දෙන ප්‍රොක්සි වස්තුවක් ආපසු එවන්න. පංතියක අභිබවා ගොස් ඇති උරුම ක්‍රම වලට ප්‍රවේශ වීම සඳහා මෙය ප්‍රයෝජනවත් වේ. සෙවුම් අනුපිළිවෙල getattr () විසින් භාවිතා කරන ආකාරයටම වේ.

පයිතන් 3.x හි ඔබට super()කිසිදු පරාමිතියක් නොමැතිව පන්තියක් තුළ භාවිතා කළ හැකිය .

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.