多态调度:区分 Python 整数与浮点数与字符串
polymorphic dispatch: distinguishing Python integers vs. floating-point numbers vs. strings
假设我有一个函数需要在其他三个函数之一之间进行调度,具体取决于它是 "integer-like" 还是 "floating-point-like" 还是 "string-like" (或其他):
def handleThing(x):
if is_integer_like(x):
return handleInteger(x)
if is_floating_point_like(x):
return handleFloatingPoint(x)
if isinstance(x, basestring):
return handleString(x)
raise ValueError('handleThing only handles numbers and strings')
如何编写 is_integer_like
和 is_floating_point_like
来处理以下类型,而不需要 使用 numpy
库?我正在寻找类似 duck-typing 的东西,但我很困惑,因为似乎没有一种通用的方法可以让我区分它们。
当我做同样的事情来识别某物是否是映射类型时,除了 isinstance(x, collections.Mapping)
我通常会做类似
的事情
def ismapping(x):
return hasattr(x, 'iteritems')
我需要处理:
类整数类型:
int
long
- 所有
numpy
整数类型(np.int
、np.int32
、np.uint32
等)
类浮点类型:
float
complex
- 所有
numpy
浮点类型(np.float32
、np.float64
等)
编辑:我也很好奇如何在 Python 2.5.3 中执行此操作,因为我坚持使用该版本的 Jython。
检查它是否实现了适当的抽象基础class:
def handleThing(x):
import numbers
if isinstance(x, numbers.Integral):
return handleInteger(x)
elif isinstance(x, numbers.Real):
return handleFloatingPoint(x)
elif isinstance(x, basestring):
return handleString(x)
raise ValueError('handleThing only handles numbers and strings')
使用 python 2.7 和 numpy 1.12:
>>> all([isinstance(t(1.0), numbers.Integral) for t in (np.int, np.int32, np.uint32, np.int64, numpy.uint64)])
True
>>> all([isinstance(t(1.0), numbers.Real) for t in (float, np.float32, np.float64, np.float128)])
True
请注意 complex
数字 不是 实数,您应该针对 numbers.Complex
.
进行测试
对于不依赖 类 明确 register
使用 number
ABC 的解决方案(因此它将适用于旧的 NumPy 版本和 Python 2.5),您可以使用 operator.index
来测试某些东西是否应该表现为整数。 (这是 __index__
的包装器,您实现它以使您的对象可用作列表索引。)
def handleThing(x):
try:
operator.index(x)
except TypeError:
pass
else:
return handleInteger(x)
if isinstance(x, basestring):
return handleString(x)
try:
# Would give false positive for strings, but we handled those already.
float(x)
except TypeError:
pass
else:
return handleFloatingPoint(x)
# You might want TypeError here.
raise ValueError('handleThing only handles numbers and strings')
假设我有一个函数需要在其他三个函数之一之间进行调度,具体取决于它是 "integer-like" 还是 "floating-point-like" 还是 "string-like" (或其他):
def handleThing(x):
if is_integer_like(x):
return handleInteger(x)
if is_floating_point_like(x):
return handleFloatingPoint(x)
if isinstance(x, basestring):
return handleString(x)
raise ValueError('handleThing only handles numbers and strings')
如何编写 is_integer_like
和 is_floating_point_like
来处理以下类型,而不需要 使用 numpy
库?我正在寻找类似 duck-typing 的东西,但我很困惑,因为似乎没有一种通用的方法可以让我区分它们。
当我做同样的事情来识别某物是否是映射类型时,除了 isinstance(x, collections.Mapping)
我通常会做类似
def ismapping(x):
return hasattr(x, 'iteritems')
我需要处理:
类整数类型:
int
long
- 所有
numpy
整数类型(np.int
、np.int32
、np.uint32
等)
类浮点类型:
float
complex
- 所有
numpy
浮点类型(np.float32
、np.float64
等)
编辑:我也很好奇如何在 Python 2.5.3 中执行此操作,因为我坚持使用该版本的 Jython。
检查它是否实现了适当的抽象基础class:
def handleThing(x):
import numbers
if isinstance(x, numbers.Integral):
return handleInteger(x)
elif isinstance(x, numbers.Real):
return handleFloatingPoint(x)
elif isinstance(x, basestring):
return handleString(x)
raise ValueError('handleThing only handles numbers and strings')
使用 python 2.7 和 numpy 1.12:
>>> all([isinstance(t(1.0), numbers.Integral) for t in (np.int, np.int32, np.uint32, np.int64, numpy.uint64)])
True
>>> all([isinstance(t(1.0), numbers.Real) for t in (float, np.float32, np.float64, np.float128)])
True
请注意 complex
数字 不是 实数,您应该针对 numbers.Complex
.
对于不依赖 类 明确 register
使用 number
ABC 的解决方案(因此它将适用于旧的 NumPy 版本和 Python 2.5),您可以使用 operator.index
来测试某些东西是否应该表现为整数。 (这是 __index__
的包装器,您实现它以使您的对象可用作列表索引。)
def handleThing(x):
try:
operator.index(x)
except TypeError:
pass
else:
return handleInteger(x)
if isinstance(x, basestring):
return handleString(x)
try:
# Would give false positive for strings, but we handled those already.
float(x)
except TypeError:
pass
else:
return handleFloatingPoint(x)
# You might want TypeError here.
raise ValueError('handleThing only handles numbers and strings')