Python:检查两个变量之间相同类型的最佳方法
Python: Best way to check for same type between two variables
我想检查 python 3.x 中的两个变量是否属于同一类型。 最理想的方法是什么?
举个例子:
class A():
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x):
x += 5
super(B, self).__init__(x)
理想情况下,如果将 A
和 B
类型的两个变量相互比较,我希望 return True
。以下是一些行不通的潜在解决方案:
>>> a = A(5)
>>> b = B(5)
>>>
>>> type(a) is type(b)
False
>>> isinstance(a, type(b))
False
>>> isinstance(b, type(a))
True
最后一个并不理想,因为如中间示例所示,如果要检查的类型是变量类型的子类,False
是 returned。
我尝试过的唯一可以涵盖所有基础的解决方案是:
>>> isinstance(a, type(b)) or isinstance(b, type(a))
True
有没有更好的方法?
此程序遍历所有 __bases__
提供的对象并检查它们之间的公共交集(无 object
):
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x):
x += 5
super(B, self).__init__(x)
class C(B):
def __init__(self, x):
self.x = x
class D:
def __init__(self, x):
self.x = x
class E(C, B):
def __init__(self, x):
self.x = x
a = A(5)
b = B(5)
c = C(5)
d = D(5)
e = E(5)
def check(*objs):
def _all_bases(o):
for b in o.__bases__:
if b is not object:
yield b
yield from _all_bases(b)
s = [(i.__class__, *_all_bases(i.__class__)) for i in objs]
return len(set(*s[:1]).intersection(*s[1:])) > 0
print(check(a, b)) # True
print(check(a, c)) # True
print(check(a, d)) # False
print(check(a, e)) # True
print(check(b, c)) # True
print(check(b, d)) # False
print(check(b, e)) # True
print(check(e, d)) # False
print(check(a, b, c)) # True
print(check(a, b, c, e)) # True
print(check(a, b, c, d)) # False
print(check('string1', 'string2')) # True
鉴于评估 A
后代之间兼容性的既定目标,我认为您可能是 over-complicating 问题所在。说到 rich comparison,至少,Python 已经为你做了这个检查。根据文档:
If the operands are of different types, and right operand’s type is a direct or indirect subclass of the left operand’s type, the reflected method of the right operand has priority, otherwise the left operand’s method has priority. Virtual subclassing is not considered.
这意味着您所要做的就是在 A
中实现运算符。如果任何后代需要添加功能,他们应该这样做。这是一个例子:
class A():
def __init__(self, x):
self.x = x
def __eq__(self, other):
if not isinstance(other, __class__):
return NotImplemented
return self.x == other.x
class B(A):
def __init__(self, x, y):
super(B, self).__init__(x + 5)
self.y = y
def __eq__(self, other):
if isinstance(other, __class__):
return super().__eq__(other) and self.y == other.y
return super().__eq__(other) # Or alternatively, NotImplemented
我想检查 python 3.x 中的两个变量是否属于同一类型。 最理想的方法是什么?
举个例子:
class A():
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x):
x += 5
super(B, self).__init__(x)
理想情况下,如果将 A
和 B
类型的两个变量相互比较,我希望 return True
。以下是一些行不通的潜在解决方案:
>>> a = A(5)
>>> b = B(5)
>>>
>>> type(a) is type(b)
False
>>> isinstance(a, type(b))
False
>>> isinstance(b, type(a))
True
最后一个并不理想,因为如中间示例所示,如果要检查的类型是变量类型的子类,False
是 returned。
我尝试过的唯一可以涵盖所有基础的解决方案是:
>>> isinstance(a, type(b)) or isinstance(b, type(a))
True
有没有更好的方法?
此程序遍历所有 __bases__
提供的对象并检查它们之间的公共交集(无 object
):
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x):
x += 5
super(B, self).__init__(x)
class C(B):
def __init__(self, x):
self.x = x
class D:
def __init__(self, x):
self.x = x
class E(C, B):
def __init__(self, x):
self.x = x
a = A(5)
b = B(5)
c = C(5)
d = D(5)
e = E(5)
def check(*objs):
def _all_bases(o):
for b in o.__bases__:
if b is not object:
yield b
yield from _all_bases(b)
s = [(i.__class__, *_all_bases(i.__class__)) for i in objs]
return len(set(*s[:1]).intersection(*s[1:])) > 0
print(check(a, b)) # True
print(check(a, c)) # True
print(check(a, d)) # False
print(check(a, e)) # True
print(check(b, c)) # True
print(check(b, d)) # False
print(check(b, e)) # True
print(check(e, d)) # False
print(check(a, b, c)) # True
print(check(a, b, c, e)) # True
print(check(a, b, c, d)) # False
print(check('string1', 'string2')) # True
鉴于评估 A
后代之间兼容性的既定目标,我认为您可能是 over-complicating 问题所在。说到 rich comparison,至少,Python 已经为你做了这个检查。根据文档:
If the operands are of different types, and right operand’s type is a direct or indirect subclass of the left operand’s type, the reflected method of the right operand has priority, otherwise the left operand’s method has priority. Virtual subclassing is not considered.
这意味着您所要做的就是在 A
中实现运算符。如果任何后代需要添加功能,他们应该这样做。这是一个例子:
class A():
def __init__(self, x):
self.x = x
def __eq__(self, other):
if not isinstance(other, __class__):
return NotImplemented
return self.x == other.x
class B(A):
def __init__(self, x, y):
super(B, self).__init__(x + 5)
self.y = y
def __eq__(self, other):
if isinstance(other, __class__):
return super().__eq__(other) and self.y == other.y
return super().__eq__(other) # Or alternatively, NotImplemented