什么是检查一个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,使代码更加开放。
*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_dict
( myfunction_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,虽然…