> This is neat. :) Could that maybe be extended to only assign selected 
> args to the instance and let others pass unchanged. So that, for instance:
> 
> @autoassign("foo", "bar")
> def __init__(self, foo, bar, baz):
>      super(baz)

I've seen some folks import inspect/functools, but from my
testing, the __init__ method in question has a .func_code object
that already has the varnames in it.  However, as you suggest, a
version below allows for named defaults, and letting others go
un-defaulted.  I'm not sure about naming conventions for
class-style decorators--start with a cap, like a class should
("AutoAssign") or because it behaves like a function, use
"auto_assign", or any of a number of other variants.  Anyways...

  class auto_assign(object):
    def __init__(self, *varnames):
      self.args = set(varnames)
    def __call__(self, fn):
      autoassign = self
      def wrapper(self, *args, **kwargs):
        for argname, argvalue in zip(
            fn.func_code.co_varnames[1:],
            args):
          if argname in autoassign.args:
            setattr(self, argname, argvalue)
        for argname in autoassign.args:
          if argname in kwargs:
            setattr(self, argname, kwargs[argname])
        fn(self, *args, **kwargs)
      return wrapper

  class Foo(object):
    @auto_assign('foo', 'baz', 'fred')
    def __init__(self, foo, bar, baz, *args, **kwargs):
      pass

  f = Foo('hello', 42, 3.14, fred='wilma', barney='betty')
  try:
    print f.foo
  except AttributeError:
    print "Could not print f.foo"

  try:
    print f.bar
  except AttributeError:
    print "Could not print f.bar"

  try:
    print f.baz
  except AttributeError:
    print "Could not print f.baz"

  try:
    print f.fred
  except AttributeError:
    print "Could not print f.fred"

  try:
    print f.barney
  except AttributeError:
    print "Could not print f.barney"

-tkc


-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to