当前位置: 首页 > 面试题库 >

使my_average(a,b)与定义了f_add和d_div的任何a和b一起使用。以及内置

相德宇
2023-03-14
问题内容

简而言之:我想要的是我编写的大多数数学函数(例如my_average(a, b))都可以使用a和定义bf_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)按照adddiv功能实现了,例如:

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

其中AddableDivisable可以定义为:

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'

内置数字,例如intdefine
__add____truediv__method,因此它们自动得到支持。如类A所示,即使它们没有定义特定的方法,也可以使用类,例如,如果仍然可以在给定的实现中使用它们,则可以通过显式__add__调用.register方法。

如有必要,使用add.registerdiv.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,而将比较引用,并会成功,因