පයිතන් හි පැරණි විලාසිතාවන් සහ නව විලාසිතාවන් අතර ඇති වෙනස කුමක්ද? මා එකක් හෝ වෙනත් එකක් භාවිතා කළ යුත්තේ කවදාද?
පයිතන් හි පැරණි විලාසිතාවන් සහ නව විලාසිතාවන් අතර ඇති වෙනස කුමක්ද? මා එකක් හෝ වෙනත් එකක් භාවිතා කළ යුත්තේ කවදාද?
Answers:
සිට නව පන්නයේ හා සම්භාව්ය පන්ති :
පයිතන් 2.1 දක්වා, පැරණි විලාසිතාවේ පන්ති පරිශීලකයාට ලබා ගත හැකි එකම රසය විය.
(පැරණි විලාසිතාවේ) පන්තියේ සංකල්පය වර්ගය පිළිබඳ සංකල්පයට සම්බන්ධ නොවේ:
x
පැරණි විලාසිතාවේ පන්තියක නිදසුනක්x.__class__
නම්, පංතිය නම් කරයිx
, නමුත්type(x)
සෑම විටම<type 'instance'>
.මෙයින් පිළිබිඹු වන්නේ සියළුම පැරණි විලාසිතාවන්, ඔවුන්ගේ පන්තියෙන් ස්වාධීනව, නිදසුනක් ලෙස හැඳින්වෙන තනි බිල්ට් වර්ගයකින් ක්රියාත්මක වන බවයි.
පංතිය සහ වර්ගය පිළිබඳ සංකල්ප ඒකාබද්ධ කිරීම සඳහා පයිතන් 2.2 හි නව විලාසිතාවේ පන්ති හඳුන්වා දෙන ලදී . නව විලාසිතාවේ පංතියක් යනු හුදෙක් පරිශීලකයා විසින් නිර්වචනය කරන ලද වර්ගයකි.
X යනු නව විලාසිතාවේ පන්තියක නිදසුනක් නම්,
type(x)
එය සාමාන්යයෙන් සමාන වේx.__class__
(මෙය සහතික කර නොතිබුණද - ආපසු ලබා දුන් අගය ඉක්මවා යාමට නව විලාසිතාවේ පන්ති අවස්ථාවක් සඳහා අවසර දෙනු ලැබේx.__class__
).නව විලාසිතාවේ පන්ති හඳුන්වාදීම සඳහා ඇති ප්රධාන පෙළඹවීම වන්නේ පූර්ණ මෙටා-ආකෘතියක් සහිත ඒකාබද්ධ වස්තු ආකෘතියක් සැපයීමයි .
බොහෝ බිල්ට් වර්ග උප වර්ගීකරණය කිරීමේ හැකියාව හෝ ගණනය කළ ගුණාංග සක්රීය කරන “විස්තර කරන්නන්” හඳුන්වාදීම වැනි ක්ෂණික ප්රතිලාභ ගණනාවක් ද එයට ඇත.
අනුකූලතා හේතූන් මත, පන්ති පෙරනිමියෙන් තවමත් පැරණි විලාසිතාවකි .
නව විලාසිතාවේ පන්ති නිර්මාණය කරනු ලබන්නේ මව් පංතියක් ලෙස තවත් නව විලාසිතාවේ පන්තියක් (එනම් වර්ගයක්) හෝ වෙනත් දෙමව්පියන්ට අවශ්ය නොවන්නේ නම් “ඉහළ මට්ටමේ” වස්තුවක් නියම කිරීමෙනි.
නව විලාසිතාවේ පන්ති වල හැසිරීම පැරණි ආකාරයේ පන්ති වලට වඩා වැදගත් තොරතුරු ගණනාවකින් වෙනස් වේ.
විශේෂ ක්රම භාවිතා කරන ආකාරය මෙන් මෙම වෙනස්කම් සමහරක් නව වස්තු ආකෘතියට මූලික වේ. අනෙක් ඒවා නම්, බහු උරුමයන් සම්බන්ධයෙන් ක්රම විසර්ජන අනුපිළිවෙල වැනි අනුකූලතා අවශ්යතා සඳහා පෙර ක්රියාත්මක කළ නොහැකි “නිවැරදි කිරීම්” ය.
පයිතන් 3 හි ඇත්තේ නව විලාසිතාවේ පන්ති පමණි .
ඔබ උප
object
පංතියෙන් හෝ නැතත්, පයිතන් 3 හි පන්ති නව විලාසිතාවකි.
super()
පැරණි විලාසිතාවේ පන්තිවල වැඩ නොකරන්න වැනි සමහර විශේෂාංග . එම ලිපියේ සඳහන් වන පරිදි, MRO වැනි මූලික විසඳුම් සහ විශේෂ ක්රම තිබේ, එය භාවිතා කිරීමට හොඳ හේතුවක් නොවේ.
ප්රකාශය අනුව:
නව විලාසිතාවේ පන්ති උරුම වන්නේ වස්තුවෙන් හෝ වෙනත් නව විලාසිතාවේ පන්තියකිනි.
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
පැරණි පන්තියේ පන්ති නැත.
class OldStyleClass():
pass
පයිතන් 3 සටහන:
පයිතන් 3 පැරණි විලාසිතාවේ පන්ති සඳහා සහය නොදක්වයි, එබැවින් ඉහත සඳහන් කළ ආකෘති පත්ර නව විලාසිතාවේ පන්තියක ප්රති results ල ලබා දේ.
object
.
class AnotherOldStyleClass: pass
class A: pass
අතර class A(): pass
එය තදින්ම සමාන ය. පළමුවැන්නෙහි අර්ථය “A කිසිදු මව් පංතියකට උරුම නොවේ” සහ දෙවැන්නෙහි අර්ථය “ මව් පන්තියක උරුමයක් ” යන්නයි . බොහෝ සමාන බව, not is
සහis not
පැරණි සහ නව විලාසිතාවේ පන්ති අතර වැදගත් හැසිරීම් වෙනස් වේ
Exception
(පහත උදාහරණයෙන්) ව්යුත්පන්න නොවන්නේ නම් නව විලාසිතාවේ පන්ති වස්තු මතු කළ නොහැක.__slots__
එකතු කරන ලදිඑය වෙනත් පිළිතුරු වල සඳහන් කර ඇති නමුත් සම්භාව්ය 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
පැරණි ශෛලියේ පන්ති තවමත් ගුණාංග සෙවීම සඳහා තරමක් වේගවත් ය. මෙය සාමාන්යයෙන් වැදගත් නොවේ, නමුත් කාර්ය සාධන සංවේදී පයිතන් 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 එන්
%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
ගයිඩෝ විසින් නව ශෛලියේ පන්ති පිළිබඳ අභ්යන්තර කතාව ලියා ඇති අතර එය පයිතන්හි නව විලාසිතාවන් සහ පැරණි විලාසිතාවන් පිළිබඳ පංතිය පිළිබඳ විශිෂ්ට ලිපියකි.
පයිතන් 3 සතුව ඇත්තේ නව විලාසිතාවේ පන්තියක් පමණි. ඔබ 'පැරණි විලාසිතාවේ පන්තියක්' ලිවුවද, එය ව්යංගයෙන් ව්යුත්පන්න කර ඇත object
.
නව විලාසිතාවේ පන්තිවල පැරණි විලාසිතාවේ පන්ති නොමැති සමහර උසස් අංග ඇත super
, එනම් නව C3 mro , සමහර ඉන්ද්රජාලික ක්රම යනාදිය.
මෙන්න ඉතා ප්රායෝගික, සත්ය / ව්යාජ වෙනසක්. පහත දැක්වෙන කේතයේ අනුවාද දෙක අතර ඇති එකම වෙනස වන්නේ දෙවන අනුවාදයේ පුද්ගලයාට වස්තුවෙන් උරුම වීමයි . ඒ හැර, අනුවාද දෙක සමාන වේ, නමුත් වෙනස් ප්රති results ල සමඟ:
පැරණි පන්තියේ පන්ති
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>
>>>
නව විලාසිතාවේ පන්ති
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>
>>>
_names_cache
ඔබ යන සෑම නමක්ම හැඹිලි (අනාගත නැවත ලබා ගැනීම සඳහා ගබඩා කරයි) ශබ්දකෝෂයකි Person.__new__
. Setdefault ක්රමය (ඕනෑම ශබ්ද කෝෂයක අර්ථ දක්වා ඇත) තර්ක දෙකක් ගනී: යතුරක් සහ අගයක්. යතුර නියෝගයේ තිබේ නම්, එය එහි වටිනාකම නැවත ලබා දෙනු ඇත. එය ආ ict ාවේ නොමැති නම්, එය පළමුව එය දෙවන තර්කය ලෙස සම්මත අගයට සකසා පසුව එය ආපසු ලබා දෙනු ඇත.
__new__()
එය සැමවිටම හැඳින්වෙන අතර එය සෑම විටම නව වස්තුවක් සාදයි, පසුව එය විසි කරයි. මෙම අවස්ථාවේ දී a if
වඩා සුදුසු වේ .setdefault()
.
__new__
ඇත්ත වශයෙන්ම පැරණි විලාසිතාවේ පන්ති සඳහා දෙයක් නොවේ, එය නිදසුනක් ලෙස ඉදිකිරීමේදී භාවිතා නොවේ (එය අහඹු නමක් පමණක් වන අතර එය අර්ථ දැක්වීම වැනි විශේෂයි __spam__
). එබැවින් පැරණි ශෛලියේ පන්තියක් තැනීම පමණක් අවශ්ය __init__
වන අතර නව ශෛලියේ ඉදිකිරීම් __new__
(නම අනුව සිංගල්ටන් උදාහරණයට සමපාත වේ) ඉදිකිරීමට හා __init__
එය ආරම්භ කිරීමට ඉල්ලා සිටී.
නව විලාසිතාවේ පංති උරුම වී ඇති object
අතර ඒවා පයිතන් 2.2 සිට ලිවිය යුතුය (එනම් class Classname(object):
ඒ වෙනුවට class Classname:
). මූලික වෙනස වන්නේ වර්ග සහ පංති ඒකාබද්ධ කිරීමයි. මෙහි ඇති හොඳ අතුරු ප්රති is ලය නම්, එය ඔබට ගොඩනංවන ලද වර්ග වලින් උරුම වීමට ඉඩ සලසයි.
වැඩි විස්තර සඳහා ඩෙස්ක්රින්ට්රෝ කියවන්න .
නව විලාසිතාවේ පන්ති පන්තියක් ඇති super(Foo, self)
තැන භාවිතා කළ හැකි අතර Foo
එය self
නිදසුනකි.
super(type[, object-or-type])
දෙමව්පියන්ට හෝ සහෝදර සහෝදරියකට ක්රම ඇමතුම් ලබා දෙන ප්රොක්සි වස්තුවක් ආපසු එවන්න. පංතියක අභිබවා ගොස් ඇති උරුම ක්රම වලට ප්රවේශ වීම සඳහා මෙය ප්රයෝජනවත් වේ. සෙවුම් අනුපිළිවෙල getattr () විසින් භාවිතා කරන ආකාරයටම වේ.
පයිතන් 3.x හි ඔබට super()
කිසිදු පරාමිතියක් නොමැතිව පන්තියක් තුළ භාවිතා කළ හැකිය .
type(x)
. මා විසින් සාදන ලද වර්ගයක් උප වර්ගීකරණය නොකරන්නේ නම්, නව විලාසිතාවේ පන්ති මට දැකිය හැකි කිසිදු වාසියක් නොපෙනේ. අවාසියක් ඇත, එය අතිරේක ටයිප් කිරීම(object)
වේ.