ما هو أفضل (الاصطلاحية) طريقة للتحقق من نوع بايثون متغير ؟ [مكررة]

StackOverflow https://stackoverflow.com/questions/378927

  •  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

أما النهج الآخر من غويدو و هو شكل من وظيفة الحمولة الزائدة مما يترك التعليمات البرمجية الخاصة بك أكثر المفتوح.

http://www.artima.com/weblogs/viewpost.jsp?thread=155514

التي يجب العمل بحيث لا, لا يوجد شيء خاطئ مع التعليمات البرمجية الخاصة بك.ومع ذلك, فإنه يمكن أيضا أن يتم ذلك مع ديكت:

{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.يمكنك فقط الحصول على فوائد في ذلك ، سواء في المدى القصير و المدى الطويل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top