Прокси-класс Python

Я пытаюсь создать прокси-класс для другого класса. Я хочу, чтобы этот класс передавался в прокси в его конструкторе, а затем, чтобы прокси динамически создавал все те же методы этого класса на себе.

Это то, что я знаю до сих пор, что не работает:

import inspect
from optparse import OptionParser

class MyClass:

    def func1(self):
        print 'MyClass.func1'


    def func2(self):
        print 'MyClass.func1'


class ProxyClass:

    def __init__(self):
        myClass = MyClass()
        members = inspect.getmembers(MyClass, predicate=inspect.ismethod)
        for member in members:
            funcName = member[0]
            def fn(self):
                print 'ProxyClass.' + funcName
                return myClass[funcName]()
            self.__dict__[funcName] = fn

proxyClass = ProxyClass()
proxyClass.func1()
proxyClass.func2()

Я думаю, что это строка self.__dict__[funcName] = fn, которую нужно изменить, но я не уверен, что делать?

Я новичок в Python, поэтому, если есть совершенно другой способ Pythonic сделать это, я тоже был бы рад услышать об этом.


person user2802557    schedule 05.09.2017    source источник
comment
Вы не сказали, как это не работает. Как вы думаете, почему это назначение dict должно измениться? Тем не менее, это странный подход. Есть ли причина, по которой вы не хотите просто делегировать вызовы, переопределяя __getattr__?   -  person Daniel Roseman    schedule 05.09.2017
comment
Текущая ошибка: когда я вызываю proxyClass.func1(), я говорю, что ей нужно принять 1 аргумент, который предполагает, что функция не была правильно помещена в экземпляр.   -  person user2802557    schedule 05.09.2017
comment
Вся предпосылка использования шаблона прокси заключается в создании класса, который упрощает/ограничивает т.д. взаимодействие с исходным классом, поэтому просто интересно, почему вы пытаетесь просто скопировать члены. И даже если вам нужно свойство 1:1 и доступ к членам в прокси, почему бы просто не передать свой класс конструктору прокси и не присвоить его чему-то вроде self.subject?   -  person Jarek.D    schedule 05.09.2017
comment
Я не уверен, что именно вы имеете в виду, назначая его self.subject и как это поможет?   -  person user2802557    schedule 05.09.2017


Ответы (1)


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

Я включил пример ниже.

class A:
    def foo(self): return 42
    def bar(self, n): return n + 5
    def baz(self, m, n): return m ** n

class Proxy:
    def __init__(self, proxied_object):
        self.__proxied = proxied_object

    def __getattr__(self, attr):
        def wrapped_method(*args, **kwargs):
            print("The method {} is executing.".format(attr))
            result = getattr(self.__proxied, attr)(*args, **kwargs)
            print("The result was {}.".format(result))
            return result    
        return wrapped_method

proxy = Proxy(A())
proxy.foo()
proxy.bar(10)
proxy.baz(2, 10)
person asthasr    schedule 05.09.2017