Can't Dynamically Bind __repr__/__str__ To A Class Created With Type
Solution 1:
Special methods must be added to the class, not to the instance. Any special method is always looked up on the type.
If Python didn't work like that, you couldn't use repr(ClassObj)
as that'd call the ClassObj.__repr__
method which would expect self
as a first argument. So Python calls type(obj).__repr__(obj)
instead.
From the datamodel documentation:
For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
[...]
The rationale behind this behaviour lies with a number of special methods such as hash() and repr() that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself:
>>> >>> 1 .__hash__() == hash(1) True>>> int.__hash__() == hash(int) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor '__hash__' of 'int'object needs an argument
The following works:
typedict = enums.copy()
typedict.update({
'name': reverse,
'__repr__': reprfun,
'__str__': reprfun,
})
instance = type('Enum', (), typedict)
return instance
You do want to be careful with the naming though; instance
is bound to a class object here, not an instance. The name is thus misleading. You may want to use cls
or classobj
or similar instead of instance
.
Demo:
>>>x = Enum(X=1, Y=2)>>>x
<class '__main__.Enum'>
>>>x.__repr__
<unbound method Enum.reprfun>
>>>x()
Enum(Y=2, X=1)
>>>str(x())
'Enum(Y=2, X=1)'
>>>repr(x())
'Enum(Y=2, X=1)'
Post a Comment for "Can't Dynamically Bind __repr__/__str__ To A Class Created With Type"