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 <masklinn@masklinn.net> wrote:
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