检查数字零时的多个条件声明 - python

时间:2016-01-15 11:18:47

标签: python conditional-statements zero typechecking or-operator

Idiomatic Python - checking for zero上有一个问题,但是在考虑条件内的变量类型的同时考虑这个问题。

给定0 if not variable else variable样式语句,它将让无效对象滑过,例如

>>> x, y = None, []
>>> 0 if not(x and y) else x / y
0
>>> x, y = None, 0
>>> 0 if not(x and y) else x / y
0
>>> x, y = 0, 1
>>> 0 if not(x and y) else x / y
0
>>> x, y = 2, ""
>>> 0 if not(x and y) else x / y
0
>>> x, y = 2, 1
>>> 0 if not(x and y) else x / y
2

但如果我明确检查变量'如果值为零,则会更好一些,因为当两种类型都不同时会引发错误或者无法与零值进行比较,例如:

>>> x, y = 2, ""
>>> 0 if (x&y) == 0 else x / y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'int' and 'str'
>>> x,y = "",""
>>> 0 if (x&y) == 0 else x / y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'str' and 'str'
>>> x,y = [],[]
>>> 0 if (x&y) == 0 else x / y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'list' and 'list'

通常在定义检查数值的条件时,类似0 if (x|y) == 0 else x/y代码更pythonic /更合适?

但它也存在问题,因为它让布尔类型漏掉并导致一些非常令人不安的事情,如ZeroDivisionErrorValueError,例如:

>>> x,y = True, True
>>> 0 if (x&y) == 0 else x / y
1
>>> x,y = True, False
>>> 0 if (x&y) == 0 else x / y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> x,y = False, True
>>> 0 if (x&y) == 0 else x / y
0
>>> x,y = False, True
>>> 0 if (x&y) == 0 else math.log(x/y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error

此外,当变量的类型是数字但有些不同时,这会导致问题:

>>> x, y = 1, 3.
>>> 0 if (x|y) == 0 else math.log(x/y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'int' and 'float'

而且_or运算符无法浮动,这很奇怪:

>>> x, y = 1., 3.
>>> 0 if (x&y) == 0 and type(x) == type(y) == float else math.log(x/y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'float' and 'float'
>>> x, y = 1., 3.
>>> 0 if (x&y) == 0. and type(x) == type(y) == float else math.log(x/y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'float' and 'float'
>>> x, y = 1, 3
>>> 0 if (x&y) == 0 and type(x) == type(y) == float else math.log(x/y)
-1.0986122886681098

所以问题是:

  • 为零值检查多个变量的pythonic方法是什么?
  • 另外,重要的是不喜欢布尔类型滑动并引发错误而不是让它返回零,这怎么可以呢?
  • 并且如何解析TypeError: unsupported operand type(s) for |: 'float' and 'float'以x和y作为浮动类型检查(x|y) == 0

1 个答案:

答案 0 :(得分:4)

考虑到PEP 20的“简单比复杂更好”,我会声称如果你想检查某个值是否具有布尔值以外的数字类型(mind:Boolean Python中的数字类型,而1/True是有效的),最谨慎的做法就是明确地做到这一点,没有任何按位操作或依赖隐式检查。

import numbers

if not isinstance(y, numbers.Number) or type(y) is bool:
    raise TypeError("y must be a number")
return x / y if y else 0