我想定义一个与其父级同名的函数,它返回父级可以接收和使用的值。虽然我认为有可能用元类来实现这一点,但我不确定如何做到这一点(假设有可能)以及是否有更好,更清洁的解决方案。
我想要的格式如下所示。 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)
答案 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
明确比隐含更好 应该有一个 - 最好只有一个 - 明显的方式来做到这一点 如果实施难以解释,那是个坏主意。