Sie sind auf Seite 1von 4

from collections import Counter class Spec(object): def __init__(self, args, varargs=None, varkw=None, defaults=None): self.args = args self.

varargs = varargs self.varkw = varkw defaults = defaults or {} self.defaults = {k:v for (k,v) in defaults.items() if k in args} self.kwonlydefaults = {k:v for (k,v) in defaults.items() if k not in args} # Confirm uniqueness: c = Counter(args) c.update([x for x in [varargs, varkw] if x]) if self.kwonlydefaults: c.update(self.kwonlydefaults.keys()) dups = [arg for (arg, count) in c.items() if count != 1] if dups: msg = "duplicate arguments {} in args definition".format(dups) raise Exception(msg) def bind(self, *args, **kwargs): data = dict(zip(self.args, args)) used_pos_names = len(data) if self.varargs: # Extras go in self.varargs data[self.varargs] = tuple(args[used_pos_names:]) elif len(args) > len(data): # No self.varargs -> extra positional arguments are an error msg = "need {} positional arguments but {} were given" raise Exception(msg.format(len(self.args), len(args))) for name in self.args: if name in data: if name in kwargs: # argument was provided positionally AND as a keyword raise Exception("duplicate argument {}".format(name)) continue if name in kwargs: data[name] = kwargs.pop(name) continue if name in self.defaults: data[name] = self.defaults[name] continue

# If we get here, then a positional arg wasn't provided positionally, by # keyword, or in the defaults. raise Exception("missing argument {}".format(name)) if self.kwonlydefaults: for key, default in self.kwonlydefaults.items(): data[key] = kwargs.pop(key, default) if self.varkw: data[self.varkw] = kwargs elif kwargs: raise Exception("unexpected argments {}".format(list(kwargs.keys()))) return data print Spec(['a', 'b', 'c'], None, 'kwargs').bind(1,2,3,4, x=4) def assign_args(pos_names, defaults=None, extra_pos_name=None, extra_kwargs_name=None, posargs=(), kwargs=None): if kwargs is None: kwargs = {} return Spec(pos_names, extra_pos_name, extra_kwargs_name, defaults).bind(*posargs, **kwargs) # if defaults is None: # defaults = {} # pos_defaults = {k:v for (k,v) in defaults.items() if k in pos_names} # kwarg_defaults = {k:v for (k,v) in defaults.items() if k not in pos_names} # # Confirm uniqueness: # c = Counter(pos_names) # if extra_pos_name: # c.update([extra_pos_name]) # if kwarg_defaults: # c.update(kwarg_defaults.keys()) # if extra_kwargs_name: # c.update([extra_kwargs_name]) # dups = [arg for (arg, count) in c.items() if count != 1] # if dups: # msg = "duplicate arguments {} in args definition".format(dups) # raise Exception(msg) # # Assign positional args to positional names # data = dict(zip(pos_names, posargs)) # used_pos_names = len(data) # if extra_pos_name: # # Extras go in extra_pos_name # data[extra_pos_name] = tuple(posargs[used_pos_names:]) # elif len(posargs) > len(data): # # No extra_pos_name -> extra positional arguments are an

error # msg = "need {} positional arguments but {} were given" # raise Exception(msg.format(len(pos_names), len(posargs))) # for name in pos_names: # if name in data: # if name in kwargs: # # argument was provided positionally AND as a keyword # raise Exception("duplicate argument {}".format(name)) # continue # if name in kwargs: # data[name] = kwargs.pop(name) # continue # if name in pos_defaults: # data[name] = defaults[name] # continue # # If we get here, then a positional arg wasn't provided positionally, by # # keyword, or in the defaults. # raise Exception("missing argument {}".format(name)) # if kwarg_defaults: # for key, default in kwarg_defaults.items(): # data[key] = kwargs.pop(key, default) # if extra_kwargs_name: # data[extra_kwargs_name] = kwargs # elif kwargs: # raise Exception("unexpected argments {}".format(list(kwargs.keys()))) # return data

def cmp(a, b): assert a == b, '{} vs {}'.format(a, b) cmp(assign_args(['a'], posargs=[1]), dict(a=1)) cmp(assign_args(['a'], {'a':2}), dict(a=2)) cmp(assign_args(['a', 'b', 'c'], {'c':3}, 'foo', posargs=[1, 2, 5, 4]), dict( a = 1, b = 2, c = 5, foo = (4, ))) #def foo(a, b, c=12, *d, e=15, **kwargs) # pos_names: ['a', 'b', 'c'] # pos_defaults: {'c':12}

# extra_pos_name: 'd' # kwarg_defaults: {'e':15} # extra_kwargs_name: 'kwargs'

Das könnte Ihnen auch gefallen