Подтвердить что ты не робот

Monkey-patch Класс Python

У меня есть класс, расположенный в отдельном модуле, который я не могу изменить.

from module import MyClass

class ReplaceClass(object)
  ...

MyClass = ReplaceClass

Это не изменяет MyClass нигде, кроме этого файла. Однако, если я добавлю метод, подобный этому

def bar():
   print 123

MyClass.foo = bar

это будет работать, и метод foo будет доступен везде.

Как полностью заменить класс?

4b9b3361

Ответ 1

import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass

Ответ 2

Избегайте from ... import (ужасный;-) способ получить имена, если вам больше всего нужны квалифицированные имена. Когда вы делаете что-то правильно, питоновский путь:

import module

class ReplaceClass(object): ...

module.MyClass = ReplaceClass

Таким образом вы можете обезвредить объект module, который вам нужен и будет работать, когда этот модуль будет использоваться для других. С формой from ... у вас просто нет объекта модуля (один из способов взглянуть на вопиющий дефект большинства людей, использующих from ...), и поэтому вам явно хуже: -);

Единственный способ, которым я рекомендую использовать оператор from, - это импортировать модуль из пакета:

from some.package.here import amodule

так что вы все еще получаете объект модуля и будете использовать квалифицированные имена для всех имен в этом модуле.

Ответ 3

Я всего лишь яйцо.,, Возможно, это очевидно для не-новичков, но мне нужна идиома from some.package.module import module.

Мне пришлось изменить один метод GenerallyHelpfulClass. Это не удалось:

import some.package.module

class SpeciallyHelpfulClass(some.package.module.GenerallyHelpfulClass): 
    def general_method(self):...

some.package.module.GenerallyHelpfulClass = SpeciallyHelpfulClass

Код работал, но не использовал поведение, перегруженное на SpeciallyHelpfulClass.

Это сработало:

from some.package import module

class SpeciallyHelpfulClass(module.GenerallyHelpfulClass): 
    def general_method(self):...

module.GenerallyHelpfulClass = SpeciallyHelpfulClass

Я предполагаю, что from ... import idiom 'получает модуль', как писал Алекс, поскольку он будет подхвачен другими модулями в пакете. Далее, более длинная пунктирная ссылка, по-видимому, приводит модуль в пространство имен с импортом по длинной пунктирной ссылке, но не изменяет модуль, используемый другими пространствами имен. Таким образом, изменения в модуле импорта будут отображаться только в пространстве имен, где они были сделаны. Это как если бы имелись две копии одного и того же модуля, каждая из которых была доступна под несколько разных ссылок.

Ответ 4

import some_module_name

class MyClass(object): 
     ... #copy/paste source class and update/add your logic

some_module_name.MyClass = MyClass

Предпочтительно не менять имя класса при замене, потому что каким-то образом кто-то может ссылаться на них с помощью getattr - что приведет к сбою, как показано ниже

getattr(some_module_name, 'MyClass') → , который сработает, если вы заменили MyClass на ReplaceClass!