【问题标题】:Return new instance of subclass when using methods inherited from parent class in Python在 Python 中使用从父类继承的方法时返回子类的新实例
【发布时间】:2018-11-03 19:27:41
【问题描述】:

我想为复杂类型创建一个新的__str__ 方法。

import numpy as np  

class Phasor(complex):
    def __str__(self):   
        magnitude = (self.real**2 + self.imag**2)**.5
        angle = np.arctan2(self.imag, self.real)
        return "%s ∠ %s°" % (round(magnitude, 2), round(np.degrees(angle), 2))

a = Phasor(1+1j)
print(a)
print(type(a))
print(a**2)
print(type(a**2))

返回

1.41 ∠ 45.0°
<class '__main__.Phasor'>
2j
<type 'complex'>

在这种情况下,将实例提升到幂返回复杂类型实例而不是子类实例。

我希望继承的方法返回子类的新实例而不是复杂的。

【问题讨论】:

  • 您必须实现所有负责算术的特殊方法,例如__add____mul____div__ 等。
  • @Aran-Fey 是否有可能创建一个包装这样的方法调用的方法?
  • @NChauhan 当然,你可以编写一个类装饰器来自动为你创建这些方法。

标签: python inheritance subclass


【解决方案1】:

为了让算术运算符返回子类的实例,您必须实现相关的 special methods,例如 __add____mul____pow__ 等。

坏消息是有很多这样的方法。好消息是您可以编写自动为您生成这些函数的代码。这是一个类装饰器,正是这样做的:

def add_arithmetic_methods(cls):
    def make_func(func_name):
        def func(self, *args, **kwargs):
            super_method = getattr(super(cls, self), func_name)
            return type(self)(super_method(*args, **kwargs))

        func.__name__ = func_name
        func.__qualname__ = '{}.{}'.format(cls.__qualname__, func_name)
        func.__module__ = cls.__module__

        return func

    for func_name in ['add', 'sub', 'mul', 'matmul', 'truediv', 'floordiv',
                      'mod', 'divmod', 'pow', 'lshift', 'rshift', 'and',
                      'xor', 'or', 'radd', 'rsub', 'rmul', 'rmatmul',
                      'rtruediv', 'rfloordiv', 'rmod', 'rdivmod', 'rpow',
                      'rlshift', 'rrshift', 'rand', 'rxor', 'ror', 'iadd',
                      'isub', 'imul', 'imatmul', 'itruediv', 'ifloordiv',
                      'imod', 'ipow', 'ilshift', 'irshift', 'iand', 'ixor',
                      'ior', 'neg', 'pos', 'abs', 'invert']:
        func_name = '__{}__'.format(func_name)
        func = make_func(func_name)
        setattr(cls, func_name, func)

    return cls

把这个放到你的 Phasor 类上,你就完成了:

@add_arithmetic_methods
class Phasor(complex):
    def __str__(self):   
        magnitude = (self.real**2 + self.imag**2)**.5
        angle = np.arctan2(self.imag, self.real)
        return "%s ∠ %s°" % (round(magnitude, 2), round(np.degrees(angle), 2))

c = Phasor(3+5j)
print(c**2)
# output: 34.0 ∠ 118.07°

【讨论】:

    猜你喜欢
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 2021-12-07
    • 2018-05-06
    相关资源
    最近更新 更多