这个问题在这里已经有答案了:

我需要知道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() 功能?

有帮助吗?

解决方案

如果有人将 unicode 字符串传递给您的函数会发生什么?或者从 dict 派生的类?或者一个实现类似字典的接口的类?以下代码涵盖前两种情况。如果您使用的是 Python 2.6,您可能需要使用 collections.Mapping 代替 dict 根据 ABC PEP.

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

其他提示

type(dict()) 说“创建一个新字典,然后找出它的类型是什么”。直接说“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

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

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

顺便说一句,请注意 操作员。但是,类型检查(如果您想这样称呼它)通常是通过将特定于类型的测试包装在 try- except 子句中来完成的,因为重要的不是变量的类型,而是您是否可以执行某些操作有或没有的东西。

isinstance 比 type 更可取,因为当您将对象实例与其超类进行比较时,它的计算结果也为 True,这基本上意味着您无需对旧代码进行特殊处理即可将其与 dict 或 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']
[]

欢迎这里的专家对鸭子打字的这种用法发表评论,我一直在使用它,但最近了解了它背后的确切概念,对此我感到非常兴奋。所以我想知道这样做是否太过分了。

我认为实际做可能会更好

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

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

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

您可能想检查一下类型检查。http://pypi.python.org/pypi/typecheck

Python 的类型检查模块

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

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

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*

不,Python 中的参数类型检查不是必需的。这是 绝不 必要的。

如果您的代码接受字符串或字典对象,那么您的设计就被破坏了。

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

类型检查会损害代码重用并降低性能。具有根据对象的类型执行不同事物的函数,这是易经的,并且更难理解和维护的行为。

您有以下更明智的选择:

1)创建一个函数 unique_values 将字典转换为唯一的值列表:

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

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

myfunction([some_string])

如果你需要传递一个字典,你可以:

myfunction(unique_values(some_dict))

这是你最好的选择,它干净、易于理解和维护。任何阅读代码的人都会了解正在发生的事情,而您不必打字。

2)制作两个功能,一个功能接受字符串列表,一个接受命令。您可以以最方便的方式在内部拨打另一个电话(myfunction_dict 可以创建一个字符串列表并调用 myfunction_list).

任何状况之下, 不进行打字检查. 。这是完全不必要的,只有缺点。以不需要类型检查的方式重构代码。从短期和长期来看,这样做只会给你带来好处。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top