duck typing assert
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Nov 9 01:30:24 EST 2012
On Thu, 08 Nov 2012 23:44:54 -0500, Terry Reedy wrote:
> On 11/8/2012 6:40 PM, Steven D'Aprano wrote:
[...]
>> IFoo.bar # returns a computed property
>
> Assuming IFoo is a class and bar is a property attribute of the class,
> IFoo.bar is the property object itself, not the computed property of an
> instance.
Given the context we were discussing, namely duck-typing, the examples I
gave should have been understood as indications, not literal code
snippets. Yes, it is true that "IFoo.bar" returns a property object, and
"Foo.bar" returns an unbound method (a function in Python 3). But they
are meant as illustrations, not working code samples. Much the same way
that we will often talk about "list.append" when what we actually mean is
the bound append method on some specific, context-dependent list instance.
I am sorry that I did not make that clear and that my terminology was
sloppy.
But in context, duck-typing classes normally is intended to substitute an
instance of one class for an instance of another class. In that case, if
IFoo.bar is a property, and Foo.bar is a method, then you cannot
substitute an IFoo instance for a Foo instance, or vice versa:
ifoo = IFoo()
ifoo.bar # returns a computed attribute
foo = Foo()
foo.bar() # calls the method
In the general case, you cannot use ifoo.bar() where foo.bar() is
expected, nor can you use foo.bar where ifoo.bar is expected. Just in
case it isn't clear what I mean:
Suppose the expected interface is that instance.bar is a method that
takes no arguments. foo.bar() matches that interface, because bar is a
method. But ifoo.bar is a property. Suppose it computes an int result.
Then ifoo.bar() will try to call an int, and raise TypeError. So ifoo
cannot be used in place of foo, and types IFoo and Foo are not duck-type
compatible. Likewise if the expected interface is for a property or
attribute, such as ifoo.bar would give. Then foo.bar returns an unbound
method. Instead of getting an error there and then, you might not get an
error until much later, say:
integers = [1, 3, ifoo.bar, foo.bar, 42]
# much later
y = sum(integers) # raises TypeError because foo.bar is a method
So, duck-typing classes IFoo (with bar a property) and Foo (with bar a
method) will not in general work, and looks(IFoo).like(Foo) should return
False.
--
Steven
More information about the Python-list
mailing list