ما هو أفضل (الاصطلاحية) طريقة للتحقق من نوع بايثون متغير ؟ [مكررة]
-
22-08-2019 - |
سؤال
هذا السؤال سبق الجواب هنا:
أريد أن أعرف إذا كان متغير في بيثون هو سلسلة أو dict.هل هناك أي شيء خاطئ مع التعليمات البرمجية التالية?
if type(x) == type(str()):
do_something_with_a_string(x)
elif type(x) == type(dict()):
do_somethting_with_a_dict(x)
else:
raise ValueError
التحديث:قبلت avisser الجواب (على الرغم من أنني سوف أغير رأيي إذا كان شخص ما يفسر لماذا isinstance
المفضل على type(x) is
).
ولكن بفضل nakedfanatic لتذكيري أنه في كثير من الأحيان نظافة استخدام ديكت (مثل بيان حالة) من إذا/أليف/آخر السلسلة.
اسمحوا لي أن أوضح على استخدام القضية.إذا كان المتغير هو سلسلة ، أنا بحاجة إلى وضعه في القائمة.إذا كان ديكت أريد قائمة من القيم الفريدة.هنا ما جئت به:
def value_list(x):
cases = {str: lambda t: [t],
dict: lambda t: list(set(t.values()))}
try:
return cases[type(x)](x)
except KeyError:
return None
إذا isinstance
ويفضل كيف تكتب هذا value_list()
وظيفة ؟
المحلول
ماذا يحدث إذا كان شخص ما يمر سلسلة unicode إلى وظيفة ؟ أو فئة مشتقة من ديكت?أو فئة تنفيذ dict-مثل واجهة ؟ البرمجية التالية يغطي الأولى اثنين من الحالات.إذا كنت تستخدم بايثون 2.6 قد ترغب في استخدام collections.Mapping
بدلا من dict
كما في ABC بيب.
def value_list(x):
if isinstance(x, dict):
return list(set(x.values()))
elif isinstance(x, basestring):
return [x]
else:
return None
نصائح أخرى
type(dict())
يقول "جديدة ديكت ثم معرفة ما هو نوع".انها أسرع من أن أقول فقط "ديكت".ولكن إذا كنت تريد فقط التحقق من نوع أكثر الاصطلاحية طريقة isinstance(x, dict)
.
ملاحظة ، isinstance
كما يشمل أقسام فرعية (شكرا داستن):
class D(dict):
pass
d = D()
print("type(d) is dict", type(d) is dict) # -> False
print("isinstance (d, dict)", isinstance(d, dict)) # -> True
المدمج في أنواع في بيثون قد بنيت في الأسماء:
>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True
راجع للشغل ملاحظة هو المشغل.ومع ذلك ، فإن التحقق من نوع (إذا كنت تريد أن نسميها) وعادة ما يتم لف نوع معين الاختبار في المحاولة-باستثناء شرط ، كما انها ليست كثيرا على نوع المتغير هذا هو المهم, ولكن ما إذا كان يمكنك أن تفعل شيئا معينا مع ذلك أم لا.
isinstance هو الأفضل على نوع لأنه أيضا بتقييم صحيح عند مقارنة مثيل كائن مع انها الفائقة ، مما يعني أنك لن يكون من أي وقت مضى خاصة القضية القديم الخاص بك رمز لاستخدامه مع ديكت أو str فرعية.
على سبيل المثال:
>>> class a_dict(dict):
... pass
...
>>> type(a_dict()) == type(dict())
False
>>> isinstance(a_dict(), dict)
True
>>>
بالطبع قد تكون هناك حالات حيث كنت لا تريد هذا السلوك ، ولكن تلك هي –أمل– الكثير أقل شيوعا من حالات حيث كنت لا تريد ذلك.
أعتقد أنني سوف تذهب بطة الكتابة النهج - "إذا كان يمشي كالبطة فهي الدجالين مثل البطة ، بطة".بهذه الطريقة سوف لا داعي للقلق حول إذا كانت سلسلة unicode أو ascii.
هنا هو ما سوف تفعل:
In [53]: s='somestring'
In [54]: u=u'someunicodestring'
In [55]: d={}
In [56]: for each in s,u,d:
if hasattr(each, 'keys'):
print list(set(each.values()))
elif hasattr(each, 'lower'):
print [each]
else:
print "error"
....:
....:
['somestring']
[u'someunicodestring']
[]
الخبراء هنا مرحبا بكم في التعليق على هذا النوع من الاستخدام من ducktyping, لقد تم استخدامه ولكن حصلت على عرض مفهوم بالضبط وراء ذلك في الآونة الأخيرة وأنا متحمس جدا حول هذا الموضوع.لذا أود أن أعرف إذا كان هذا مبالغة في القيام.
أعتقد أنه قد يكون من المفضل أن تفعل في الواقع
if isinstance(x, str):
do_something_with_a_string(x)
elif isinstance(x, dict):
do_somethting_with_a_dict(x)
else:
raise ValueError
2 أشكال بديلة ، اعتمادا على التعليمات البرمجية الخاصة بك واحدة أو أخرى ربما يعتبر أفضل من ذلك حتى.واحد هو أن لا ننظر قبل نقلة
try:
one, two = tupleOrValue
except TypeError:
one = tupleOrValue
two = None
أما النهج الآخر من غويدو و هو شكل من وظيفة الحمولة الزائدة مما يترك التعليمات البرمجية الخاصة بك أكثر المفتوح.
التي يجب العمل بحيث لا, لا يوجد شيء خاطئ مع التعليمات البرمجية الخاصة بك.ومع ذلك, فإنه يمكن أيضا أن يتم ذلك مع ديكت:
{type(str()): do_something_with_a_string,
type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()
قليلا أكثر إيجازا pythonic لن أقول لك ؟
تحرير..الالتفات Avisser نصيحة رمز أيضا يعمل مثل هذا ، تبدو أجمل:
{str: do_something_with_a_string,
dict: do_something_with_a_dict}.get(type(x), errorhandler)()
قد تحتاج إلى تحقق من typecheck.http://pypi.python.org/pypi/typecheck
نوع التحقق وحدة بيثون
توفر هذه الحزمة قوية وقت التشغيل typechecking مرافق الثعبان الوظائف والأساليب المولدات.دون الحاجة مخصص المعالج أو تعديلات على اللغة ، typecheck حزمة يسمح المبرمجين و ضمان الجودة المهندسين لجعل دقيقة تأكيدات حول الإدخال و الإخراج من التعليمات البرمجية الخاصة بهم.
لقد تم استخدام نهج مختلف:
from inspect import getmro
if (type([]) in getmro(obj.__class__)):
# This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
# This one is a dict, or ...
لا أستطيع أن أتذكر لماذا كنت تستخدم هذا بدلا من isinstance ، على الرغم من...
*sigh*
لا typechecking الحجج في بايثون ليست ضرورية.فمن أبدا من الضروري.
إذا كان لديك رمز يقبل أي سلسلة أو ديكت كائن التصميم الخاص بك مكسورة.
الذي يأتي من حقيقة أنه إذا كنت لا تعرف بالفعل نوع من كائن في البرنامج الخاص بك, إذا كنت تفعل شيئا خاطئا بالفعل.
Typechecking يضر إعادة استخدام التعليمات البرمجية ويقلل من الأداء.وجود وظيفة ينفذ أشياء مختلفة اعتمادا على نوع الكائن الذي تم تمريره هو علة المعرضة لديه السلوك الصعب فهم والحفاظ عليها.
لديك التالية تعقلا خيارات:
1) جعل وظيفة unique_values
الذي يحول dicts فريدة من نوعها في قوائم القيم:
def unique_values(some_dict):
return list(set(some_dict.values()))
جعل الخاص بك وظيفة نفترض الحجة مرت دائما قائمة.بهذه الطريقة, إذا كنت تحتاج إلى تمرير سلسلة إلى وظيفة لك:
myfunction([some_string])
إذا كنت بحاجة إلى تمرير أنه ديكت ، يمكنك القيام به:
myfunction(unique_values(some_dict))
هذا هو الخيار الأفضل هو نظيفة وسهلة الفهم و الحفاظ عليها.أي شخص قراءة رمز immediatelly يفهم ما يحدث و لا يكون إلى typecheck.
2) جعل اثنين من وظائف ، أن تقبل قوائم سلاسل واحد يقبل
dicts.يمكنك إجراء مكالمة واحدة أخرى داخليا ، في الأكثر ملاءمة
الطريقة (myfunction_dict
يمكن إنشاء قائمة من سلاسل الاتصال myfunction_list
).
في أي حال ، لا typecheck.فإنه لا لزوم لها تماما و فقط سلبيات.ريفاكتور التعليمات البرمجية الخاصة بك بدلا من ذلك بطريقة لا تحتاج إلى typecheck.يمكنك فقط الحصول على فوائد في ذلك ، سواء في المدى القصير و المدى الطويل.