Question

I have devised a proxy class that allows me to replace any type/class with a factory method and still retain most of the functionality of the class object. Here is a sample of how it works:

class ProxyClass:
    def __init__(self, cls):
        self._ProxyClass_cls = cls
    def __getattr__(self, name):
        return getattr(self._ProxyClass_cls, name)

class _strProxy(ProxyClass):
    def __call__(self, s):
        if '\n' in s:
            raise ValueError
        if s not in self._cache:
            self._cache[s] = self._ProxyClass_cls(s)
        return self._cache[s]

str = _strProxy(str)
str._cache = {}


>>> s = str('hello')
>>> s
'hello'
>>> type(s)
<type 'str'>
>>> str('hello\n')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __call__
ValueError

I like this implementation of factory methods because it completely replaces the original class object and still allows things like the following:

>>> map(str.split, [str('foo bar'), str('bar foo')])
[['foo', 'bar'], ['bar', 'foo']]

The only problem I have found is with operations on the class itself such as repr():

>>> repr(str)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__repr__' of 'str' object needs an argument

In this example, repr() is attempting to call str.__repr__() rather than type.__repr__(str). I tried fixing changing str.__class__ but found out that this is impossible in this case:

>>> str.__class__ = type
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to a class

Does anyone know of any way to restore the functionality of repr(str) or maybe another way to accomplish what I am doing?

Was it helpful?

Solution

Make sure that all your classes inherit from object:

class ProxyClass(object):

In Python 3.x, all classes inherit from object anyway, so you don't need to do this. But in Python 2.x, the inheritance stuff doesn't work right unless all the classes involved are "new-style classes" that inherit from object.

repr(str) works fine for me after making the above change.

OTHER TIPS

Why not do

>>> class _strPproxy(ProxyClass):
...     def __call__(self, s):
...         self.s = s
...         if '\n' in s:
...             raise ValueError
...         if s not in self._cache:
...             self._cache[s] = self._ProxyClass_cls(s)
...         return self._cache[s]
...     def __repr__(self): 
...         return repr(self.s)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top