දී ඇති වස්තුවක් යම් වර්ගයකට අයත් දැයි පරීක්ෂා කිරීමට හොඳම ක්රමය කුමක්ද? දී ඇති වර්ගයකින් වස්තුව උරුම වී ඇත්දැයි පරීක්ෂා කරන්නේ කෙසේද?
මට වස්තුවක් ඇතැයි කියමු o
. එය එසේ දැයි මා පරීක්ෂා කරන්නේ කෙසේද str
?
දී ඇති වස්තුවක් යම් වර්ගයකට අයත් දැයි පරීක්ෂා කිරීමට හොඳම ක්රමය කුමක්ද? දී ඇති වර්ගයකින් වස්තුව උරුම වී ඇත්දැයි පරීක්ෂා කරන්නේ කෙසේද?
මට වස්තුවක් ඇතැයි කියමු o
. එය එසේ දැයි මා පරීක්ෂා කරන්නේ කෙසේද str
?
Answers:
නම්, පරීක්ෂා කිරීමට o
ඇති අවස්ථාව කියන්නේ str
හෝ ඕනෑම උපපංතිය str
, භාවිතා isinstance (මෙය "කැනෝනිකල්" මාර්ගය වනු ඇත):
if isinstance(o, str):
වර්ගය o
හරියටම දැයි පරීක්ෂා කිරීමට str
(උප පංති බැහැර කරන්න):
if type(o) is str:
පහත සඳහන් දෑ ද ක්රියාත්මක වන අතර සමහර අවස්ථාවල එය ප්රයෝජනවත් විය හැකිය:
if issubclass(type(o), str):
අදාළ තොරතුරු සඳහා පයිතන් පුස්තකාල යොමුව තුළ ඇති කාර්යයන් බලන්න .
තවත් එක් සටහනක්: මේ අවස්ථාවේ දී, ඔබ පයිතන් 2 භාවිතා කරන්නේ නම්, ඔබට ඇත්ත වශයෙන්ම භාවිතා කිරීමට අවශ්ය විය හැකිය:
if isinstance(o, basestring):
මක්නිසාද යත් මෙය යුනිකෝඩ් නූල් ද අල්ලා ගනු ඇත ( unicode
උප කාණ්ඩයක් නොවේ str
; දෙකම str
සහ unicode
උප පංති වේ basestring
). basestring
පයිතන් 3 හි තවදුරටත් නොපවතින බව සලකන්න , එහිදී නූල් ( ) සහ ද්විමය දත්ත ( ) දැඩි ලෙස වෙන් කරනු ලැබේ .str
bytes
විකල්පයක් ලෙස, isinstance
පන්ති රාශියක් පිළිගනී. ඕනෑම උප පංතියක නිදසුනක් True
නම් මෙය නැවත පැමිණේ :o
(str, unicode)
if isinstance(o, (str, unicode)):
type(a) is Object
නොවේ නම් එය ද සත්යයකි isinstance(a, Object)
. කෙසේ වෙතත්, එසේ type(a) is SubClassOfObject
නම් type(a) is Object == False
, නමුත් isinstance(a, Object) == True
. හරිද?
a is b
යන්නෙන් අදහස් කරන්නේ a සහ b යනු එකම දෙයයි, එනම් මතකයේ ඇති එකම වස්තුව ගැන සඳහන් කිරීමයි. එබැවින් a
සහ b
හරියටම එකම පන්තිය විය යුතුය, උප පංති නොවේ isinstance()
. උදාහරණයක් ලෙස stackoverflow.com/a/133024/1072212
මෙම බොහෝ වස්තුවක වර්ගය පරීක්ෂා කිරීමට Pythonic ක්රමයක් ... එය පරීක්ෂා කිරීමට නොවේ.
පයිතන් තාරා ටයිප් කිරීම දිරිගන්වන බැවින් , ඔබ try...except
ඒවා භාවිතා කිරීමට අවශ්ය ආකාරයට වස්තුවේ ක්රම භාවිතා කළ යුතුය. එබැවින් ඔබේ ශ්රිතය ලිවිය හැකි ගොනු වස්තුවක් සොයන්නේ නම්, එය උප පංතියක් දැයි පරීක්ෂා නොකරන්න , file
එහි .write()
ක්රමය භාවිතා කිරීමට උත්සාහ කරන්න !
ඇත්ත වශයෙන්ම, සමහර විට මෙම ලස්සන සාරාංශ බිඳ වැටෙන අතර isinstance(obj, cls)
ඔබට අවශ්ය වන්නේ එයයි. නමුත් අරපිරිමැස්මෙන් භාවිතා කරන්න.
if hasattr(ob, "write") and callable(ob.write):
නැතහොත් යම් ප්රවේශයක් සුරකින්න ...func = getattr(ob, "write", None)
if callable(func): ...
hasattr
පමණක් යටපත් කරයි - බලන්න: docs.python.org/3.4/library/functions.html#hasattr
isinstance(o, str)
ආපසු True
නම් o
යනු str
හෝ උරුම බව ආකාරයේ වන str
.
type(o) is str
ආපසු True
එන්නේ o
str නම් පමණි . උරුම වූ වර්ගයක් False
නම් එය නැවත පැමිණේ .o
str
isinstance
සහ අතර වෙනස type(var) == type('')
පැහැදිලි නැති නිසා.
ප්රශ්නය අසන ලද සහ පිළිතුරු දුන් පසු, පයිතන්ට ටයිප් ඉඟි එකතු කරන ලදි . පයිතන් හි ඉඟි ටයිප් කර පරීක්ෂා කිරීමට ඉඩ ලබා දෙන නමුත් සංඛ්යාත්මකව ටයිප් කළ භාෂාවන්ට වඩා වෙනස් ආකාරයකින්. Python දී ඉඟි කාර්යයන් හා සම්බන්ධ වීමේදී ප්රවේශ දත්ත ලෙස කටයුතු සමග තර්ක කිරීමට අෙප්ක්ෂිත වර්ග ඇසුරු ටයිප් කර මෙම ඉඩ වර්ග පරීක්ෂා කිරීමට සඳහා. ඉඟි වාක්ය ඛණ්ඩයේ උදාහරණය:
def foo(i: int):
return i
foo(5)
foo('oops')
මෙම අවස්ථාවේ දී අපට අවශ්ය foo('oops')
වන්නේ තර්කයේ විවරණය කළ වර්ගය බැවින් දෝෂයක් අවුලුවාලීමට ය int
. ස්ක්රිප්ට් සාමාන්යයෙන් ක්රියාත්මක වන විට එකතු කළ ආකාරයේ ඉඟියක් දෝෂයක් ඇති නොකරයි . කෙසේ වෙතත්, එය වෙනත් වැඩසටහන් විමසීමට සහ වර්ගයේ දෝෂ පරීක්ෂා කිරීමට භාවිතා කළ හැකි අපේක්ෂිත වර්ග විස්තර කරන ශ්රිතයට ගුණාංග එකතු කරයි.
වර්ගයේ දෝෂය සොයා ගැනීමට භාවිතා කළ හැකි මෙම වෙනත් වැඩසටහන් වලින් එකක් mypy
:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(ඔබට mypy
ඔබේ පැකේජ කළමණාකරුගෙන් ස්ථාපනය කිරීමට අවශ්ය විය හැකිය . එය CPython සමඟ එන බව මම නොසිතමි.
මේ ආකාරයෙන් ටයිප් කිරීම සංඛ්යාත්මකව ටයිප් කළ සම්පාදිත භාෂාවලින් ටයිප් කිරීම වඩා වෙනස් වේ. පයිතන් හි වර්ග ගතික බැවින්, සෑම අවස්ථාවකම එය සිදුවිය යුතු යැයි අපි අවධාරනය කරන්නේ නම්, වර්ගය පරීක්ෂා කිරීම ධාවන වේලාවේදී සිදු කළ යුතුය. පැහැදිලි වර්ගයේ චෙක්පත් අවශ්යතාවයට වඩා සීමා සහිත වන අතර අනවශ්ය දෝෂ ඇති කළ හැකිය (උදා: තර්කය සැබවින්ම හරියටම list
වර්ගයට අයත් විය යුතුද? නැතහොත් නැවත ලබා ගත හැකි කිසිවක් ප්රමාණවත්ද?).
පැහැදිලි ආකාරයේ පරීක්ෂාවේ උඩු යටිකුරු වන්නේ එය කලින් දෝෂ හඳුනාගෙන තාරාවන්ගේ ටයිප් කිරීමට වඩා පැහැදිලි දෝෂ පණිවිඩ ලබා දිය හැකි වීමයි. තාරා වර්ගයක නිශ්චිත අවශ්යතා ප්රකාශ කළ හැක්කේ බාහිර ලියකියවිලි වලින් පමණි (එය පරිපූර්ණ හා නිරවද්ය යැයි සිතිය හැකිය) සහ නොගැලපෙන වර්ගවල දෝෂ ඇතිවිය හැක්කේ ඒවා ආරම්භ වූ ස්ථානයෙන් බොහෝ දුරිනි.
පයිතන් වර්ගයේ ඉඟි යනු වර්ග නියම කර පරීක්ෂා කළ හැකි සම්මුතියක් ඉදිරිපත් කිරීම සඳහා වන නමුත් සුපුරුදු කේත ක්රියාත්මක කිරීමේදී අමතර පිරිවැයක් නොමැත.
මෙම typing
පැකේජය ඔස්සේ විශේෂයෙන් වර්ග කිරීමකින් තොරව අවශ්ය හැසිරීම් ප්රකාශ කිරීමට වර්ගය ඉඟි භාවිතා කළ හැකි බව විචල්ය ටයිප් කරන්න. නිදසුනක් ලෙස, එම හැසිරීම් සමඟ ඕනෑම වර්ගයක අවශ්යතාවය නියම කිරීමට Iterable
සහ Callable
ඉඟි වැනි විචල්යයන් එයට ඇතුළත් වේ .
වර්ග පරීක්ෂා කිරීම සඳහා වඩාත්ම පයිතොනික් ක්රමය ටයිප් ඉඟි වන අතර, බොහෝ විට ඊටත් වඩා පයිතොනික් වර්ග පරීක්ෂා නොකිරීම සහ තාරා ටයිප් කිරීම මත රඳා සිටීම. ටයිප් ඉඟි සාපේක්ෂව අළුත් ඒවා වන අතර ජූරි සභාව වඩාත් පයිතොනික් විසඳුම වන විට ඒවා තවමත් ක්රියාත්මක නොවේ. සාපේක්ෂව මතභේදාත්මක නමුත් සාමාන්ය සංසන්දනයක්: ටයිප් ඉඟි මඟින් බලාත්මක කළ හැකි ලියකියවිලි ආකාරයක් සපයයි, කේත ජනනය කිරීමට පෙර සහ දෝෂ තේරුම් ගැනීමට පහසුය, තාරාවන්ගේ යතුරු ලියනය කළ නොහැකි දෝෂ හසු කර ගත හැකි අතර සංඛ්යාත්මකව පරීක්ෂා කළ හැකිය (අසාමාන්ය ලෙස) හැඟීම නමුත් එය තවමත් ධාවන කාලයෙන් පිටත). අනෙක් අතට, තාරා ටයිප් කිරීම දිගු කලක් තිස්සේ පයිතොනික් ක්රමයක් වී ඇති අතර, ස්ථිතික යතුරු ලියනය පිළිබඳ සංජානන පොදු කාර්යයක් නොපෙන්වයි, අඩු වාචික වන අතර, සියලු ශක්ය වර්ග සහ පසුව සමහරක් පිළිගනු ඇත.
mypy
භාවිතා කරන පයිතන් මොඩියුලයකි importlib
. මෙය “ස්ථිතික වර්ග පරීක්ෂා කිරීම” දාර්ශනික ප්රශ්නයක් වන නමුත් සාමාන්ය භාෂා පරිවර්තකයා සහ ආනයන යන්ත්රෝපකරණ සම්බන්ධ බැවින් බොහෝ දෙනා අපේක්ෂා කරන දෙයට වඩා එය වෙනස් ය.
තාරාවන් ටයිප් කිරීම භයානක වන්නේ කවදාදැයි නොදැන නපුරු වීමට හේතුව මෙන්න. නිදසුනක් ලෙස: මෙන්න පයිතන් කේතය (නිසි ලෙස ඇතුල් කිරීම මඟ හැරීම), ඔබට තාරාවෙකු අවශ්ය වූ විට ඔබට බෝම්බයක් නොලැබෙන බවට වග බලා ගැනීම සඳහා සමතුලිතතාවය සහ නිකුත් කිරීමේ පන්තියේ කාර්යයන් ගැන සැලකිලිමත් වීමෙන් මෙම තත්වය වළක්වා ගත හැකි බව සලකන්න.
class Bomb:
def __init__(self):
""
def talk(self):
self.explode()
def explode(self):
print "BOOM!, The bomb explodes."
class Duck:
def __init__(self):
""
def talk(self):
print "I am a duck, I will not blow up if you ask me to talk."
class Kid:
kids_duck = None
def __init__(self):
print "Kid comes around a corner and asks you for money so he could buy a duck."
def takeDuck(self, duck):
self.kids_duck = duck
print "The kid accepts the duck, and happily skips along"
def doYourThing(self):
print "The kid tries to get the duck to talk"
self.kids_duck.talk()
myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
class EvilDuck(Duck)
(සහ) අභිබවා යන කතාවක් නිර්මාණය කළ හැකිය . එසේත් නැතිනම්, class ChineseCancerDuck(Duck)
වසර ගණනාවකට පසු නොපෙන්වන අතුරු ආබාධයකින්. ඔබේ දරුවා අධීක්ෂණය කිරීම වඩා හොඳ වනු ඇත (සහ ඇගේ සෙල්ලම් බඩු හොඳින් පරීක්ෂා කර බලන්න :)
__file__
වෙනත් දෙයක් අදහස් කිරීම සඳහා ඔබට ගුණාංගය (ගොනු වැනි වස්තු හඳුනා ගැනීමට බහුලව භාවිතා වේ) අභිබවා යාමෙන් ඔබට පයිතන් කේත විශාල ප්රමාණයක් ලබා ගත හැකිය .
isinstance(o, str)
මම හිතන්නේ පයිතන් වැනි ගතික භාෂාවක් භාවිතා කිරීමේ සිසිල්ම දෙය නම් ඔබ ඇත්තටම එවැනි දෙයක් පරීක්ෂා කර බැලිය යුතු නැති බවයි.
මම ඔබේ වස්තුවට අවශ්ය ක්රම අමතා අල්ලා ගන්නෙමි AttributeError
. පසුකාලීනව මෙය පරීක්ෂා කිරීම සඳහා වස්තුවක් සමච්චල් කිරීම වැනි විවිධ කාර්යයන් ඉටු කිරීම සඳහා වෙනත් (සම්බන්ධයක් නැති) වස්තූන් සමඟ ඔබේ ක්රම ඇමතීමට ඉඩ ලබා දේ.
සමග වෙබ් ලකුණු දත්ත ලබා විට මම මේ ගොඩක් භාවිත කර urllib2.urlopen()
ඇති නැවත වන වැනි ගොනු වස්තුව. මෙය ගොනුවකින් කියවන ඕනෑම ක්රමයකට පාහේ යැවිය හැක, මන්ද එය read()
සැබෑ ගොනුවක් ලෙස එකම ක්රමය ක්රියාත්මක කරන බැවිනි .
නමුත් මට විශ්වාසයි භාවිතා කිරීමට කාලයක් හා ස්ථානයක් ඇති බව isinstance()
, එසේ නොමැති නම් එය එහි නොතිබෙනු ඇත :)
වඩාත් සංකීර්ණ ආකාරයේ වලංගු කිරීම් සඳහා, පයිතන් වර්ගයේ ඉඟි විවරණයන් මත පදනම්ව වලංගු කිරීමේ යතුරු ලියනයෙහි ප්රවේශයට මම කැමතියි :
from typeguard import check_type
from typing import List
try:
check_type('mylist', [1, 2], List[int])
except TypeError as e:
print(e)
ඔබට ඉතා පිරිසිදු හා කියවිය හැකි ආකාරයකින් ඉතා සංකීර්ණ වලංගු කිරීම් කළ හැකිය.
check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo)
වර්ගයක __name__ භාවිතා කරමින් ඔබට විචල්ය වර්ගයක් තිබේදැයි පරීක්ෂා කළ හැකිය.
උදා:
>>> a = [1,2,3,4]
>>> b = 1
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'
හියුගෝ වෙත:
ඔබ බොහෝ විට අදහස් list
වෙනුවට array
, නමුත් වර්ග පරික්ෂාව සමග මුළු ගැටලුව ලකුණු බව - ඔබ ප්රශ්නයට වස්තුව ලැයිස්තුවක් නම් දැන ගැනීමට අවශ්ය නැහැ, ඔබ එය අනුක්රමයක් එය තනි වස්තුවක් වේ නම් හෝ යම් ආකාරයක වේ නම් දැන ගැනීමට අවශ්ය. එබැවින් එය අනුක්රමයක් ලෙස භාවිතා කිරීමට උත්සාහ කරන්න.
ඔබට පවතින වස්තුවකට වස්තුව එක් කිරීමට අවශ්ය යැයි පවසන්න, නැතහොත් එය වස්තු අනුක්රමයක් නම්, ඒ සියල්ල එකතු කරන්න
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
මේ සමඟ ඇති එක් උපක්රමයක් නම්, ඔබ නූල් සහ / හෝ නූල් අනුක්රමය සමඟ වැඩ කරන්නේ නම් - එය උපක්රමශීලී ය, නූලක් බොහෝ විට තනි වස්තුවක් ලෙස සිතන නමුත් එය අක්ෂර අනුක්රමයකි. ඊට වඩා නරක ය, එය සැබවින්ම තනි දිග නූල් අනුක්රමයක් බැවින්.
මම සාමාන්යයෙන් මගේ API නිර්මාණය කිරීමට තෝරා ගන්නේ එය තනි අගයක් හෝ අනුක්රමයක් පමණක් පිළිගන්නා හෙයිනි - එය දේවල් පහසු කරයි. එය ක්රියාත්මක කිරීමට අපහසු නොවේ [ ]
නම් ඔබට අවශ්ය වේවා එය සමත් විට ඔබේ තනි අගය පමණ.
(මෙය නූල් සමඟ දෝෂ ඇති කළ හැකි වුවද, ඒවා අනුපිළිවෙල මෙන් පෙනේ.)
වර්ගය පරීක්ෂා කිරීම සඳහා සරල ක්රමයක් නම්, ඔබ දන්නා කෙනෙකු සමඟ එය සංසන්දනය කිරීමයි.
>>> a = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True
මම හිතන්නේ හොඳම ක්රමය ඔබේ විචල්යයන් හොඳින් ටයිප් කිරීමයි. "ටයිප් කිරීමේ" පුස්තකාලය භාවිතා කිරීමෙන් ඔබට මෙය කළ හැකිය.
උදාහරණයක්:
from typing import NewType
UserId = NewType ('UserId', int)
some_id = UserId (524313
) `
ලබා දී ඇති අගය කුමන අක්ෂර වර්ගය දැයි පරීක්ෂා කිරීමට ඔබට පහත පේළියෙන් පරීක්ෂා කළ හැකිය:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)