惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
有赞技术团队
有赞技术团队
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
D
DataBreaches.Net
F
Full Disclosure
腾讯CDC
博客园 - 【当耐特】
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园 - 聂微东
雷峰网
雷峰网
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
Scott Helme
Scott Helme
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
O
OpenAI News
Project Zero
Project Zero
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Application and Cybersecurity Blog
Application and Cybersecurity Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
MongoDB | Blog
MongoDB | Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
Schneier on Security
Schneier on Security

博客园 - yushih

初学Erlang,写两个程序玩玩 Django杂记: super与metaclass,locmem有害 一直没弄明白的事--为什么招聘要求会有“面向对象分析与设计”这一项 用Linux的iptables和Python模拟广域网 实用主义之过--Pragmatic Version Control using Subersion, 2nd Ed.的书评 Python把C语言打得满地找牙 信春哥!Python递归原地满状态变显式堆栈!入教即送尾递归优化! STL的binary search算法正确性的初步说明 关于文档标准之争的一点旁注 有关Ruby eval的一点编程风格 Design pattern一来,动态语言就笑了 - yushih - 博客园 完全没有领会“电子商务”的真谛 超级奇怪的F#格式错误 JAOO的魅力所在 一个Ruby idiom F#的一点糖 C++ hack:将C++编译器的类型检查转化为SLR(1)解析器 Quotes The Ruby Programming Language第一版非官方修正
Python programming with goto
yushih · 2010-05-05 · via 博客园 - yushih

豆瓣Python版有人想要goto。虽说看不出来goto有什么特别吸引力,但是为了实现Python社区对广大人民群众做出的“Python是世界上除Lisp外最牛b的编程语言”的庄严承诺,同时也为了复习一下一段时间没用Python知识,写了一个goto模块。使用如下例:

 1 from goto import *
 2 
 3 @patch
 4 def f2():
 5     goto(10)
 6     print 'should not see this'
 7     label(10)
 8     for i in range(1,99999):
 9         print i
10         if i == 5:
11             goto('out')
12     label('out')
13 
14 f2()

用法是:

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

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

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

 goto模块的代码如下:

goto.py

import dis,pdb#dummy functions serving as target of bytecode patching
def goto(label):
    
passdef 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 Noneif 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
+=1return 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<len(old):
        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 += 1if 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)