我需要知道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更受欢迎,我会改变主意)。

但是感谢nakedfanatic提醒我,使用dict(作为case语句)通常比使用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()函数?


当前回答

这应该可以工作-所以,不,您的代码没有任何问题。然而,它也可以用dict来完成:

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

更简洁,更精辟,你说呢?


编辑. .听从了Avisser的建议,代码也是这样工作的,而且看起来更好:

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

其他回答

如果有人将unicode字符串传递给你的函数会发生什么?还是从dict派生的类?还是一个实现字典式接口的类?下面的代码涵盖了前两种情况。如果您使用的是Python 2.6,则可能需要使用集合。根据ABC PEP映射而不是字典。

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

我觉得还是去做比较好

if isinstance(x, str):
    do_something_with_a_string(x)
elif isinstance(x, dict):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

另一种形式,取决于你的代码,一种或另一种甚至可能被认为是更好的。一是三思而后行

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

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

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

我想我会采用鸭子打字的方法——“如果它走路像鸭子,它呱呱叫得像鸭子,它就是鸭子”。这样就不需要担心字符串是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']
[]

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

这应该可以工作-所以,不,您的代码没有任何问题。然而,它也可以用dict来完成:

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

更简洁,更精辟,你说呢?


编辑. .听从了Avisser的建议,代码也是这样工作的,而且看起来更好:

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

你可能想要检查typcheck。 http://pypi.python.org/pypi/typecheck

Python类型检查模块

这个包为Python函数、方法和生成器提供了强大的运行时类型检查工具。不需要自定义预处理器或改变语言,类型检查包允许程序员和质量保证工程师对他们的代码的输入和输出做出精确的断言。