Python“in”不检查类型?

时间:2022-12-21 17:00:54
>>> False in [0]
True
>>> type(False) == type(0)
False

The reason I stumbled upon this:

我偶然发现这个的原因:

For my unit-testing I created lists of valid and invalid example values for each of my types. (with 'my types' I mean, they are not 100% equal to the python types) So I want to iterate the list of all values and expect them to pass if they are in my valid values, and on the other hand, fail if they are not. That does not work so well now:

对于我的单元测试,我为每个类型创建了有效和无效示例值的列表。 (我的意思是'我的类型',它们不是100%等于python类型)所以我想迭代所有值的列表并期望它们在我的有效值中通过,另一方面,失败如果他们不是。现在这种方法效果不佳:

>>> valid_values = [-1, 0, 1, 2, 3]
>>> invalid_values = [True, False, "foo"]
>>> for value in valid_values + invalid_values:
...     if value in valid_values:
...         print 'valid value:', value
... 
valid value: -1
valid value: 0
valid value: 1
valid value: 2
valid value: 3
valid value: True
valid value: False

Of course I disagree with the last two 'valid' values.

当然,我不同意最后两个“有效”的价值观。

Does this mean I really have to iterate through my valid_values and compare the type?

这是否意味着我真的必须遍历我的valid_values并比较类型?

4 个解决方案

#1


4  

As others have written, the "in" code does not do what you want it to do. You'll need something else.

正如其他人所写的那样,“in”代码不会按照您的意愿执行。你还需要别的东西。

If you really want a type check (where the check is for exactly the same type) then you can include the type in the list:

如果您真的想要进行类型检查(检查的类型完全相同),那么您可以在列表中包含该类型:

>>> valid_values = [(int, i) for i in [-1, 0, 1, 2, 3]]
>>> invalid_values = [True, False, "foo"]
>>> for value in [v[1] for v in valid_values] + invalid_values:
...   if (type(value), value) in valid_values:
...     print value, "is valid"
...   else:
...     print value, "is invalid"
... 
-1 is valid
0 is valid
1 is valid
2 is valid
3 is valid
True is invalid
False is invalid
foo is invalid
>>> 

Handling subtypes is a bit more difficult, and will depend on what you want to do.

处理子类型有点困难,并且取决于您想要做什么。

#2


15  

The problem is not the missing type checking, but because in Python bool is a subclass of int. Try this:

问题不在于缺少类型检查,而是因为在Python中bool是int的子类。尝试这个:

>>> False == 0
True
>>> isinstance(False, int)
True

#3


6  

According to the documentation, __contains__ is done by iterating over the collection and testing elements by ==. Hence the actual problem is caused by the fact, that False == 0 is True.

根据文档,__contains__是通过==迭代集合和测试元素来完成的。因此,实际问题是由False == 0为True的事实引起的。

#4


3  

Since True == 1 and False == 0 it's hard to differentiate between the two.

由于True == 1和False == 0,因此很难区分这两者。

One possible but ugly approach (which is also not guaranteed to work in all Python implementations but should be OK in CPython):

一种可能但丑陋的方法(也不保证在所有Python实现中都能工作,但在CPython中应该可以):

>>> for value in valid_values + invalid_values:
...    if value in valid_values and not any(v is value for v in invalid_values):
...        print ('valid value:', value)
...
valid value: -1
valid value: 0
valid value: 1
valid value: 2
valid value: 3

#1


4  

As others have written, the "in" code does not do what you want it to do. You'll need something else.

正如其他人所写的那样,“in”代码不会按照您的意愿执行。你还需要别的东西。

If you really want a type check (where the check is for exactly the same type) then you can include the type in the list:

如果您真的想要进行类型检查(检查的类型完全相同),那么您可以在列表中包含该类型:

>>> valid_values = [(int, i) for i in [-1, 0, 1, 2, 3]]
>>> invalid_values = [True, False, "foo"]
>>> for value in [v[1] for v in valid_values] + invalid_values:
...   if (type(value), value) in valid_values:
...     print value, "is valid"
...   else:
...     print value, "is invalid"
... 
-1 is valid
0 is valid
1 is valid
2 is valid
3 is valid
True is invalid
False is invalid
foo is invalid
>>> 

Handling subtypes is a bit more difficult, and will depend on what you want to do.

处理子类型有点困难,并且取决于您想要做什么。

#2


15  

The problem is not the missing type checking, but because in Python bool is a subclass of int. Try this:

问题不在于缺少类型检查,而是因为在Python中bool是int的子类。尝试这个:

>>> False == 0
True
>>> isinstance(False, int)
True

#3


6  

According to the documentation, __contains__ is done by iterating over the collection and testing elements by ==. Hence the actual problem is caused by the fact, that False == 0 is True.

根据文档,__contains__是通过==迭代集合和测试元素来完成的。因此,实际问题是由False == 0为True的事实引起的。

#4


3  

Since True == 1 and False == 0 it's hard to differentiate between the two.

由于True == 1和False == 0,因此很难区分这两者。

One possible but ugly approach (which is also not guaranteed to work in all Python implementations but should be OK in CPython):

一种可能但丑陋的方法(也不保证在所有Python实现中都能工作,但在CPython中应该可以):

>>> for value in valid_values + invalid_values:
...    if value in valid_values and not any(v is value for v in invalid_values):
...        print ('valid value:', value)
...
valid value: -1
valid value: 0
valid value: 1
valid value: 2
valid value: 3