associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Revisão 1e 2008-01-14 12:20:52

Excluir mensagem

NoSelf

Essa é para você, que fica desesperado em ter que digitar aquele MALDITO 'self' no início de todos seus métodos. Seus problemas acabaram! Você jamais terá de se preocupar em digitar aqueles quatro caracteres na definição de método novamente. Claro que você terá de se preocupar com muitas outras coisas, mas isso é um mero detalhe.

Basta salvar o código abaixo em um módulo, importar a classe NoSelfType para seu módulo e definir a variável 'metaclass = NoSelfType' no início.

OBS: aos desavisados, esse código é uma brincadeira, feita para mostrar como retirar o self é algo muito mais complicado do que parece! Não vá utilizá-lo em código real!

   1 import opcode
   2 import types
   3 
   4 
   5 locals().update(opcode.opmap)
   6 
   7 
   8 def noself(func, inst):
   9     code = func.func_code
  10     argdefs = func.func_defaults
  11 
  12     argcount = code.co_argcount
  13     nlocals = code.co_nlocals
  14     stacksize = code.co_stacksize
  15     flags = code.co_flags
  16     codestring = code.co_code
  17     constants = code.co_consts
  18     names = code.co_names
  19     varnames = code.co_varnames
  20     filename = code.co_filename
  21     name = code.co_name
  22     firstlineno = code.co_firstlineno
  23     lnotab = code.co_lnotab
  24     freevars = code.co_freevars
  25     cellvars = code.co_cellvars
  26 
  27     varnames = varnames + ('self',)
  28     constants = constants + (inst,)
  29     nlocals += 1
  30 
  31 
  32     bcode = map(ord, code.co_code)
  33     bcode = [LOAD_CONST,
  34              len(constants)-1,
  35              0,
  36              STORE_FAST,
  37              len(varnames)-1,
  38              0] + bcode
  39 
  40 
  41     itercode = iter(enumerate(bcode))
  42     earg = 0
  43     while 1:
  44         try:
  45             i, op = itercode.next()
  46             if op >= opcode.HAVE_ARGUMENT:
  47                 oparg = itercode.next()[1] + itercode.next()[1]*256 + earg
  48                 if op == LOAD_GLOBAL:
  49                     if names[oparg] == 'self':
  50                         bcode[i] = LOAD_FAST
  51                         bcode[i+1] = len(varnames)-1
  52                         bcode[i+2] = 0
  53         except StopIteration:
  54             break
  55 
  56     codestring = ''.join(map(chr, bcode))
  57 
  58 
  59 
  60     ncode = types.CodeType(argcount, nlocals, stacksize, flags, codestring, constants, names, varnames, filename, name, firstlineno, lnotab, freevars, cellvars)
  61     nfunc = types.FunctionType(ncode, func.func_globals, func.func_name, argdefs, func.func_closure)
  62 
  63     return nfunc
  64 
  65 
  66 class NoSelfMethod(object):
  67     def __init__(self, func, instance=None, cls=None):
  68         self.im_func = func
  69         self.im_self = instance
  70         self.im_class = cls
  71 
  72     def __get__(self, obj, cls):
  73         return NoSelfMethod(self.im_func, obj, cls)
  74 
  75     def __call__(self, *args, **kwds):
  76         if self.im_self is None:
  77             return self.im_func(*args, **kwds)
  78         else:
  79             func = noself(self.im_func, self.im_self)
  80             return func(*args, **kwds)
  81 
  82 
  83 class NoSelfType(type):
  84     def __new__(mcls, name, bases, dic):
  85         for k, v in dic.items():
  86             if callable(v):
  87                 dic[k] = NoSelfMethod(v)
  88 
  89         return type.__new__(NoSelfType, name, bases, dic)
  90         
  91 
  92 def test():
  93 
  94     class C(object):
  95         __metaclass__ = NoSelfType
  96 
  97         def __init__(a, b, c=None):
  98             print 'Look mom... no self!'
  99             print 'I am', self, 'they called me with', a, b, c
 100 
 101         def m(obj):
 102         
 103             assert obj is self
 104 
 105 
 106     o = C(1, 2, c='foo')
 107     o.m(o)
 108         
 109         
 110 if __name__ == '__main__':
 111     test()