patternpythonMinor
Creating Proxy classes for immutable objects
Viewed 0 times
proxyobjectscreatingimmutableforclasses
Problem
As a bit of a learning project, I decided to take the concept of proxying objects a bit further and extend it to creating proxy classes which create proxy'd objects. I originally found the idea of proxying objects in python on Activestate. I'm currently using a very odd pattern (creating a class with just staticmethods and abusing
Is this a good idea, or should I return to using a function that takes a
The entire purpose of this
Shameless self-plugging: This is actually a core piece of code at pyranoid, which I work on, since it seems interesting.
```
import functools
import collections
class Proxy(type):
__special_names__ = {
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__', '__getslice__',
'__gt__', '__hash__', '__hex__', '__int__', '__iter__', '__le__', '__len__',
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__',
'__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__',
'__rdivmod__', '__reduce__', '__reduce_ex__', '__reversed__',
__new__ to return my classes, instead of using a function (since that would reinstantiate __special_names__, __imethods__, and __other_magic__ every time it ran.Is this a good idea, or should I return to using a function that takes a
type and returns a Proxy subclass? On a second note, is there any way to make isinstance and issubclass happy without actually subclassing the given type? I originally wanted to use __call__ for the class which would make it at least somewhat readable, since when you call functions, you call their __call__ attribute (afaik), but python seems to think I have to use the __new__ attribute instead to use a class as a function.The entire purpose of this
class Proxy hack is to create Proxy classes for immutable objects - this way if you do a = b = 10 and a += 5, a == b == 15 without having to update b.Shameless self-plugging: This is actually a core piece of code at pyranoid, which I work on, since it seems interesting.
```
import functools
import collections
class Proxy(type):
__special_names__ = {
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__', '__getslice__',
'__gt__', '__hash__', '__hex__', '__int__', '__iter__', '__le__', '__len__',
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__',
'__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__',
'__rdivmod__', '__reduce__', '__reduce_ex__', '__reversed__',
Solution
Some quick thoughts:
-
I can't tell from reading the code what the purpose is. What is this for? What are the use cases? How am I supposed to use it?
-
There's no docstring for the
-
What is the role of the
-
Names starting and ending with two underscores are reserved for future use by the language and the standard library:
So I'd recommend avoiding names of this form in your own code.
-
What's the difference between
-
The docstring for
-
Why does
-
Instead of
you could write
-
-
What order are the names in
-
The method returned by
But really this is just fumbling in the dark because I don't understand what problem you are trying to solve. I see that you edited the post to add an explanation (you want to be able to proxy immutable objects), but this still leaves me in the dark. Why do you want to proxy immutable objects?
-
I can't tell from reading the code what the purpose is. What is this for? What are the use cases? How am I supposed to use it?
-
There's no docstring for the
Proxy class or for the usable_base_type method.-
What is the role of the
Proxy class? You never seem to create any instances of it. (The __new__ method returns an instance of the newType that it has just created.) Python is not Java: not everything needs to be a class.-
Names starting and ending with two underscores are reserved for future use by the language and the standard library:
____ System-defined names. These names are defined by the interpreter and its implementation (including the standard library). Current system names are discussed in the Special method names section and elsewhere. More will likely be defined in future versions of Python. Any use of ____ names, in any context, that does not follow explicitly documented use, is subject to breakage without warning.So I'd recommend avoiding names of this form in your own code.
-
What's the difference between
__special_names__ and __other_magic__? Why is __slots__ not in either of these sets?-
The docstring for
__method_wrapper__ says "cast the result", but Python doesn't have casting. What does this method really do?-
Why does
__imethod_wrapper____ end in four underscores?-
Instead of
__special_names__.union(__imethods__).union(__other_magic__)you could write
__special_names__ | __imethods__ | __other_magic__-
__special_names__ is almost in alphabetical order (which is a useful way to order a list like this, because it helps you spot missing and duplicate items), but __next__ is out of order. Why is that?-
What order are the names in
__other_magic__ in? Why not alphabetical order like the two other lists? And why is this list formatted with one name per line while the others are paragraph-wrapped?-
The method returned by
__method_wrapper__ calls Proxy() each time it is called, which will create another newType class. Is this really what you want to happen? Won't this lead to a proliferation of identical classes?But really this is just fumbling in the dark because I don't understand what problem you are trying to solve. I see that you edited the post to add an explanation (you want to be able to proxy immutable objects), but this still leaves me in the dark. Why do you want to proxy immutable objects?
Code Snippets
__special_names__.union(__imethods__).union(__other_magic__)__special_names__ | __imethods__ | __other_magic__Context
StackExchange Code Review Q#27468, answer score: 2
Revisions (0)
No revisions yet.