2016-05-22 5 views
1

Я хотел бы определить функцию с тем же именем, что и ее родительский элемент, который возвращает значение, которое родитель может получить и использовать. Хотя я думаю, что можно достичь этого с помощью метакласса, я не уверен, как это можно сделать (при условии, что это возможно), и есть ли лучшее, более чистое решение.Как вернуть значение в суперкласс без переопределения родительской функции?

Мой желаемый формат показан ниже. Класс 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

Печать '2 1 0' на Python 2.7 и 3.4 – csl

+1

Если определить метод в подклассе с тем же именем, то по определению переопределить родительский метод. Я почти уверен, что вы хотите сделать, это невозможно и будет плохой идеей.Я предлагаю, чтобы у вас есть 'f' в родительском вызове некоторый абстрактный метод' g', за который ребенок отвечает за переопределение. –

+0

Обратите внимание, что это будет просто 'return super(). F (a)'. – jonrsharpe

ответ

3

Существует ключевая проблема с этим утверждением:

Я хотел бы определить функцию с тем же именем, как своего родителя, который возвращает значение, которое родитель может получить

Могу ли я спросить, почему это необходимо?

f в классе «Дети» совершенно отличается от 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

Явное лучше, чем неявное.
Должен быть один - и желательно только один - простой способ сделать это.
Если реализация трудно объяснить, это плохая идея.

+1

как примечание стороны. Я хотел бы указать, что «может реализовать специальный метод, который вызывается под <...> curcumstances» - довольно распространенная констатация, просто подумайте о подклассе 'dict' overriding' __missing__' –

 Смежные вопросы

  • Нет связанных вопросов^_^