duck typing assert‏

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Nov 9 07:30:24 CET 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