Behaviour-based interface/protocol implementation?
Alan Franzoni
mailing at franzoni.eu
Wed Jan 26 04:00:57 EST 2011
On Tue, Jan 25, 2011 at 6:48 PM, Terry Reedy <tjreedy at udel.edu> wrote:
> This is correct!
>
> print(len(mo))
> TypeError: object of type 'MyObj' has no len()
That's interesting. I must admit I was not thinking about special
methods in my original post, I used that example just because of Chris
response.
by the way, define 'correct' - if that means 'that's how this works in
python', it's a tautology, not correctness :-) Instead I think this
highlights an asymmetry in how python handles special methods, and
makes it less ducktyped than I wanted. Consider this:
class MyObject(object):
@staticmethod
def __len__():
return 1
mo = MyObject()
print mo.__len__
print len(mo)
class LenObj(object):
def __len__(self):
return 3
lo = LenObj()
print lo.__len__
print len(lo)
import types
class OtherObj(object):
pass
oo = OtherObj()
def __len__(self):
return 2
oo.__len__ = types.MethodType(__len__, oo, OtherObj)
print oo.__len__
print len(oo)
Output:
<function __len__ at 0x1004bb938>
1
<bound method LenObj.__len__ of <__main__.LenObj object at 0x1004ce510>>
3
<bound method OtherObj.__len__ of <__main__.OtherObj object at 0x1004ce590>>
Traceback (most recent call last):
File "pymethods.py", line 34, in <module>
print len(oo)
TypeError: object of type 'OtherObj' has no len()
The problem is not "function attributes" - the problem is that the
__len__() method must be set on the class, not on the instance. I
think this is not completely clear here:
http://docs.python.org/reference/datamodel.html
By the way, my original post didn't take into account special methods
- let's suppose they don't exist for a moment.
I'd just like to check *at runtime* whether an object *any object!*
respects a certain signature.
*I don't want to care about the class of that object because I want
true duck typing*. I mean, I should be able to pass *anything* that
responds to a certain contract:
@DuckType
class MyInterface(object):
def someMethod(self):
pass
def otherMethod(self, a, b):
pass
class SomeObj(object):
@classmethod
def someMethod(cls):
pass
@classmethod
def otherMethod(cls, a, b):
pass
class OtherObj(object):
def someMethod(self):
pass
def otherMethod(cls, a, b):
pass
class ThirdObj(object):
pass
oo = OtherObj()
to = ThirdObj()
to.someMethod = lambda: None
to.otherMethod = lambda a,b: None
MyInterface.maybe_implemented_by(oo) # -> True
MyInterface.maybe_implemented_by(to) # -> True
MyInterface.maybe_implemented_by(SomeObj) # -> True
That's just what I'd like and I suppose can't be currently done with
current ABC, PyProtocols or zope.interface implementations, right?
--
Alan Franzoni
--
contact me at public@[mysurname].eu
More information about the Python-list
mailing list