On Sep 12, 1:05 pm, [EMAIL PROTECTED] (Alex Martelli) wrote: > Making, say, 'a' hiddenly mean 'x.a', within a function, requires a > decorator that suitably rewrites the function's bytecode... (after > which, it WOULD still be terrible and horrible and not to be used, just > as you say, but it might at least _work_;-). Main problem is, the > decorator needs to know the set of names to be "faked out" in this > terrible and horrible way at the time the 'def' statement executes: it > can't wait until runtime (to dynamically determine what's in var(self)) > before it rewrites the bytecode
All right Alex, and since I had 20 minutes of spare time I implemented the decorator you are talking about by using the wonderful byteplay module ;) Here it is: import dis from byteplay import Code, LOAD_GLOBAL, LOAD_ATTR, LOAD_FAST, STORE_FAST def instance2local(varname): yield LOAD_FAST, 'self' yield LOAD_ATTR, varname yield STORE_FAST, varname def declare_instance_vars(*varnames): def dec(f): c = Code.from_code(f.func_code) # change LOAD_GLOBAL -> LOAD_FAST for i, (opcode, value) in enumerate(c.code): if opcode == LOAD_GLOBAL and value in varnames: c.code[i] = (LOAD_FAST, value) # insert instance2local assigments at the beginning assignments = [] for varname in varnames: for pair in instance2local(varname): assignments.append(pair) c.code[0:0] = assignments # redefine the code object f.func_code = c.to_code() return f return dec class Test(object): def __init__(self): self.a = 1 self.b = 2 def test1(self): a = self.a b = self.b return a * b @declare_instance_vars('a', 'b') def test2(self): return a * b co1 = Test.__dict__['test1'].func_code co2 = Test.__dict__['test2'].func_code print 'bytecode for test1' dis.dis(co1) print 'bytecode for test2' dis.dis(co2) t = Test() assert t.test1() == t.test2() It is still a hack, since one is not supposed to mess around with bytecodes, but at least it seems to work ;) [warning: I have not tested it more than you see] Michele Simionato -- http://mail.python.org/mailman/listinfo/python-list