如何在不覆盖父函数的情况下将值返回给超类?

时间:2016-05-22 21:41:01

标签: python python-3.x inheritance python-3.5 metaclass

我想定义一个与其父级同名的函数,它返回父级可以接收和使用的值。虽然我认为有可能用元类来实现这一点,但我不确定如何做到这一点(假设有可能)以及是否有更好,更清洁的解决方案。

我想要的格式如下所示。 Child类将由我自己以外的开发人员定义,因此我希望尽可能少的限制。 (例如,我最好不要使用super(Child).f(a)来替换return a。)我也不确定如何在我的模型中使用关键字参数,这是更可取的。

class Parent:
    def f(self, arg):
        print("Received {}.".format(arg))
        return arg ** 3

class Child(Parent):
    def f(self, c, b, a):
        print(a, b, c)
        return a

# Prints "2 1 0" and "Received 2.". Sets value to 8.
value = Child().f(0, 1, 2)

1 个答案:

答案 0 :(得分:3)

此声明存在一个关键问题:

  

我想定义一个与同名的函数,它的父级返回父级可以接收的值

请问,为什么这有必要?

Child类中的f与Parent类中的f完全不同,因此将它们命名为相同的内容即使您确实使其工作也非常混乱。

假设我使用您的Parent编写了子课程:

class Child(Parent):
    def f(self):
        return 2

我希望Child().f()返回2,但是如果你在添加arg ** 3的幕后添加隐藏的逻辑,那么我将改为8并完全混淆并诅咒你的库以添加非常 - 直观的规则。

相反,为什么不使用一个函数并在子类中定义额外的逻辑辅助函数:

class Parent:
    def f(self, *v_args):
        arg = self.helper_f(*v_args)
        print("Received {}.".format(arg))
        return arg ** 3

    def helper_f(self,*args):
        "really should be an abstract method, must be implemented in a subclass"
        raise NotImplementedError("Must override in a subclass!") 

class Child(Parent):
    def helper_f(self, c, b, a):
        print(a, b, c)
        return a

# Prints "Received 2.". Sets value to 8.
value = Child().f(0, 1, 2)

当然,是的,您在技术上可以使用元类自动执行此操作。但同样,对于使用Parent课程的任何人来说,完全令人困惑

class Child_Method_Redirector(type):
    def __new__(meta, name, bases, cls_dict):
        if bases is not ():
            if "f" in cls_dict:
                cls_dict["_auto_renamed_helper_f"] = cls_dict["f"]
                del cls_dict["f"]
        return type.__new__(meta,name,bases,cls_dict)


class Parent(metaclass=Child_Method_Redirector):
    def f(self, *v_args):
        arg = self._auto_renamed_helper_f(*v_args)
        print("Received {}.".format(arg))
        return arg ** 3

class Child(Parent):
    def f(self):
        return 2

# now it does Print "Received 2." and Sets value to 8.
value = Child().f()

但是请不要这样做,它违反了the zen

  

明确比隐含更好   应该有一个 - 最好只有一个 - 明显的方式来做到这一点   如果实施难以解释,那是个坏主意。