解决此问题的一种方法是使用元类来定义__instancecheck__ 的自定义实现,然后定义具有元类的具体类,并在具体类中使用isinstance。
这有引入元类机器的缺点,这通常是无关紧要的。
但它的好处是可以干净地封装您希望使用的任何属性,您对您的应用程序的“逻辑整数”的意思。
这里有一些代码来展示这种方法:
class Integral(type):
def __instancecheck__(self, other):
try:
cond1 = int(other) == other
cond2 = (other >= 1.0) or (other < 1.0)
# ... plus whatever other properties you want to check
return all([cond1, cond2,])
except:
return False
class IntLike:
__metaclass__ = Integral
print isinstance(-1, IntLike)
print isinstance('1', IntLike)
print isinstance(27.2, IntLike)
print isinstance(27.0, IntLike)
print isinstance(fractions.Decimal(2), IntLike)
print isinstance(fractions.Fraction(4, 2), IntLike)
打印出来:
True
False
False
True
True
True
请注意,摆脱逻辑整数的数学概念应该适用于您的程序的想法很重要。除非你带上一些校对机器,否则你不会得到那个。例如,您提到了某些可用的函数等属性,特别是sqrt——但这不适用于负整数,除非您实现自定义行为来检查复杂结果。
它将是特定于应用程序的。例如,其他人可能会选择此代码并对其进行修改,以便 '1' 确实注册为 IntLike,也许为了他们的应用程序,它是正确的。
这就是为什么我喜欢这里的元类方法。它使您可以明确地表示您正在施加的每个条件,并将它们存储在一个位置。然后使用常规的isinstance 机制可以让代码阅读器非常清楚您要做什么。
最后,请注意,没有给定的条件永远是完美的。例如,下面的类可用于“欺骗”int(x) == x 技巧:
class MyInt(object):
def __init__(self, value):
self.value = value
def __int__(self):
return int(self.value)
def __add__(self, other):
return self.value + other
#... define all needed int operators
def __eq__(self, other):
if isinstance(other, float):
raise TypeError('How dare you compare me to a float!')
return self.value == other
# ..etc
然后你会得到这样的行为:
In [90]: mi = MyInt(3)
In [91]: mi + 4
Out[91]: 7
In [92]: mi == 3
Out[92]: True
In [93]: int(mi) == mi
Out[93]: True
In [94]: mi == 3.0
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-93-827bea4a197f> in <module>()
----> 1 mi == 3.0
<ipython-input-89-66fec92fab7d> in __eq__(self, other)
13 def __eq__(self, other):
14 if isinstance(other, float):
---> 15 raise TypeError('How dare you compare me to a float!')
16 return self.value == other
17
TypeError: How dare you compare me to a float!
isinstance(mi, IntLike) 是否返回True 将完全取决于您如何为MyInt 实现比较运算符,以及您在Integral 的__instancecheck__ 中所做的任何额外检查。