【发布时间】:2016-04-20 23:26:56
【问题描述】:
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 的代码是否更符合 Python 风格/更合适?
但这也是有问题的,因为它让布尔类型通过,这会导致一些非常令人不安的事情发生,例如 ZeroDivisionError 或 ValueError,例如:
>>> 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
所以问题是:
- 检查多个变量的值为零的 Python 方法是什么?
- 另外,重要的是不要喜欢 boolean 类型的 slip 并引发错误而不是让它返回零,如何做到这一点?
- 以及应该如何解决
TypeError: unsupported operand type(s) for |: 'float' and 'float'以检查(x|y) == 0与x 和y 作为浮点类型?
【问题讨论】:
-
如果您的数值运算取决于两个操作数的确切类型,显而易见(因此是 Pythonic)的解决方案是明确检查两个操作数的类型或处理预期的异常。
-
显式检查:“0 in (x,y)”怎么样?
-
@A.Haaji 这将在布尔值上失败:
0 in (True, False) => True -
0 in (x,y)和not (x and y)有区别吗? -
any(i is 0 for i in (x,y))怎么样?
标签: python conditional-statements zero typechecking or-operator