检查数字零时的多重条件声明 - python
Multiple condition declaration when checking for numerical zero - python
Idiomatic Python - checking for zero 上有一个问题,但考虑这个问题时还要检查条件内的变量类型。
给定 0 if not variable else variable
样式语句,它会让 nully 对象溜走,例如
>>> 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/更合适?
但它也有问题,因为它让布尔类型溜走,导致一些非常令人不安的事情发生,例如 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
运算符不能接受 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)
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 方法是什么?
- 此外,重要的是不要喜欢布尔类型的滑动并引发错误而不是让它 return 为零,这怎么办?
- 和如何解决
TypeError: unsupported operand type(s) for |: 'float' and 'float'
以检查 (x|y) == 0
以 x 和 y 作为浮点类型?
考虑到 PEP 20 的 "Simple is better than complex",我会声称,如果您想检查一个值是否具有布尔值以外的数字类型(请注意:布尔值 是 Python 中的数字类型,并且 1/True
是有效的),最 pythonic 的方法是明确地做到这一点,没有任何按位运算或依赖隐式检查。
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
Idiomatic Python - checking for zero 上有一个问题,但考虑这个问题时还要检查条件内的变量类型。
给定 0 if not variable else variable
样式语句,它会让 nully 对象溜走,例如
>>> 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/更合适?
但它也有问题,因为它让布尔类型溜走,导致一些非常令人不安的事情发生,例如 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
运算符不能接受 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)
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 方法是什么?
- 此外,重要的是不要喜欢布尔类型的滑动并引发错误而不是让它 return 为零,这怎么办?
- 和如何解决
TypeError: unsupported operand type(s) for |: 'float' and 'float'
以检查(x|y) == 0
以 x 和 y 作为浮点类型?
考虑到 PEP 20 的 "Simple is better than complex",我会声称,如果您想检查一个值是否具有布尔值以外的数字类型(请注意:布尔值 是 Python 中的数字类型,并且 1/True
是有效的),最 pythonic 的方法是明确地做到这一点,没有任何按位运算或依赖隐式检查。
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