将字符串与字节进行比较时,可以让 Python3 报错吗
Can you make Python3 give an error when comparing strings to bytes
将代码从 Python 2 转换为 Python 3 时,一个问题是测试字符串和字节是否相等时的行为发生了变化。例如:
foo = b'foo'
if foo == 'foo':
print("They match!")
在 Python 3 上不打印任何内容,而 "They match!" 在 Python 2 上不打印任何内容。在这种情况下很容易发现,但在许多情况下,检查是对可能已被删除的变量执行的在其他地方定义,因此没有明显的类型信息。
我想让 Python 3 解释器在字符串和字节之间进行相等性测试时给出错误,而不是默默地得出它们不同的结论。有什么办法可以做到这一点?
(EDITED: 修复我错误地建议在实例上修改 __eq__
会影响 ==
评估的问题,如@所建议的user2357112supportsMonica).
通常,您可以通过覆盖您想要保护的类型的 __eq__
方法来做到这一点。
不幸的是,这不能用于内置类型,特别是 str
和 bytes
,因此代码如下:
foo = b'foo'
bytes.__eq__ = ... # a custom equal function
# str.__eq__ = ... # if it were 'foo' == foo (or `type(foo)`)
if foo == 'foo':
print("They match!")
只会抛出:
AttributeError: 'bytes' object attribute '__eq__' is read-only
您可能需要手动用类似的东西来保护比较:
def str_eq_bytes(x, y):
if isinstance(x, str) and isinstance(y, bytes):
raise TypeError("Comparison between `str` and `bytes` detected.")
elif isinstance(x, bytes) and isinstance(y, str):
raise TypeError("Comparison between `bytes` and `str` detected.")
使用如下:
foo = 'foo'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
# They match!
foo = 'bar'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
# <nothing gets printed>
foo = b'foo'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
TypeError: Comparison between `bytes` and `str` detected.
另一种选择是破解您自己的 Python 分支并覆盖 __eq__
。
请注意,Pypy 也不允许您覆盖内置类型的方法。
有一个选项,-b
,你可以传递给Python解释器,使其在比较byte/str时发出警告或错误。
> python --help
usage: /bin/python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-b : issue warnings about str(bytes_instance), str(bytearray_instance)
and comparing bytes/bytearray with str. (-bb: issue errors)
这会产生一个 BytesWarning,如下所示:
> python -bb -i
Python 3.8.0
Type "help", "copyright", "credits" or "license" for more information.
>>> v1 = b'foo'
>>> v2 = 'foo'
>>> v1 == v2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BytesWarning: Comparison between bytes and string
将代码从 Python 2 转换为 Python 3 时,一个问题是测试字符串和字节是否相等时的行为发生了变化。例如:
foo = b'foo'
if foo == 'foo':
print("They match!")
在 Python 3 上不打印任何内容,而 "They match!" 在 Python 2 上不打印任何内容。在这种情况下很容易发现,但在许多情况下,检查是对可能已被删除的变量执行的在其他地方定义,因此没有明显的类型信息。
我想让 Python 3 解释器在字符串和字节之间进行相等性测试时给出错误,而不是默默地得出它们不同的结论。有什么办法可以做到这一点?
(EDITED: 修复我错误地建议在实例上修改 __eq__
会影响 ==
评估的问题,如@所建议的user2357112supportsMonica).
通常,您可以通过覆盖您想要保护的类型的 __eq__
方法来做到这一点。
不幸的是,这不能用于内置类型,特别是 str
和 bytes
,因此代码如下:
foo = b'foo'
bytes.__eq__ = ... # a custom equal function
# str.__eq__ = ... # if it were 'foo' == foo (or `type(foo)`)
if foo == 'foo':
print("They match!")
只会抛出:
AttributeError: 'bytes' object attribute '__eq__' is read-only
您可能需要手动用类似的东西来保护比较:
def str_eq_bytes(x, y):
if isinstance(x, str) and isinstance(y, bytes):
raise TypeError("Comparison between `str` and `bytes` detected.")
elif isinstance(x, bytes) and isinstance(y, str):
raise TypeError("Comparison between `bytes` and `str` detected.")
使用如下:
foo = 'foo'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
# They match!
foo = 'bar'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
# <nothing gets printed>
foo = b'foo'
if str_eq_bytes(foo, 'foo') or foo == 'foo':
print("They match!")
TypeError: Comparison between `bytes` and `str` detected.
另一种选择是破解您自己的 Python 分支并覆盖 __eq__
。
请注意,Pypy 也不允许您覆盖内置类型的方法。
有一个选项,-b
,你可以传递给Python解释器,使其在比较byte/str时发出警告或错误。
> python --help
usage: /bin/python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-b : issue warnings about str(bytes_instance), str(bytearray_instance)
and comparing bytes/bytearray with str. (-bb: issue errors)
这会产生一个 BytesWarning,如下所示:
> python -bb -i
Python 3.8.0
Type "help", "copyright", "credits" or "license" for more information.
>>> v1 = b'foo'
>>> v2 = 'foo'
>>> v1 == v2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BytesWarning: Comparison between bytes and string