Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

reflection - Completely wrap an object in Python

I am wanting to completely wrap an object so that all attribute and method requests get forwarded to the object it's wrapping, but also overriding any methods or variables that I want, as well as providing some of my own methods. This wrapper class should appear 100% as the existing class (isinstance must act as if it is actually the class), however subclassing in itself is not going to cut it, as I want to wrap an existing object. Is there some solution in Python to do this? I was thinking something along the lines of:

class ObjectWrapper(BaseClass):
    def __init__(self, baseObject):
        self.baseObject = baseObject

    def overriddenMethod(self):
        ...

    def myOwnMethod1(self):
        ...

    ...

    def __getattr__(self, attr):
        if attr in ['overriddenMethod', 'myOwnMethod1', 'myOwnMethod2', ...]
            # return the requested method
        else:
            return getattr(self.baseObject, attr)

But I'm not that familiar with overriding __getattr__, __setattr__ and __hasattr__, so I'm not sure how to get that right.

question from:https://stackoverflow.com/questions/1443129/completely-wrap-an-object-in-python

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The simplest way in most cases is probably:

class ObjectWrapper(BaseClass):
    def __init__(self, baseObject):
        self.__class__ = type(baseObject.__class__.__name__,
                              (self.__class__, baseObject.__class__),
                              {})
        self.__dict__ = baseObject.__dict__

    def overriddenMethod(self):
        ...

Working in this way, i.e. by reassigning self's __class__ and __dict__ in this fashion, you need only provide your overrides -- Python's normal attribute getting and setting mechanisms will do the rest... mostly.

You'll be in trouble only if baseObject.__class__ defines __slots__, in which case the multiple inheritance approach doesn't work and you do need the cumbersome __getattr__ (as others said, at least you don't need to worry that it will be called with attributes you're overriding, as it won't!-), __setattr__ (a greater pain, as it DOES get called for every attribute), etc; and making isinstance and special methods work takes painstaking and cumbersome detailed work.

Essentially, __slots__ means that a class is a special, each instance a lightweight "value object" NOT to be subject to further sophisticated manipulation, wrapping, etc, because the need to save a few bytes per instance of that class overrides all the normal concerns about flexibility and so on; it's therefore not surprising that dealing with such extreme, rare classes in the same smooth and flexible way as you can deal with 99%+ of Python objects is truly a pain. So DO you need to deal with __slots__ (to the point of writing, testing, debugging and maintaining hundreds of lines of code just for those corner cases), or will the 99% solution in half a dozen lines suffice?-)

It should also be noted that this may lead to memory leaks, as creating a subclass adds the subclass to the base class' list of subclasses, and isn't removed when all instances of the subclass are GC'd.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...