I was trying to think how a decorator @strict_duck_typing could be
implemented to solve the issue Bruce Leban described. The more I think about
it, the harder I think it is to implement.
I wanted to do something along the lines of:
def parameters_from_signature(function, args, kwargs):
"Translate a generic function call to the function's parameters by name"
argnames, varargs, keywords, defaults = inspect.getargspec(function)
args_and_kwargs = kwargs.copy()
names_and_args = zip(argnames, args)
args_and_kwargs.update(names_and_args)
if varargs is not None:
args_and_kwargs[varargs] = args[len(argnames):]
return args_and_kwargs
def strict_duck_typing(function):
attr_dict = attributes_used_by_function(function)
def verify_and_run(*args, **kwargs):
called_with = parameters_from_signature(function, args, kwargs)
for parameter, attributes_needed in attr_dict.items():
for attr in attributes_needed:
if not hasattr(called_with[parameter], attr):
raise TypeError("Parameter '%s' given doesn't have '%s'
attribute/method." % (parameter, attr))
function(*args, **kwargs)
Of course the big enchilada is the function 'attributes_used_by_function'
which I left out because it has to do some insane things. I was thinking of
using ast.parse(inspect.getsource(function)) and then:
1. stepping into each function call which involves the function
parameters, perhaps repeating the ast.parse/inspect.getsource combo.
2. collecting all the methods and attributes accessed.
3. getattr/setattr/hasattr need to be simulated or handled
4. return a dictionary of { parameter_name: attributes_needed_set }
And even after this crazy piece of work there are some limitations ie:
1. C functions wouldn't be inspected, which is a tragedy, ie len(),
iter(), etc have to be especially treated...
2. dynamically generated attributes and attribute names will always break
this decorator.
3. performance issues
4. probably more things i didn't think of...
So I like the idea of strict duck typing, but it's gonna take more than one
mailing list reply for me to write a POC :)
On Sun, Sep 20, 2009 at 12:56 PM, Masklinn
On 20 Sep 2009, at 06:21 , Bruce Leban wrote: I don't quite understand what you are trying to solve. Here's a related
problem: One of the issues with duck typing is that something might look sort of like a duck but isn't really and it would be nice to make it easy to avoid using an object in a "half-baked" manner:
def playWithDuck(d): d.walk() d.quack()
if someone calls playWithDuck(dog) then the dog's going to get walked before trying to make the dog quack fails.
Note that with a structural type system (that of OCaml's objects for instance) this will work, the `playWithDuck` function will be inferred to take any subtype of < walk : unit; duck : unit > (or something like that) (basically, any object with a `walk` and a `quack` method (both returning nothing) will work).
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas