什么是检查一个Pythonvariables的types的最佳(惯用)方式?

我需要知道Python中的variables是string还是字典。 下面的代码有什么问题吗?

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提醒我,使用字典(作为一个case语句)通常比if / elif / else系列更清晰。

让我详细说明我的用例。 如果一个variables是一个string,我需要把它放在一个列表中。 如果是字典,我需要一个唯一值列表。 以下是我想到的:

 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()函数?

如果有人传递一个unicodestring到你的函数会发生什么? 还是从字典派生的类? 还是一个实现类似字典界面的类? 以下代码涵盖了前两种情况。 如果您使用的是Python 2.6,则可能需要按照ABC PEP使用collections.Mapping而不是dict

 def value_list(x): if isinstance(x, dict): return list(set(x.values())) elif isinstance(x, basestring): return [x] else: return None 

type(dict())说“做一个新的字典,然后找出它的types是什么”。 只是说“字典”更快。

但是如果你只想检查types,更常用的方法是isinstance(x, dict)

Python中的内置types已经build立了名称:

 >>> s = "hallo" >>> type(s) is str True >>> s = {} >>> type(s) is dict True 

顺便说一句, 运算符。 然而,types检查(如果你想这样调用的话)通常是通过在try-except子句中包装一个types特定的testing来完成的,因为它不是那么重要的variables的types,而是可以做一定的有没有东西。

isinstance比type更受欢迎,因为当你将一个对象实例与它的超类进行比较时,它的计算结果也是True,这基本上意味着你永远不必特别用你的旧代码来使用dict或str子类。

例如:

  >>> class a_dict(dict): ... pass ... >>> type(a_dict()) == type(dict()) False >>> isinstance(a_dict(), dict) True >>> 

当然,可能有些情况下你不想要这种行为,但是这种行为比你想要的情况要less得多。

我想我会去打鸭子的方法 – “如果它像鸭子一样走路,就像鸭子,鸭子一样嘎嘎叫”。 这样你就不用担心string是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替代forms,取决于你的代码之一或其他可能被认为比甚至更好。 一个是不要看你跳跃

 try: one, two = tupleOrValue except TypeError: one = tupleOrValue two = None 

另一种方法来自Guido,它是一种函数重载的forms,使代码更加开放。

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

*sigh*

不,python中的types查询参数是不必要的。 这是没有必要的。

如果你的代码接受一个string或字典对象,你的devise是打破。

这是因为如果你不知道自己的程序中是否有对象的types,那么你已经做错了。

types检查会损害代码重用并降低性能。 具有根据传递的对象的types执行不同事情的函数是容易出错的,并且具有难以理解和维护的行为。

您有以下更好的select:

1)创build一个函数unique_values ,用于转换唯一值列表中的字典:

 def unique_values(some_dict): return list(set(some_dict.values())) 

让你的函数假设传递的参数总是一个列表。 这样,如果你需要传递一个string给函数,你只需要:

 myfunction([some_string]) 

如果你需要通过一个字典,你可以:

 myfunction(unique_values(some_dict)) 

这是你最好的select,它很干净,易于理解和维护。 任何人都能够立即阅读代码,了解正在发生的事情,而且不必检查。

2)做两个函数,一个接受string列表,另一个接受字典。 您可以用最方便的方式在内部调用另一个myfunction_dictmyfunction_dict可以创build一个string列表并调用myfunction_list )。

在任何情况下, 不要检查 。 这是完全没有必要的,只有缺点。 重构你的代码,而不需要进行types检查。 你只能从短期和长期获益。

你可能想看看typecheck。 http://pypi.python.org/pypi/typecheck

Python的types检查模块

该软件包为Python函数,方法和生成器提供了强大的运行时types检查function。 不需要定制的预处理器或对语言的改动,typecheck软件包允许程序员和质量保证工程师对其代码的input和输出做出精确的断言。

这应该工作 – 所以不,你的代码没有任何问题。 不过,也可以用字典来完成:

 {type(str()): do_something_with_a_string, type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)() 

你会不会说一点简洁和pythonic?


编辑..听着Avisser的build议,代码也是这样工作,看起来更好:

 {str: do_something_with_a_string, dict: do_something_with_a_dict}.get(type(x), errorhandler)() 

我一直在使用不同的方法:

 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,虽然…