import sys, os

class plain_grouping:
  def __init__(self, x, y, z):
    self.x = x
    self.y = y
    self.z = z

class update_grouping:
  def __init__(self, x, y, z):
    self.__dict__.update(locals())
    del self.self

def plain_adopt():
  frame = sys._getframe(1)
  init_locals = frame.f_locals
  self = init_locals[frame.f_code.co_varnames[0]]
  self.__dict__.update(init_locals)
  del self.self

class plain_adopt_grouping:
  def __init__(self, x, y, z):
    plain_adopt()

class autoinit(object):

  def __init__(self, *args, **keyword_args):
    self.__dict__.update(
      zip(self.__autoinit__.im_func.func_code.co_varnames[1:], args))
    self.__dict__.update(keyword_args)
    self.__autoinit__(*args, **keyword_args)

class autoinit_grouping(autoinit):

  def __autoinit__(self, x, y, z):
    pass

class autoattr(type):
  def __init__(cls, name, bases, dct):
    super(autoattr, cls).__init__(name, bases, dct)
    old_init = cls.__init__
    varnames = old_init.im_func.func_code.co_varnames[1:]
    def new_init(self, *args, **keyword_args):
      self.__dict__.update(zip(varnames, args))
      self.__dict__.update(keyword_args)
      old_init(self, *args, **keyword_args)
    cls.__init__ = new_init

class autoattr_grouping:
  __metaclass__ = autoattr
  def __init__(self, x, y, z):
    pass

try:
  from namespace import Record
except ImportError:
  Record = None
else:
  class record_grouping(Record):
    x = None
    y = None
    z = None

class timer:
  def __init__(self):
    self.t0 = os.times()
  def get(self):
    tn = os.times()
    return (tn[0]+tn[1]-self.t0[0]-self.t0[1])

def time_overhead(n_repeats):
  t = timer()
  for i in xrange(n_repeats):
    pass
  return t.get()

def time(method, n_repeats):
  g = method(x=1,y=2,z=3)
  assert g.x == 1
  assert g.y == 2
  assert g.z == 3
  t = timer()
  for i in xrange(n_repeats):
    method(x=1,y=2,z=3)
  return t.get()

def time_all(n_repeats=100000):
  print "overhead: %.2f" % time_overhead(n_repeats)
  print "plain_grouping: %.2f" % time(plain_grouping, n_repeats)
  print "update_grouping: %.2f" % time(update_grouping, n_repeats)
  print "plain_adopt_grouping: %.2f" % time(plain_adopt_grouping, n_repeats)
  print "autoinit_grouping: %.2f" % time(autoinit_grouping, n_repeats)
  print "autoattr_grouping: %.2f" % time(autoattr_grouping, n_repeats)
  if (Record is not None):
    print "record_grouping: %.2f" % time(record_grouping, n_repeats)

if (__name__ == "__main__"):
  time_all()
