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