检查Python变量类型的最佳(惯用)方法是什么?

时间:2008-12-18 19:27:57

标签: python types typechecking

我需要知道Python中的变量是字符串还是字典。以下代码有什么问题吗?

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),我会改变主意。

但是感谢barefanatic提醒我使用dict(作为案例陈述)比使用if / elif / else系列更为清晰。

让我详细说明我的用例。如果变量是一个字符串,我需要将它放在一个列表中。如果它是一个字典,我需要一个唯一值的列表。这就是我想出的:

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

10 个答案:

答案 0 :(得分:315)

如果某人将unicode字符串传递给您的函数会发生什么?还是一个源自dict的类?或者是一个实现类似dict的界面的类?以下代码涵盖前两种情况。如果您使用的是Python 2.6,则根据collections.Mapping,您可能希望使用ABC PEP而不是dict

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

答案 1 :(得分:57)

type(dict())说“做一个新的词典,然后找出它的类型是什么”。说“dict”更快。 但是,如果您只想检查类型,则更为惯用的方式是isinstance(x, dict)

注意,isinstance还包括子类(感谢Dustin):

class D(dict):
    pass

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True

答案 2 :(得分:34)

Python中的内置类型有内置名称:

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

顺便说一下运算符。但是,类型检查(如果你想调用它)通常是通过在try-except子句中包装特定于类型的测试来完成的,因为它不是那么重要的变量类型,而是你是否可以做某些事情。有与否的事。

答案 3 :(得分:19)

isinstance优先于类型,因为当你将一个对象实例与它的超类进行比较时,它也会计算为True,这基本上意味着你不必特别使用旧代码将它与dict或str子类一起使用。< / p>

例如:

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

当然,在某些情况下,您可能不会想要这种行为,但这些行为 - 实际上 - 比您想要它的情况要少得多。

答案 4 :(得分:8)

我想我会采用鸭子打字方式 - “如果它像鸭子一样走路,它会像鸭子一样嘎嘎叫,它是一只鸭子”。这样您就不必担心字符串是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']
[]

这里的专家欢迎评论这种类型的鸭子使用方法,我一直在使用它,但最近介绍了它背后的确切概念,并对此非常兴奋。所以我想知道这是不是太过分了。

答案 5 :(得分:6)

我认为实际上可能更喜欢

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

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

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

答案 6 :(得分:3)

这应该有效 - 所以不,你的代码没有任何问题。但是,它也可以用dict完成:

{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)()

答案 7 :(得分:3)

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

Python的类型检查模块

该软件包为Python函数,方法和生成器提供了强大的运行时类型检查功能。无需自定义预处理器或对语言进行更改,类型检查包允许程序员和质量保证工程师对其代码的输入和输出进行精确断言。

答案 8 :(得分:1)

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

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,但是......

答案 9 :(得分:0)

*sigh*

不,python中的类型检查参数不是必需的。它从不 必要的。

如果您的代码接受字符串或dict对象,则您的设计会被破坏。

这是因为如果您还不知道对象的类型 在你自己的程序中,你已经做错了。

Typechecking会损害代码重用并降低性能。有一个功能 根据传递的对象的类型执行不同的操作 容易出错并且行为难以理解和维护。

您有以下更合理的选择:

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

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

让你的函数假设传递的参数始终是一个列表。这样,如果你需要将一个字符串传递给函数,你只需:

myfunction([some_string])

如果您需要传递dict,请执行以下操作:

myfunction(unique_values(some_dict))

这是您最好的选择,它干净,易于理解和维护。任何人 阅读代码立即了解正在发生的事情,而你却没有 对于typecheck。

2)制作两个函数,一个接受字符串列表,另一个接受 http://stardict.sourceforge.net/Dictionaries.php下载。你可以在最方便的时候在内部拨打另一个电话 方式(myfunction_dict可以创建字符串列表并调用myfunction_list)。

无论如何,不要进行类型检查。这是完全没有必要的,只有 缺点。以您不需要进行类型检查的方式重构代码。 无论是短期还是长期,您只能从中获益。