2016-10-03 4 views
0

У меня есть модуль python «blackbox», который я хотел бы расширить. Модуль предоставляет класс class Foo без функции __init__ и вспомогательную функцию FooMaker, которая возвращает объекты типа Foo. Обычная стратегия проходящих модулей:Расширение модуля python черного ящика

class ExtendedFoo(blackbox.Foo): 
    def __init__(self, x): 
     super(ExtendedFoo, self).__init__(x) 

не будет работать здесь, так как, как уже упоминалось выше, я должен полагаться на blackbox.FooMaker вместо __init__ функции Foo «s.

Любые идеи о том, как расширить модуль blackbox?

+1

Вызовите FooMaker внутри вашего init? – idjaw

+3

Использовать состав, а не специализацию –

+0

Вы хотите, чтобы ваш '__init__' запускался до или после того, как FooMaker делает все, что он делает? – MisterMiyagi

ответ

0

Оказалось, что Foo класс имел сеттер функцию, таким образом, что в конечном счете работал для меня был

class ExtendedFoo(blackbox.Foo): 
    pass 

def ExtendedFooMaker(*args): 
    _efoo = ExtendedFoo() 
    _efoo.set(FooMaker(*args).get()) 
    return _efoo 
-1

Если модуль не делает серьезного взлома, вы можете просто заменить его элементы. Обратите внимание, что все ссылки и задания работают над именами blackbox., а не локальными именами!

Если вы хотите, чтобы ваш новый класс '__init__ был запущен внутри FooMaker, просто наследуйте и заменяйте Foo.

import blackbox 
class ExtendedFoo(blackbox.Foo): 
    def __init__(self, x): 
     super(ExtendedFoo, self).__init__(x) 

blackbox.Foo = ExtendedFoo 

Таким образом, FooMaker будет экземпляр класса только ExtendedFoo.

В качестве альтернативы вы можете заменить FooMaker своей собственной версией.

import blackbox 
_bbfoomaker = blackbox.FooMaker # keep reference so we can use it later 
def SuperFooMaker(*fooargs, **fookwargs): 
    new_instance = _bbfoomaker(*fooargs, **fookwargs) 
    new_instance.whitebox = True # or whatever 

blackbox.FooMaker = SuperFooMaker 

Ограничение на секунду, что если другой модуль делает что-то вроде from blackbox import FooMaker, ваш модуль должен быть запущен/импортирован ранее. В противном случае другой модуль все еще видит оригинальную фабрику, похожую на то, как у вас все еще есть _bbfoomaker.

+0

Первый вариант не сработал, возможно, потому, что модуль Blackbox сделал что-то странное со своими собственными пространствами имен. Второй вариант просто создаст экземпляр «blackbox.Foo», в то время как мне действительно нужен новый класс с новым именем. –

+0

Является ли этот «черный ящик» доступным для просмотра? – MisterMiyagi

+0

Да, класс 'Foo' -' lxml.etree._ElementTree', а 'FooMaker' -' lxml.etree.parse' –

1

Это должно сделать то же самое, как ваше решение, но немного короче:

from blackbox import Foo, FooMaker 

class ExtendedFoo(Foo): 

    def __init__(self, *args, **kwargs): 
     self.set(FooMaker(*args, **kwargs).get()) 
Смежные вопросы