如何根据数据类型在python中设置条件?

011*_*100 19 python conditional types

这个问题似乎令人难以置信,但我无法弄清楚.我知道你可以检查python中的数据类型,但是如何根据数据类型设置条件?例如,如果我必须编写一个通过字典/列表排序并将所有整数相加的代码,那么如何隔离搜索以仅查找整数?

我想一个简单的例子看起来像这样:

y = []
for x in somelist:
    if type(x) == <type 'int'>:  ### <--- psuedo-code line
    y.append(x)
print sum(int(z) for z in y)
Run Code Online (Sandbox Code Playgroud)

那么对于第3行,我将如何设置这样的条件?

Jak*_*yer 40

怎么样,

if isinstance(x, int):
Run Code Online (Sandbox Code Playgroud)

但更清洁的方式就是这样

sum(z for z in y if isinstance(z, int))
Run Code Online (Sandbox Code Playgroud)

  • 进一步阅读:[python中的isinstance()和type()之间的差异](http://stackoverflow.com/q/1549801/1025391) (2认同)
  • 是的,这是实现他想做的事情的好方法。然而,可能值得指出他的问题的答案是“if type(x) == int”,但为什么这是一个坏主意。 (2认同)

Mis*_*agi 10

在Python中进行类型检查有一个非常大的"依赖".有很多方法可以处理类型,并且都有其优点和缺点.随着Python3,还出现了更多.

  • 显式类型相等

类型是第一类对象,您可以像处理任何其他值一样对待它们.因此,如果你想要某种类型的东西int,只需测试它:

if type(x) == int:
Run Code Online (Sandbox Code Playgroud)

这是最严格的测试类型:它需要确切的类型相等.通常,这不是你想要的:

  • 它排除了替代类型:a float无效,即使它的行为类似于int许多目的.
  • 它排除了子类和抽象类型:一个漂亮的打印int子类或者enum会被拒绝,即使它们是逻辑上的整数.
    • 这严重限制了便携性:Python2字符串可以是任一 strunicode,和整数可以是任一 intlong.

需要注意的是显式类型的平等其低级别操作的用途:

  • 某些类型不能被子类化,例如slice.在这里,明确的检查更明确.
  • 某些低级操作(如序列化或C-API)需要特定类型.

变种

还可以对__class__属性执行比较:

if x.__class__ == int:
Run Code Online (Sandbox Code Playgroud)

注意,如果一个类定义了一个__class__属性,那么它就不一样了type(x).

当有多个要检查的类时,使用dictto dispatch操作更具可扩展性,并且比显式检查更快(≥5-10种类型).这对转换和序列化特别有用:

dispatch_dict = {float: round, str: int, int: lambda x: x}
def convert(x):
    converter = self.dispatch_dict[type(x)]  # lookup callable based on type
    return converter(x)
Run Code Online (Sandbox Code Playgroud)
  • 实例检查显式类型

惯用类型测试使用isinstance 内置:

if isinstance(x, int):
Run Code Online (Sandbox Code Playgroud)

此检查既准确又高效.这通常是人们想要检查类型的原因:

  • 它正确处理子类型.一个漂亮的打印int子类仍将通过此测试.
  • 它允许一次检查多种类型.在Python2中,do isinstance(x, (int, long))会获得所有内置整数.

最重要的是,大多数情况下,缺点是微不足道的:

  • 它仍然接受以奇怪方式表现的时髦子类.由于任何事情都可以以奇怪的方式表现出来,这是徒劳的.
  • 它很容易被过多的限制:很多人检查isinstance(x, list)时,任何序列(如tuple),甚至可迭代(例如generator)会做的一样好.对于通用库而言,这比脚本或应用程序更受关注.

变种

如果您已有类型,则issubclass行为相同:

if issubclass(x_type, int):
Run Code Online (Sandbox Code Playgroud)
  • 实例检查抽象类型

Python有一个抽象基类的概念.松散地说,这些表达了类型的含义,而不是它们的层次结构:

if isinstance(x, numbers.Real):  # accept anything you can sum up like a number
Run Code Online (Sandbox Code Playgroud)

换句话说,类型(x)不一定继承,numbers.Real但必须表现得像它.不过,这是一个非常复杂和困难的概念:

  • 如果您正在寻找基本类型,这往往是矫枉过正.整数只是int大部分时间.
  • 来自其他语言的人经常会混淆其概念.
    • 区别于例如C++,重点是抽象基类而不是抽象基类.
    • ABCs可以像Java接口一样使用,但可能仍然具有具体的功能.

但是,它对通用库和抽象非常有用.

  • 许多函数/算法不需要显式类型,只需要它们的行为.
    • 如果您只需要按键查找内容,则将您dict限制为特定的内存类型.相比之下,collections.abc.Mapping还包括数据库包装器,大型磁盘支持的字典,惰性容器,... - 和dict.
  • 它允许表达部分类型约束.
    • 没有严格的基类型实现迭代.但是如果你检查对象collections.abc.Iterable,它们都会for循环工作.
  • 它允许创建显示为相同抽象类型的单独的优化实现.

虽然通常不需要一次性脚本,但我强烈建议将其用于超出一些python版本的任何内容.

  • 暂时转换

处理类型的惯用方法不是测试它们,而是假设它们是兼容的.如果您已经预期输入中存在一些错误的类型,只需跳过所有不兼容的内容:

try:
    ix = int(x)
except (ValueError, TypeError):
    continue  # not compatible with int, try the next one
else:
    a.append(ix)
Run Code Online (Sandbox Code Playgroud)

这实际上不是类型检查,但通常用于相同的意图.

  • 保证您在输出中具有预期的类型.
  • 它在将错误类型,例如专业一些有限的回旋余地floatint.
  • 它的工作原理,你不知道哪些类型符合int.

主要缺点是它是一个明确的转变.

  • 您可以默默地接受"错误"值,例如转换str包含文字的值.
  • 它不必要的转换,甚至类型,这将是不够好,比如floatint时候,你只需要数字.

转换是某些特定用例的有效工具.如果你大致知道你的输入是什么,它最有效,并且必须保证你的输出.

  • 控制输入

最好的做法是确保您不必首先检查类型.这是一个元主题,因为它强烈依赖于用例.

在这里,somelist应该永远不会将非数字放入其中.