2015-06-12 2 views
1

у меня есть библиотека с одним из родителей и дюжина детей:settattr для родительского класса для использования у детей

# mylib1.py: 
# 
class Foo(object): 
    def __init__(self, a): 
    self.a = a 


class FooChild(Foo): 
    def __init__(self, a, b): 
    super(FooChild, self).__init__(a) 
    self.b = b 

# more children here... 

Теперь я хочу расширить эту библиотеку с простым (но немного spesific, для использования в другой подход). Поэтому я хотел бы изменить родительский класс и использовать его дочерние элементы.

# mylib2.py: 
# 
import mylib1 

def fooMethod(self): 
    print 'a={}, b={}'.format(self.a, self.b) 

setattr(mylib1.Foo, 'fooMethod', fooMethod) 

И теперь я могу использовать его как это:

# way ONE: 
import mylib2 

fc = mylib2.mylib1.FooChild(3, 4) 
fc.fooMethod() 

или как это:

# way TWO: 
# order doesn't matter here: 
import mylib1 
import mylib2 

fc = mylib1.FooChild(3, 4) 

fc.fooMethod() 

Итак, мои вопросы:

  1. Это хорошая вещь ?
  2. Как это должно быть сделано лучше?
+0

Что вы пытаетесь достичь? Зачем вам нужно динамически добавлять метод? – Pynchia

+0

@ Pynchia, я спрашиваю, как это сделать лучше. Поэтому я должен использовать 'mylib1.Foo' и * all * его подклассы, и мне нужно иметь' fooMethod' во всех этих [под] классах. И я не хочу подклассифицировать все. – brownian

ответ

0

В программировании существует общее правило, что вы должны избегать зависимости от глобального состояния. Это означает, что ваши глобальные переменные должны быть по возможности постоянными. Классы (в основном) - глобальные.

Ваш подход называется патчем обезьяны. И если у вас нет по-настоящему веской причины объяснять это, вы должны избегать этого. Это связано с тем, что исправление обезьяны нарушает вышеуказанное правило.

Представьте, что у вас есть два отдельных модуля, и оба они используют этот подход. Один из них устанавливает Foo.fooMethod для некоторого метода. Другое - другому. Затем вы каким-то образом переключаете управление между этими модулями. В результате было бы трудно определить, где именно используется fooMethod. Это означает, что трудно отлаживать проблемы.

Есть люди (например, Брэндон Крейг-Родос), которые считают, что исправление плохо даже в тестах.

Что я хотел бы предложить, это использовать некоторые атрибуты, которые вы задали бы при создании экземпляров вашего класса Foo() (и его дочерних элементов), которые будут контролировать поведение вашего fooMethod. Тогда поведение этого метода будет зависеть от того, как вы создавали экземпляр объекта, а не из глобального состояния.

+0

Должен ли я создавать 'class Moo' с соответствующими' mooMethod' и подклассами каждый 'mylib1. *' 'От' Moo'? Например: 'class FooMoo (Foo, Moo)' then 'class SubFooMoo (SubFoo, Moo)' --- и тот же для всех классов из 'mylib1'? – brownian

+1

Я думаю, что этот вопрос должен идти к «сказанному омару», потому что он предложил микшионный подход. Мое предложение состояло в том, чтобы создать общий fooMethod, который мог бы говорить по-разному в зависимости от некоторого атрибута. Но не зная, какова ваша цель, трудно сказать, каков правильный подход. Тем не менее, вы должны избегать парализаций. – zefciu

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