カテゴリー
Uncategorized

[Python] 参照渡し

見るも無惨なキモイコードシリーズ

というか引数を内部でポンポンいじられるのって単純な話分かりにくいよ。関数で加工した値を再度代入する、という形はやっぱり分かりやすい。

import sys
from opcode import *
def callee_names(frame_depth=1):
result = []
frame = sys._getframe(frame_depth + 2)
co = frame.f_code
code = co.co_code
i = 0; n = frame.f_lasti - 2
oparg = extended_arg = 0
while i < n:
c = code[i]
op = ord(c)
i = i + 1
if op >= HAVE_ARGUMENT:
oparg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg
extended_arg = 0
i = i + 2
if op == EXTENDED_ARG:
extended_arg = oparg * 65536L
if op in hasconst:
result.append(co.co_consts[oparg])
elif op in hasname:
result.append(co.co_names[oparg])
elif op in haslocal:
result.append(co.co_varnames[oparg])
elif op in hasfree:
result.append((co.co_cellvars + co.co_freevars)[oparg])
callee = sys._getframe(frame_depth + 1)
argcount = callee.f_code.co_argcount
index = argcount
if callee.f_code.co_flags & 0x04:
argcount += len(callee.f_locals[callee.f_code.co_varnames[index]])
index += 1
if callee.f_code.co_flags & 0x08:
argcount += len(callee.f_locals[callee.f_code.co_varnames[index]]) * 2
result = result[-argcount:]
return result
class ByRef(object):
def __init__(self):
self.__dict__['locals'] = callee_names(1)
def __setattr__(self, _name, _value):
callee = sys._getframe(1)
caller = sys._getframe(2)
argindex = list(callee.f_code.co_varnames).index(_name)
localname = self.__dict__['locals'][argindex]
caller.f_locals[localname] = _value
if __name__ == '__main__':
def foo(v1, v2, *args, **kwargs):
byref = ByRef() # first of all, create ByRef instance.
byref.v2 = v1 * 2
a = 10
b = 0
c = -10
print b
foo(a, b, c,
foo=1)
print b

例によって動かない可能性がある

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です