python替代goto_在python中怎么实现goto功能

展开全部

goto语句32313133353236313431303231363533e78988e69d8331333337393464也称为无条件转移语句,其一般格式如下: goto 语句标号; 其中语句标号是按标识符规定书写的符号, 放在某一语句行的前面,标号后加冒号(:)。语句标号起标识语句的作用,与goto 语句配合使用。

用法是:

1. from goto import *。注意暂时不支持import goto,不是不能实现,是暂时没时间写。

2.对需要使用goto的函数,前面加个@patch

3.用label(x)和goto(x)的形式写label和goto。x可以是数字或字符串。

goto模块的代码如下:import dis,pdb

#dummy functions serving as target of bytecode patching

def goto(label):

pass

def label(label):

pass

#

def decode_bytecode(fun):

"""Input: a function

Ouput: a list of pairs (opcode, arguments)"""

c = fun.func_code.co_code

n = len(c)

i = 0

while i < n:

op = c[i]

i += 1

arguments = ""

if ord(op) >= dis.HAVE_ARGUMENT:

arguments = c[i : i+2]

i += 2

yield (op, arguments)

def sample():

goto(200)

if 1 == 2:

sample()

else:

print 'sample'

def test_decode(fun):

for op,arg in decode_bytecode(fun):

if arg=='':

print dis.opname[ord(op)]

else:

print dis.opname[ord(op)] +' '+str(ord(arg[0]))+' '+str(ord(arg[1]))

def match_pattern(seq, i, p):

"""

try to match pattern p to seq[i:], return None if match failed

seq: output of decode_bytecode

p -> [instr, instr, ...]

instr -> (opcode, arg, arg) opcode is a opcode string

arg -> '' I don't give a damn about this arg

arg -> integer match arg with number

arg -> string the arg is key of the returned match dict from which the arg value can be extracted

arg -> lambda lambda is evaluated with the argument, false return means failed match

"""

#pdb.set_trace()

m = {}

for op, arg1, arg2 in p:

if i==len(seq):

return None

if dis.opmap[op] != ord(seq[i][0]):

return None

if arg1 == '':

pass

else:

if seq[i][1] == '': return None

a1 = ord(seq[i][1][0])

if type(arg1) is str:

m[arg1]=a1

elif type(arg1) is int:

if arg1 != a1: return None

elif not arg1(a1):

return None

#don't need arg2 in this program

i+=1

return m

def int_to_bytecode_arg(i):

return chr(i % 256) +\

chr(i // 256)

def patch(fun):

NOP = chr(dis.opmap['NOP'])

co = fun.func_code

old = list(decode_bytecode(fun))

new = [] #a list of characters

#mapping from label to bytecode offset

label_table={}

#if a goto(label) is seen but label is not seen

#record for the number the bytecode offset of the

#argument for JUMP_ABSOLUTE for later patching

goto_table={}

i=0

#pdb.set_trace()

while i

m= match_pattern(old, i,

[('LOAD_GLOBAL','fun_name',''),

('LOAD_CONST','label',''),

('CALL_FUNCTION',1,''),

('POP_TOP','','')])

if m:

stmt = co.co_names[m['fun_name']]

label = co.co_consts[m['label']]

if m and stmt == 'goto':

# we have a goto statement

if label_table.has_key(label):

arg = int_to_bytecode_arg(label_table[label])

else:

arg = '\xff\xff'

goto_table[label] =\

goto_table.get(label, [])+[len(new)+1]

new += chr(dis.opmap['JUMP_ABSOLUTE'])

new += arg

#todo

#this is to maintain proper bytecode offset to

#source code line number mapping. A better way

#would be fixing the mapping instead of using

#placeholders

new += NOP*7

i += 4

elif m and stmt == 'label':

# we have a label statement

label_table[label]=len(new)

if goto_table.has_key(label):

for offset in goto_table[label]:

new[offset: offset+2]=int_to_bytecode_arg(len(new))

del goto_table[label]

new += NOP*10

i += 4

else:

# emit as-is

new += old[i][0] #the opcode

new += old[i][1] #its args if it has

i += 1

if len(goto_table):

#todo: output line number

raise Exception('missing label')

import types

newcode = types.CodeType(co.co_argcount,

co.co_nlocals,

co.co_stacksize,

co.co_flags,

''.join(new),

co.co_consts,

co.co_names,

co.co_varnames,

co.co_filename,

co.co_name,

co.co_firstlineno,

co.co_lnotab)

return types.FunctionType(newcode,fun.func_globals)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值