下面这个例子用可变长参数调用func并将可变长参数*arg传递给func。比如test(sleep, 1)就相当于 sleep(1);test(max, 1, -1)就相当于调用max(1,-1)。
def test(func, *args, **kargs): if not callable(func): raise RuntimeError, str(func) + ' not a callable object' else: func(*args, **kargs)
def test(func, *args, **kargs): if not callable(func): raise RuntimeError, str(func) + ' not a callable object' else: func(*args, **kargs)
import os
import time
from threading import Thread
class Job(Thread):
def __init__(self, cmd):
Thread.__init__(self)
self.cmd = cmd
self.starttime = time.time()
def run(self):
os.popen(self.cmd)
print "time %.2fs, job %s is done"%(time.time()-self.starttime,self.cmd)
jobs = []
for i in range(1, 5):
j = Job("sleep %d"%i)
jobs.append(j)
j.start()
for j in jobs:
j.join()
print "time %.2fs, job %s returned"%(time.time() - j.starttime, j.cmd)
time 1.00s, job sleep 1 is done
time 1.00s, job sleep 1 returned
time 2.00s, job sleep 2 is done
time 2.00s, job sleep 2 returned
time 3.00s, job sleep 3 is done
time 3.00s, job sleep 3 returned
time 4.00s, job sleep 4 is done
time 4.00s, job sleep 4 returned
for j in reversed(jobs):得到结果:
j.join()
print "time %.2fs, job %s returned"%(time.time() - j.starttime, j.cmd)
time 1.00s, job sleep 1 is done所以当你调用join时,仅仅是检查该线程是否以及结束。如果结束则返回;否则阻塞直至结束。
time 2.00s, job sleep 2 is done
time 3.00s, job sleep 3 is done
time 4.00s, job sleep 4 is done
time 4.00s, job sleep 4 returned
time 4.01s, job sleep 3 returned
time 4.01s, job sleep 2 returned
time 4.01s, job sleep 1 returned
for j in reversed(jobs):
j.join(0.5)
print "time %.2fs, job %s returned"%(time.time() - j.starttime, j.cmd)
time 0.52s, job sleep 1 returned
time 1.00s, job sleep 1 is done
time 1.02s, job sleep 2 returned
time 1.52s, job sleep 3 returned
time 2.00s, job sleep 2 is done
time 2.02s, job sleep 4 returned
time 3.00s, job sleep 3 is done
time 4.00s, job sleep 4 is done
class Jobs(Queue.Queue):
def __init__(self):
Queue.Queue.__init__(self)
def newjob(self, name, func, *args, **kargs):
if not callable(func):
raise RuntimeError, str(func) + ' not a callable object'
self.put((name, func, args, kargs))
def do(self, numthreads = 1, debug = True):
threads = []
for i in range(numthreads):
t = Worker("thread%d"%i, self, debug)
threads.append(t)
t.start()
for t in threads:
t.join()
class Worker(threading.Thread):
def __init__(self, name, jobs, debug = False):
threading.Thread.__init__(self)
self.name = name
self.jobs = jobs
self.debug = debug
def run(self):
while not self.jobs.empty():
try:
job = self.jobs.get(True, 1)
(name, func, args, kargs) = job
except:
break
stime = time()
func(*args, **kargs)
if self.debug:
print "%s is done by %s, fin in %.2f s"%(name, self.name, time()-stime
>>>mylist = [1,2,3] >>>type(mylist) <type 'list'>所以这里我们新建了一个list的实例叫mylist。通过内建的type()函数我们可以查看这个实例的类型,返回的结果告诉我们它的类型是list这种内建的类型。
>>>type(list) <type 'type'> >>>list.__bases__ (<type 'object'>,)这里我们先查看了list的类型。我们得知list的类型是type,换言之list是type的一个实例。紧接着我们用__bases__属性查看它的父类,得知list其实继承了内建的object。再来
>>>type(type) <type 'type'> >>>type.__bases__ (<type 'object'>,)好,现在我们知道type的类型还是type自己,它是自己的一个实例,同时它继承了object。最后:
>>>type(object) <type 'type'> >>>type.__bases__ ()从而我们得知,object也是type的一个实例,同时它没有父类。
>>>class oldclass: ... def __init__(self): ... pass >>>class newclass(object): ... def __init__(self): ... pass
>>>oldobj = oldclass() >>>newobj = newclass() >>>print type(oldobj), oldobj.__class__ <type 'instance'> <class __main__.oldclass at 0x7f700714da10> >>>print type(newobj), newobj.__class__ <class '__main__.newclass'> <class '__main__.newclass'>
>>>print type(dict), dict.__class__ <type 'type'> <type 'type'>我们看到同样的结论。
Include/ | C源代码的头文件(.h) |
Lib/ | 用Python自己写的Python库文件(.py) |
Python/ | 这里是"编译器"和解释器的源码,Python的核心所在 |
Grammar/ | 包括一个Grammar文件,用BNF描述Python语言语法 |
Parser/ | 生成pgen这个工具使用Grammar文件 |
stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef它表示每个stmt可以是一个simple_stmt也可以是一个compound_stmt。simple_stmt可以是几个small_stmt的同行并列用";"隔开。 small_stmt可以是expr_stmt, print_stmt, del_stmt等简单语句。而compound_stmt则包括if_stmt, while_stmt等需要跨越多行的复合语句。就这样Python用BNF范式定义了最基本的语法。 现在我们有了这个通俗易懂的Grammar文件以后,pgen负责把这个Grammar转换成NFA,然后再转换为相应的DFA,接着再化简这个DFA,最后保存在gramint.c 和gramint.h这两个文件中。如果你觉得很复杂,你只需要记住我们根据Grammar这个文件得到了一个语法规则就可以了。我们现在来看一下一个py交互模式的运作流程以便于理解:
run_tty_loop(fp,filename){ for (;;) { run_tty_1(fp,filename); //不断执行一个“单行”语句 } }
run_tty_1(fp, filename) { //gram <- graminit将已生成的Python语法规则放进gram, //其实不在这个函数里完成,为了理解的方便我就这样写在这里。 //根据语法gram以及输入文件fp生成语法树存放在n中 node* n = parsefile(fp, filename, &gram, single_input, ...) // 执行以n为根节点的语法树 v = run_node(n, filename, ...) }
parsefile(fp,filename, g, ...) { //初始化err_ret //初始化一个tokenizer(词法分析器)tok tok = tok_setupf(fp, ...); return parsetok(tok, g, ...); }所以这个函数也相当简单,初始化一个词法分析器然后调用parsetok开始做词法分析。再来看parsetok:
parsetok(tok, g, ...) { ps = newparser(g, start) for (;;) { type = tok_get(tok, &a, &b); addtoken(ps, type, ...); } delparser(ps); }所以这里就是用一个for循环不停的调用tok_get抓取下一个token供语法分析使用。语法分析里的状态转移以及移进归约在addtoken中实现。