如何在不覆盖父函数的情况下 return 超类的值?
How can I return a value to a superclass without overriding the parent function?
我想定义一个与其父函数同名的函数,returns 一个父函数可以接收和使用的值。虽然我认为可以通过元class实现这一点,但我不确定人们会怎么做(假设这是可能的)以及是否有更好、更清洁的解决方案。
我想要的格式如下所示。 Child
class 将由我以外的开发人员定义,因此我希望限制尽可能少。 (例如,理想情况下,我不希望使用 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)
此语句存在一个关键问题:
I would like to define a function with the same name as its parent which returns a value that the parent can receive
请问,为什么需要这个?
Child class 中的 f
与 Parent class 中的 f
完全不同,所以它们的命名相同即使你让它工作也非常令人困惑。
假设我用你的 Parent
:
写了 child class
class Child(Parent):
def f(self):
return 2
我希望 Child().f()
到 return 2,但是如果你在添加 arg ** 3
的幕后添加隐藏逻辑,那么我将得到 8,并且完全困惑和诅咒您的图书馆添加了非常 non-intuitive 规则。
相反,为什么不使用一个函数并在 subclasses:
中定义额外的逻辑辅助函数
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)
当然,是的,从技术上讲,您 可以 使用元 class 自动执行此操作。但同样,对于使用您的 Parent
class
的任何人,这将 完全混淆
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
Explicit is better than implicit.
There should be one-- and preferably only one --obvious way to do it.
If the implementation is hard to explain, it's a bad idea.
我想定义一个与其父函数同名的函数,returns 一个父函数可以接收和使用的值。虽然我认为可以通过元class实现这一点,但我不确定人们会怎么做(假设这是可能的)以及是否有更好、更清洁的解决方案。
我想要的格式如下所示。 Child
class 将由我以外的开发人员定义,因此我希望限制尽可能少。 (例如,理想情况下,我不希望使用 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)
此语句存在一个关键问题:
I would like to define a function with the same name as its parent which returns a value that the parent can receive
请问,为什么需要这个?
Child class 中的 f
与 Parent class 中的 f
完全不同,所以它们的命名相同即使你让它工作也非常令人困惑。
假设我用你的 Parent
:
class Child(Parent):
def f(self):
return 2
我希望 Child().f()
到 return 2,但是如果你在添加 arg ** 3
的幕后添加隐藏逻辑,那么我将得到 8,并且完全困惑和诅咒您的图书馆添加了非常 non-intuitive 规则。
相反,为什么不使用一个函数并在 subclasses:
中定义额外的逻辑辅助函数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)
当然,是的,从技术上讲,您 可以 使用元 class 自动执行此操作。但同样,对于使用您的 Parent
class
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
Explicit is better than implicit.
There should be one-- and preferably only one --obvious way to do it.
If the implementation is hard to explain, it's a bad idea.