简而言之:我想要的是我编写的大多数数学函数(例如my_average(a, b)
)都可以使用a
和定义b
了f_add
和的任何数学函数f_div
。没有重载+和/且没有破坏my_average(built_in_type, built_in_type)
python 3。
具体来说,我正在使用我创建的颜料对象的实例。这些对象的重载运算符并不简单。例如:
两个实例之间的差异(出于距离目的)可能是a.lab - b.lab
。(Lab色彩空间在感知距离和欧几里得距离之间具有良好的相关性。)
两个实例的总和(出于混合目的)可能是a.srgb + b.srgb
。(srgb颜色空间是线性的,适用于数学操作。)
对于其他目的,总和与差额可能意味着其他。
因此,在现有模块中键入鸭子将不起作用。
pigment_instance.distance(self, b)
pigment_instance.mix(self, b)
只要我不介意在每次有这样的新对象时都重写每个函数(作为一种方法)就可以了。我想做的就是再次重写我的函数,以使其更强大。
我已经尝试了几件事:
class Averager():
__init__(self, f_mix, f_distance):
self.f_mix = f_mix
...
def __call__(self, a, b):
# return the average calculated with self.f_something functions
可以,但是最后我将整个模块都埋在了一个类中。
def mix(a, b, f_mix=lambda x, y: x + y, f_distance=lambda x, y: x - y)
# or, same as above with decorators.
同样,可以正常工作,但是每次我要计算2 + 2时,我必须保留长的默认参数或提供一个f_add。
def pigment_functions(f_mix, f_distance):
return [
functools.partial(mix, f_mix=somefunc, f_distance=somefunc),
functools.partial(distance, f_mix=somefunc, f_distance=somefunc)]
mix, difference = pigment_functions(f_mix, f_distance)
与第二个相似的选择。
def mix(a, b):
try: a + b
except TypeError: # look for some global f_mix
也可以,但是我在每个函数中都有全局变量和混乱
其中哪一个(或其他)有意义?
如果您已经my_average(a, b)
按照add
和div
功能实现了,例如:
def my_average(a, b):
return div(add(a, b), 2)
然后为不同的类型提供不同的实现,可以使用functools.singledispatch
:
import functools
@singledispatch
def div(x, y:int): # default implementation
raise NotImplementedError('for type: {}'.format(type(x)))
@div.register(Divisible) # anything with __truediv__ method
def _(x, y):
return x / y
@singledispatch
def add(a, b):
raise NotImplementedError('for type: {}'.format(type(a)))
@add.register(Addable) # anything with __add__ method
def _(a, b):
return a + b
其中Addable
,Divisable
可以定义为:
from abc import ABCMeta, abstractmethod
class Divisible(metaclass=ABCMeta):
"""Anything with __truediv__ method."""
__slots__ = ()
__hash__ = None # disable default hashing
@abstractmethod
def __truediv__(self, other):
"""Return self / other."""
@classmethod
def __subclasshook__(cls, C):
if cls is Divisible:
if any("__truediv__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
class Addable(metaclass=ABCMeta):
"""Anything with __add__ method."""
__slots__ = ()
__hash__ = None # disable default hashing
@abstractmethod
def __add__(self, other):
"""Return self + other."""
@classmethod
def __subclasshook__(cls, C):
if cls is Addable:
if any("__add__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
>>> isinstance(1, Addable) # has __add__ method
True
>>> isinstance(1, Divisible) # has __truediv__ method
True
>>> my_average(1, 2)
1.5
>>> class A:
... def __radd__(self, other):
... return D(other + 1)
...
>>> isinstance(A(), Addable)
False
>>> _ = Addable.register(A) # register explicitly
>>> isinstance(A(), Addable)
True
>>> class D:
... def __init__(self, number):
... self.number = number
... def __truediv__(self, other):
... return self.number / other
...
>>> isinstance(D(1), Divisible) # via issubclass hook
True
>>> my_average(1, A())
1.0
>>> my_average(A(), 1) # no A.__div__
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'A' and 'int'
内置数字,例如int
define
__add__
,__truediv__
method,因此它们自动得到支持。如类A
所示,即使它们没有定义特定的方法,也可以使用类,例如,如果仍然可以在给定的实现中使用它们,则可以通过显式__add__
调用.register
方法。
如有必要,使用add.register
和div.register
定义其他类型的实现,例如:
@div.register(str)
def _(x, y):
return x % y
之后:
>>> my_average("%s", "b") # -> `("%s" + "b") % 2`
'2b'
问题内容: 正如我在标题中提到的 a + = b和a = + b以及a 和 a有什么区别?我有点困惑 问题答案: 相当于 相当于 且两者都增加1。不同之处在于,返回的是增量之前的值,而返回的是增量之后的值。 那是:
问题内容: 我尝试了一些代码,使用XOR在Java中交换两个整数而不使用第三个变量。 这是我尝试的两个交换函数: 这段代码产生的输出是这样的: 我很好奇,为什么这样说: 与这个不同吗? 问题答案: 问题是评估的顺序: 参见JLS第15.26.2节 首先,对左操作数求值以产生一个变量。 如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,并且不会发生赋值。 否则,将保存
问题内容: 今天,我发现了python语言一个有趣的“功能”,这让我感到非常悲伤。 那个怎么样?我以为两者是等同的!更糟糕的是,这是我调试时遇到的麻烦的代码 WTF!我的代码中包含列表和字典,并且想知道我到底怎么把dict的键附加到列表上而又没有调用.keys()。事实证明,这就是方法。 我认为这两个陈述是等效的。即使忽略这一点,我也可以理解将字符串追加到列表的方式(因为字符串只是字符数组),但是
问题内容: 这是我的第一个问题,我开始学习Python。之间有什么区别: 和 在下面的示例中编写时,它显示不同的结果。 和 问题答案: 在中,在将右侧的表达式赋给左侧之前对其求值。因此,它等效于: 在第二个示例中,运行时已更改的值。因此,结果是不同的。
我尝试了一些代码在Java中交换两个整数,而不使用第三个变量,即使用XOR。 以下是我尝试的两个交换函数: 该代码产生的输出如下: 我很想知道,为什么会有这样的说法: 和这个不一样?
问题内容: 我目前正在尝试了解在自定义类上使用和之间的区别。有许多网站说使用’+’运算符会导致使用特殊方法-到目前为止还不错。 但是,当我运行以下示例时,我得到两个不同的结果。 结果: 现在,据我了解,执行Python时检查/执行int方法-发现没有实现添加int和C对象的实现-返回NotImplemented- 这使Python知道检查对象C并执行其中的代码。 为什么执行代码会导致结果,但是其他
本文向大家介绍if(a-b <0)和if(a 相关面试题,主要包含被问及if(a-b <0)和if(a 时的应答技巧和注意事项,需要的朋友参考一下 并且可能意味着两个不同的东西。考虑以下代码: 运行时,将仅打印。发生的事情显然是错误的,但是溢出并变为,这是负面的。 话虽如此,请考虑一下数组的长度确实接近。中的代码如下所示: 确实接近,所以(是)可能溢出并变成(即负数)。然后,将 下溢 相减回正数。
问题内容: 这是我必须弄清楚怎么可能的代码。我有一个线索,但我不知道该怎么做。我认为这与负数和正数有关,也可能与变量修饰符有关。我是一个初学者,我到处都看过解决方案,但是找不到可用的东西。 问题是:您需要声明和初始化两个变量。如果条件必须为真。 代码: 感谢您抽出宝贵的时间。 问题答案: 这对于基本类型是不可能的。您可以使用带框的整数来实现: 在和比较将使用未装箱的值1,而将比较引用,并会成功,因