How to fake/proxy a class in Python

前端 未结 3 628
花落未央
花落未央 2020-11-29 07:17

I wrote some wrapper which has another object as an attribute. This wrapper proxies (forwards) all attribute requests with __getattr__ and __setattr__

相关标签:
3条回答
  • 2020-11-29 07:46

    in case someone else is looking for a more complete proxy implementation

    Although there are several python proxy solutions similar to those OP is looking for, I could not find a solution that will also proxy classes and arbitrary class objects, as well as automatically proxy functions return values and arguments. Which is what I needed.

    I've got some code written for that purpose as part of a full proxying/logging python execution and I may make it into a separate library in the future. If anyone's interested you can find the core of the code in a pull request. Drop me a line if you'd like this as a standalone library.

    My code will automatically return wrapper/proxy objects for any proxied object's attributes, functions and classes. The purpose is to log and replay some of the code, so i've got the equivalent "replay" code and some logic to store all proxied objects to a json file.

    0 讨论(0)
  • 2020-11-29 07:56

    Generally, you can use the wrapt library (pypi), which does the heavy lifting for you:

    The wrapt module focuses very much on correctness. It therefore goes way beyond existing mechanisms such as functools.wraps() to ensure that decorators preserve introspectability, signatures, type checking abilities etc. [...]

    To ensure that the overhead is as minimal as possible, a C extension module is used for performance critical components

    It supports creating custom wrapper classes. In order to add your own attributes, you need to declare them in such a way that wrapt doesn't try to pass them on to the wrapped instance. You can:

    • Prefix the attribute with _self_ and add properties for access
    • Declare the attribute at the class level, in addition to in __init__
    • Use slots, if appropriate for your class (not mentioned in the docs), like this:

      class ExtendedMesh(ObjectProxy):
          __slots__ = ('foo')
      
          def __init__(self, subject):
              super().__init__(subject)
              self.foo = "bar"
      

    It also supports function wrappers, which might suit your purpose.

    0 讨论(0)
  • 2020-11-29 08:00

    This problem is reasonably well addressed by this recipe:

    Object Proxying (Python recipe)

    The general idea you have to follow is that most methods on classes are accessed through some combination of __getattr__ and __getattribute__ either on the class itself, or on its metaclass, but this does not apply to python special methods, the ones that begin and end with double underscore, for those to be found, they must be actual methods on the actual class, no attribute proxying is possible.

    Which of those methods you must provide will obviously depend on which of those methods the proxied class itself offers. The special methods you need to provide for isinstance() are the __instancecheck__ and __subclasscheck__ methods. for repr() to work, you must also define an appropriate __repr__() on the proxy class itself.

    0 讨论(0)
提交回复
热议问题