2006年06月24日 星期六 12:15
Python 2.5的beta 1出来了。每次拿到新版本的时候,总是先看what's new。这次看with的时候,发现与先前PEP 310的有很大不同。2.5最终实现的是PEP343。 下面是我翻译的what's new。第一次接触with,谬误指出请大家包涵。 --------------------------------------------------------------------------------------------------------- 8 PEP 343: The 'with' statement The 'with' statement clarifies code that previously would use try...finally blocks to ensure that clean-up code is executed. In this section, I'll discuss the statement as it will commonly be used. In the next section, I'll examine the implementation details and show how to write objects for use with this statement. 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 The 'with' statement is a new control-flow structure whose basic structure is: 'with' statement是一个新的流程控制结构,其基本的语法如下: with expression [as variable]: with-block The expression is evaluated, and it should result in an object that supports the context management protocol. This object may return a value that can optionally be bound to the name variable. (Note carefully that variable is not assigned the result of expression.) The object can then run set-up code before with-block is executed and some clean-up code is executed after the block is done, even if the block raised an exception. (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, 即便是因为发生了异常,它也会执行清理代码。 To enable the statement in Python 2.5, you need to add the following directive to your module: 要在Python 2.5里面用with语句,你得在module里面加上下面这行: from __future__ import with_statement The statement will always be enabled in Python 2.6. 等到了Python 2.6,你就不用再这么麻烦了。 Some standard Python objects now support the context management protocol and can be used with the 'with' statement. File objects are one example: 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 File对象就是一例: with open('/etc/passwd', 'r') as f: for line in f: print line ... more processing code ... After this statement has executed, the file object in f will have been automatically closed, even if the 'for' loop raised an exception part-way through the block. 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, file对象f也会自动关闭。 The threading module's locks and condition variables also support the 'with' statement: threading模块的lock和condition对象也支持with 语句 (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): lock = threading.Lock() with lock: # Critical section of code ... The lock is acquired before the block is executed and always released once the block is complete. 执行block之前得先得到lock,然后执行完毕之后会释放锁。 The decimal module's contexts, which encapsulate the desired precision and rounding characteristics for computations, provide a context_manager() method for getting a context manager: decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 (context是上下文的意思)将计算的精度和近似要求封装了起来 (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): import decimal # Displays with default precision of 28 digits v1 = decimal.Decimal('578') print v1.sqrt() ctx = decimal.Context(prec=16) #---------------------------------------- # 根据shhgs的试验,ctx对象是没有context_manager()方法的, # 你得 # with ctx.get_manager() : #---------------------------------------- with ctx.context_manager(): # All code in this block uses a precision of 16 digits. # The original context is restored on exiting the block. print v1.sqrt() 8.1 Writing Context Managers Under the hood, the 'with' statement is fairly complicated. Most people will only use 'with' in company with existing objects and don't need to know these details, so you can skip the rest of this section if you like. Authors of new objects will need to understand the details of the underlying implementation and should keep reading. 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, 那就得受累读下去了。 A high-level explanation of the context management protocol is: context management 接口的大致概括如下: The expression is evaluated and should result in an object called a ``context manager''. The context manager must have __enter__() and __exit__() methods. (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 这个context manager必须提供__enter__()和__exit__()方法。 The context manager's __enter__() method is called. The value returned is assigned to VAR. If no 'as VAR' clause is present, the value is simply discarded. 然后(with)再调用context manager的__enter__()方法。 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 如果没有'as VAR',这个值就丢了。 The code in BLOCK is executed. 然后执行BLOCK。 If BLOCK raises an exception, the __exit__(type, value, traceback) is called with the exception details, the same values returned by sys.exc_info(). The method's return value controls whether the exception is re-raised: any false value re-raises the exception, and True will result in suppressing it. You'll only rarely want to suppress the exception, because if you do the author of the code containing the 'with' statement will never realize anything went wrong. 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 If BLOCK didn't raise an exception, the __exit__() method is still called, but type, value, and traceback are all None. 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, traceback都是None。 Let's think through an example. I won't present detailed code but will only sketch the methods necessary for a database that supports transactions. 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 支持transaction地数据库所必须提供的方法。 (For people unfamiliar with database terminology: a set of changes to the database are grouped into a transaction. Transactions can be either committed, meaning that all the changes are written into the database, or rolled back, meaning that the changes are all discarded and the database is unchanged. See any database textbook for more information.) (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) Let's assume there's an object representing a database connection. Our goal will be to let the user write code like this: 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: db_connection = DatabaseConnection() with db_connection as cursor: cursor.execute('insert into ...') cursor.execute('delete from ...') # ... more operations ... The transaction should be committed if the code in the block runs flawlessly or rolled back if there's an exception. Here's the basic interface for DatabaseConnection that I'll assume: 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 下面是我所预想的这个DatabaseConnection的基本接口。 class DatabaseConnection: # Database interface def cursor (self): "Returns a cursor object and starts a new transaction" def commit (self): "Commits current transaction" def rollback (self): "Rolls back current transaction" The __enter__() method is pretty easy, having only to start a new transaction. For this application the resulting cursor object would be a useful result, so the method will return it. The user can then add as cursor to their 'with' statement to bind the cursor to a variable name. __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 class DatabaseConnection: ... def __enter__ (self): # Code to start a new transaction cursor = self.cursor() return cursor The __exit__() method is the most complicated because it's where most of the work has to be done. The method has to check if an exception occurred. If there was no exception, the transaction is committed. The transaction is rolled back if there was an exception. __exit__()最烦了,因为绝大多数的工作都是在这里干的。 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 In the code below, execution will just fall off the end of the function, returning the default value of None. None is false, so the exception will be re-raised automatically. If you wished, you could be more explicit and add a return statement at the marked location. 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 class DatabaseConnection: ... def __exit__ (self, type, value, tb): if tb is None: # No exception, so commit self.commit() else: # Exception occurred, so rollback. self.rollback() # return False 8.2 The contextlib module The new contextlib module provides some functions and a decorator that are useful for writing objects for use with the 'with' statement. 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 The decorator is called contextfactory, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the yield will be executed as the __enter__() method, and the value yielded will be the method's return value that will get bound to the variable in the 'with' statement's as clause, if any. The code after the yield will be executed in the __exit__() method. Any exception raised in the block will be raised by the yield statement. 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 此外,yield还会把block里面的异常再抛出来。 Our database example from the previous section could be written using this decorator as: 我们前面讲的数据库的例子可以这样改写: from contextlib import contextfactory @contextfactory def db_transaction (connection): cursor = connection.cursor() try: yield cursor except: connection.rollback() raise else: connection.commit() db = DatabaseConnection() with db_transaction(db) as cursor: ... The contextlib module also has a nested(mgr1, mgr2, ...) function that combines a number of context managers so you don't need to write nested 'with' statements. In this example, the single 'with' statement both starts a database transaction and acquires a thread lock: contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 transaction并获取了线程的锁。 lock = threading.Lock() with nested (db_transaction(db), lock) as (cursor, locked): ... Finally, the closing(object) function returns object so that it can be bound to a variable, and calls object.close() at the end of the block. 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, 然后在block的最后(with会自动)调用object.close()了。 import urllib, sys from contextlib import closing with closing(urllib.urlopen('http://www.yahoo.com')) as f: for line in f: sys.stdout.write(line) 8 PEP 343: The 'with' statement The 'with' statement clarifies code that previously would use try...finally blocks to ensure that clean-up code is executed. In this section, I'll discuss the statement as it will commonly be used. In the next section, I'll examine the implementation details and show how to write objects for use with this statement. 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 The 'with' statement is a new control-flow structure whose basic structure is: 'with' statement是一个新的流程控制结构,其基本的语法如下: with expression [as variable]: with-block The expression is evaluated, and it should result in an object that supports the context management protocol. This object may return a value that can optionally be bound to the name variable. (Note carefully that variable is not assigned the result of expression.) The object can then run set-up code before with-block is executed and some clean-up code is executed after the block is done, even if the block raised an exception. (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, 即便是因为发生了异常,它也会执行清理代码。 To enable the statement in Python 2.5, you need to add the following directive to your module: 要在Python 2.5里面用with语句,你得在module里面加上下面这行: from __future__ import with_statement The statement will always be enabled in Python 2.6. 等到了Python 2.6,你就不用再这么麻烦了。 Some standard Python objects now support the context management protocol and can be used with the 'with' statement. File objects are one example: 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 File对象就是一例: with open('/etc/passwd', 'r') as f: for line in f: print line ... more processing code ... After this statement has executed, the file object in f will have been automatically closed, even if the 'for' loop raised an exception part-way through the block. 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, file对象f也会自动关闭。 The threading module's locks and condition variables also support the 'with' statement: threading模块的lock和condition对象也支持with 语句 (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): lock = threading.Lock() with lock: # Critical section of code ... The lock is acquired before the block is executed and always released once the block is complete. 执行block之前得先得到lock,然后执行完毕之后会释放锁。 The decimal module's contexts, which encapsulate the desired precision and rounding characteristics for computations, provide a context_manager() method for getting a context manager: decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 (context是上下文的意思)将计算的精度和近似要求封装了起来 (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): import decimal # Displays with default precision of 28 digits v1 = decimal.Decimal('578') print v1.sqrt() ctx = decimal.Context(prec=16) #---------------------------------------- # 根据shhgs的试验,ctx对象是没有context_manager()方法的, # 你得 # with ctx.get_manager() : #---------------------------------------- with ctx.context_manager(): # All code in this block uses a precision of 16 digits. # The original context is restored on exiting the block. print v1.sqrt() 8.1 Writing Context Managers Under the hood, the 'with' statement is fairly complicated. Most people will only use 'with' in company with existing objects and don't need to know these details, so you can skip the rest of this section if you like. Authors of new objects will need to understand the details of the underlying implementation and should keep reading. 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, 那就得受累读下去了。 A high-level explanation of the context management protocol is: context management 接口的大致概括如下: The expression is evaluated and should result in an object called a ``context manager''. The context manager must have __enter__() and __exit__() methods. (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 这个context manager必须提供__enter__()和__exit__()方法。 The context manager's __enter__() method is called. The value returned is assigned to VAR. If no 'as VAR' clause is present, the value is simply discarded. 然后(with)再调用context manager的__enter__()方法。 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 如果没有'as VAR',这个值就丢了。 The code in BLOCK is executed. 然后执行BLOCK。 If BLOCK raises an exception, the __exit__(type, value, traceback) is called with the exception details, the same values returned by sys.exc_info(). The method's return value controls whether the exception is re-raised: any false value re-raises the exception, and True will result in suppressing it. You'll only rarely want to suppress the exception, because if you do the author of the code containing the 'with' statement will never realize anything went wrong. 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 If BLOCK didn't raise an exception, the __exit__() method is still called, but type, value, and traceback are all None. 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, traceback都是None。 Let's think through an example. I won't present detailed code but will only sketch the methods necessary for a database that supports transactions. 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 支持transaction地数据库所必须提供的方法。 (For people unfamiliar with database terminology: a set of changes to the database are grouped into a transaction. Transactions can be either committed, meaning that all the changes are written into the database, or rolled back, meaning that the changes are all discarded and the database is unchanged. See any database textbook for more information.) (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) Let's assume there's an object representing a database connection. Our goal will be to let the user write code like this: 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: db_connection = DatabaseConnection() with db_connection as cursor: cursor.execute('insert into ...') cursor.execute('delete from ...') # ... more operations ... The transaction should be committed if the code in the block runs flawlessly or rolled back if there's an exception. Here's the basic interface for DatabaseConnection that I'll assume: 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 下面是我所预想的这个DatabaseConnection的基本接口。 class DatabaseConnection: # Database interface def cursor (self): "Returns a cursor object and starts a new transaction" def commit (self): "Commits current transaction" def rollback (self): "Rolls back current transaction" The __enter__() method is pretty easy, having only to start a new transaction. For this application the resulting cursor object would be a useful result, so the method will return it. The user can then add as cursor to their 'with' statement to bind the cursor to a variable name. __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 class DatabaseConnection: ... def __enter__ (self): # Code to start a new transaction cursor = self.cursor() return cursor The __exit__() method is the most complicated because it's where most of the work has to be done. The method has to check if an exception occurred. If there was no exception, the transaction is committed. The transaction is rolled back if there was an exception. __exit__()最烦了,因为绝大多数的工作都是在这里干的。 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 In the code below, execution will just fall off the end of the function, returning the default value of None. None is false, so the exception will be re-raised automatically. If you wished, you could be more explicit and add a return statement at the marked location. 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 class DatabaseConnection: ... def __exit__ (self, type, value, tb): if tb is None: # No exception, so commit self.commit() else: # Exception occurred, so rollback. self.rollback() # return False 8.2 The contextlib module The new contextlib module provides some functions and a decorator that are useful for writing objects for use with the 'with' statement. 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 The decorator is called contextfactory, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the yield will be executed as the __enter__() method, and the value yielded will be the method's return value that will get bound to the variable in the 'with' statement's as clause, if any. The code after the yield will be executed in the __exit__() method. Any exception raised in the block will be raised by the yield statement. 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 此外,yield还会把block里面的异常再抛出来。 Our database example from the previous section could be written using this decorator as: 我们前面讲的数据库的例子可以这样改写: from contextlib import contextfactory @contextfactory def db_transaction (connection): cursor = connection.cursor() try: yield cursor except: connection.rollback() raise else: connection.commit() db = DatabaseConnection() with db_transaction(db) as cursor: ... The contextlib module also has a nested(mgr1, mgr2, ...) function that combines a number of context managers so you don't need to write nested 'with' statements. In this example, the single 'with' statement both starts a database transaction and acquires a thread lock: contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 transaction并获取了线程的锁。 lock = threading.Lock() with nested (db_transaction(db), lock) as (cursor, locked): ... Finally, the closing(object) function returns object so that it can be bound to a variable, and calls object.close() at the end of the block. 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, 然后在block的最后(with会自动)调用object.close()了。 import urllib, sys from contextlib import closing with closing(urllib.urlopen('http://www.yahoo.com')) as f: for line in f: sys.stdout.write(line) ---------------------------------------------------------------------------------------------------------
2006年06月24日 星期六 18:55
Well done! Great work! On 6/24/06, shhgs <shhgs.efhilt at gmail.com> wrote: > > Python 2.5的beta 1出来了。每次拿到新版本的时候,总是先看what's new。这次看with的时候,发现与先前PEP > 310的有很大不同。2.5最终实现的是PEP343。 > > 下面是我翻译的what's new。第一次接触with,谬误指出请大家包涵。 > > > --------------------------------------------------------------------------------------------------------- > 8 PEP 343: The 'with' statement > > The 'with' statement clarifies code that previously would use > try...finally > blocks to ensure that clean-up code is executed. In this section, I'll > discuss > the statement as it will commonly be used. In the next section, I'll > examine the > implementation details and show how to write objects for use with this > statement. > > 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 > 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 > > The 'with' statement is a new control-flow structure whose basic structure > is: > > 'with' statement是一个新的流程控制结构,其基本的语法如下: > > > with expression [as variable]: > with-block > > The expression is evaluated, and it should result in an object that > supports the > context management protocol. This object may return a value that can > optionally > be bound to the name variable. (Note carefully that variable is not > assigned the > result of expression.) The object can then run set-up code before > with-block is > executed and some clean-up code is executed after the block is done, > even if the > block raised an exception. > > (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, > 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 > 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) > 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, > 即便是因为发生了异常,它也会执行清理代码。 > > To enable the statement in Python 2.5, you need to add the following > directive > to your module: > > 要在Python 2.5里面用with语句,你得在module里面加上下面这行: > > > from __future__ import with_statement > > The statement will always be enabled in Python 2.6. > 等到了Python 2.6,你就不用再这么麻烦了。 > > Some standard Python objects now support the context management protocol > and > can be used with the 'with' statement. File objects are one example: > > 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 > File对象就是一例: > > with open('/etc/passwd', 'r') as f: > for line in f: > print line > ... more processing code ... > > After this statement has executed, the file object in f will have been > automatically > closed, even if the 'for' loop raised an exception part-way through the > block. > > 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, > file对象f也会自动关闭。 > > The threading module's locks and condition variables also support the > 'with' statement: > > threading模块的lock和condition对象也支持with 语句 > (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): > > > lock = threading.Lock() > with lock: > # Critical section of code > ... > > The lock is acquired before the block is executed and always released > once the block > is complete. > > 执行block之前得先得到lock,然后执行完毕之后会释放锁。 > > The decimal module's contexts, which encapsulate the desired precision > and rounding > characteristics for computations, provide a context_manager() method > for getting a > context manager: > > decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, > 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 > (context是上下文的意思)将计算的精度和近似要求封装了起来 > (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): > > import decimal > > # Displays with default precision of 28 digits > v1 = decimal.Decimal('578') > print v1.sqrt() > > ctx = decimal.Context(prec=16) > #---------------------------------------- > # 根据shhgs的试验,ctx对象是没有context_manager()方法的, > # 你得 > # with ctx.get_manager() : > #---------------------------------------- > with ctx.context_manager(): > # All code in this block uses a precision of 16 digits. > # The original context is restored on exiting the block. > print v1.sqrt() > > > > 8.1 Writing Context Managers > Under the hood, the 'with' statement is fairly complicated. > Most people will only use 'with' in company with existing objects > and don't need to know these details, so you can skip the rest of > this section if you like. Authors of new objects will need to understand > the details of the underlying implementation and should keep reading. > > 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, > 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, > 那就得受累读下去了。 > > A high-level explanation of the context management protocol is: > > context management 接口的大致概括如下: > > The expression is evaluated and should result in an object called a > ``context manager''. The context manager must have __enter__() and > __exit__() methods. > > (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 > 这个context manager必须提供__enter__()和__exit__()方法。 > > The context manager's __enter__() method is called. > The value returned is assigned to VAR. > If no 'as VAR' clause is present, the value is simply discarded. > > 然后(with)再调用context manager的__enter__()方法。 > 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 > 如果没有'as VAR',这个值就丢了。 > > > The code in BLOCK is executed. > > 然后执行BLOCK。 > > If BLOCK raises an exception, the __exit__(type, value, traceback) is > called > with the exception details, the same values returned by sys.exc_info(). > The method's return value controls whether the exception is re-raised: > any false value re-raises the exception, and True will result in > suppressing it. > You'll only rarely want to suppress the exception, because if you do the > author > of the code containing the 'with' statement will never realize > anything went wrong. > > 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 > 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 > 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, > 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 > > If BLOCK didn't raise an exception, the __exit__() method is still called, > but type, value, and traceback are all None. > > 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, > traceback都是None。 > > Let's think through an example. I won't present detailed code but will > only > sketch the methods necessary for a database that supports transactions. > > 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 > 支持transaction地数据库所必须提供的方法。 > > (For people unfamiliar with database terminology: a set of changes to > the database > are grouped into a transaction. Transactions can be either committed, > meaning that > all the changes are written into the database, or rolled back, meaning > that the > changes are all discarded and the database is unchanged. See any > database textbook > for more information.) > > (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 > 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, > 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) > > Let's assume there's an object representing a database connection. > Our goal will be to let the user write code like this: > > 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: > > db_connection = DatabaseConnection() > with db_connection as cursor: > cursor.execute('insert into ...') > cursor.execute('delete from ...') > # ... more operations ... > > The transaction should be committed if the code in the block runs > flawlessly or > rolled back if there's an exception. Here's the basic interface for > DatabaseConnection > that I'll assume: > > 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 > 下面是我所预想的这个DatabaseConnection的基本接口。 > > > class DatabaseConnection: > # Database interface > def cursor (self): > "Returns a cursor object and starts a new transaction" > def commit (self): > "Commits current transaction" > def rollback (self): > "Rolls back current transaction" > > The __enter__() method is pretty easy, having only to start a new > transaction. > For this application the resulting cursor object would be a useful result, > so the method will return it. The user can then add as cursor to their > 'with' > statement to bind the cursor to a variable name. > > __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, > cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 > > class DatabaseConnection: > ... > def __enter__ (self): > # Code to start a new transaction > cursor = self.cursor() > return cursor > > The __exit__() method is the most complicated > because it's where most of the work has to be done. > The method has to check if an exception occurred. > If there was no exception, the transaction is committed. > The transaction is rolled back if there was an exception. > > __exit__()最烦了,因为绝大多数的工作都是在这里干的。 > 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 > > In the code below, execution will just fall off the end of the function, > returning the default value of None. None is false, so the exception will > be re-raised automatically. If you wished, you could be more explicit and > add a return statement at the marked location. > > 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, > 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 > > class DatabaseConnection: > ... > def __exit__ (self, type, value, tb): > if tb is None: > # No exception, so commit > self.commit() > else: > # Exception occurred, so rollback. > self.rollback() > # return False > > > > 8.2 The contextlib module > The new contextlib module provides some functions and a decorator that > are useful > for writing objects for use with the 'with' statement. > > 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 > > The decorator is called contextfactory, and lets you write a single > generator > function instead of defining a new class. The generator should yield > exactly one value. > The code up to the yield will be executed as the __enter__() method, > and the value yielded will be the method's return value that will get > bound to the > variable in the 'with' statement's as clause, if any. The code after > the yield will be > executed in the __exit__() method. Any exception raised in the block > will be raised > by the yield statement. > > 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 > 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, > yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 > 此外,yield还会把block里面的异常再抛出来。 > > Our database example from the previous section could be written using > this decorator as: > > 我们前面讲的数据库的例子可以这样改写: > > from contextlib import contextfactory > > @contextfactory > def db_transaction (connection): > cursor = connection.cursor() > try: > yield cursor > except: > connection.rollback() > raise > else: > connection.commit() > > db = DatabaseConnection() > with db_transaction(db) as cursor: > ... > > The contextlib module also has a nested(mgr1, mgr2, ...) function > that combines a number of context managers so you don't need to write > nested > 'with' statements. In this example, the single 'with' statement both > starts a database > transaction and acquires a thread lock: > > contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, > 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 > transaction并获取了线程的锁。 > > lock = threading.Lock() > with nested (db_transaction(db), lock) as (cursor, locked): > ... > > Finally, the closing(object) function returns object so that it can be > bound > to a variable, and calls object.close() at the end of the block. > > 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, > 然后在block的最后(with会自动)调用object.close()了。 > > import urllib, sys > from contextlib import closing > > with closing(urllib.urlopen('http://www.yahoo.com')) as f: > for line in f: > sys.stdout.write(line) > > > 8 PEP 343: The 'with' statement > > The 'with' statement clarifies code that previously would use > try...finally > blocks to ensure that clean-up code is executed. In this section, I'll > discuss > the statement as it will commonly be used. In the next section, I'll > examine the > implementation details and show how to write objects for use with this > statement. > > 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 > 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 > > The 'with' statement is a new control-flow structure whose basic structure > is: > > 'with' statement是一个新的流程控制结构,其基本的语法如下: > > > with expression [as variable]: > with-block > > The expression is evaluated, and it should result in an object that > supports the > context management protocol. This object may return a value that can > optionally > be bound to the name variable. (Note carefully that variable is not > assigned the > result of expression.) The object can then run set-up code before > with-block is > executed and some clean-up code is executed after the block is done, > even if the > block raised an exception. > > (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, > 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 > 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) > 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, > 即便是因为发生了异常,它也会执行清理代码。 > > To enable the statement in Python 2.5, you need to add the following > directive > to your module: > > 要在Python 2.5里面用with语句,你得在module里面加上下面这行: > > > from __future__ import with_statement > > The statement will always be enabled in Python 2.6. > 等到了Python 2.6,你就不用再这么麻烦了。 > > Some standard Python objects now support the context management protocol > and > can be used with the 'with' statement. File objects are one example: > > 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 > File对象就是一例: > > with open('/etc/passwd', 'r') as f: > for line in f: > print line > ... more processing code ... > > After this statement has executed, the file object in f will have been > automatically > closed, even if the 'for' loop raised an exception part-way through the > block. > > 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, > file对象f也会自动关闭。 > > The threading module's locks and condition variables also support the > 'with' statement: > > threading模块的lock和condition对象也支持with 语句 > (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): > > > lock = threading.Lock() > with lock: > # Critical section of code > ... > > The lock is acquired before the block is executed and always released > once the block > is complete. > > 执行block之前得先得到lock,然后执行完毕之后会释放锁。 > > The decimal module's contexts, which encapsulate the desired precision > and rounding > characteristics for computations, provide a context_manager() method > for getting a > context manager: > > decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, > 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 > (context是上下文的意思)将计算的精度和近似要求封装了起来 > (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): > > import decimal > > # Displays with default precision of 28 digits > v1 = decimal.Decimal('578') > print v1.sqrt() > > ctx = decimal.Context(prec=16) > #---------------------------------------- > # 根据shhgs的试验,ctx对象是没有context_manager()方法的, > # 你得 > # with ctx.get_manager() : > #---------------------------------------- > with ctx.context_manager(): > # All code in this block uses a precision of 16 digits. > # The original context is restored on exiting the block. > print v1.sqrt() > > > > 8.1 Writing Context Managers > Under the hood, the 'with' statement is fairly complicated. > Most people will only use 'with' in company with existing objects > and don't need to know these details, so you can skip the rest of > this section if you like. Authors of new objects will need to understand > the details of the underlying implementation and should keep reading. > > 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, > 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, > 那就得受累读下去了。 > > A high-level explanation of the context management protocol is: > > context management 接口的大致概括如下: > > The expression is evaluated and should result in an object called a > ``context manager''. The context manager must have __enter__() and > __exit__() methods. > > (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 > 这个context manager必须提供__enter__()和__exit__()方法。 > > The context manager's __enter__() method is called. > The value returned is assigned to VAR. > If no 'as VAR' clause is present, the value is simply discarded. > > 然后(with)再调用context manager的__enter__()方法。 > 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 > 如果没有'as VAR',这个值就丢了。 > > > The code in BLOCK is executed. > > 然后执行BLOCK。 > > If BLOCK raises an exception, the __exit__(type, value, traceback) is > called > with the exception details, the same values returned by sys.exc_info(). > The method's return value controls whether the exception is re-raised: > any false value re-raises the exception, and True will result in > suppressing it. > You'll only rarely want to suppress the exception, because if you do the > author > of the code containing the 'with' statement will never realize > anything went wrong. > > 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 > 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 > 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, > 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 > > If BLOCK didn't raise an exception, the __exit__() method is still called, > but type, value, and traceback are all None. > > 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, > traceback都是None。 > > Let's think through an example. I won't present detailed code but will > only > sketch the methods necessary for a database that supports transactions. > > 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 > 支持transaction地数据库所必须提供的方法。 > > (For people unfamiliar with database terminology: a set of changes to > the database > are grouped into a transaction. Transactions can be either committed, > meaning that > all the changes are written into the database, or rolled back, meaning > that the > changes are all discarded and the database is unchanged. See any > database textbook > for more information.) > > (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 > 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, > 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) > > Let's assume there's an object representing a database connection. > Our goal will be to let the user write code like this: > > 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: > > db_connection = DatabaseConnection() > with db_connection as cursor: > cursor.execute('insert into ...') > cursor.execute('delete from ...') > # ... more operations ... > > The transaction should be committed if the code in the block runs > flawlessly or > rolled back if there's an exception. Here's the basic interface for > DatabaseConnection > that I'll assume: > > 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 > 下面是我所预想的这个DatabaseConnection的基本接口。 > > > class DatabaseConnection: > # Database interface > def cursor (self): > "Returns a cursor object and starts a new transaction" > def commit (self): > "Commits current transaction" > def rollback (self): > "Rolls back current transaction" > > The __enter__() method is pretty easy, having only to start a new > transaction. > For this application the resulting cursor object would be a useful result, > so the method will return it. The user can then add as cursor to their > 'with' > statement to bind the cursor to a variable name. > > __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, > cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 > > class DatabaseConnection: > ... > def __enter__ (self): > # Code to start a new transaction > cursor = self.cursor() > return cursor > > The __exit__() method is the most complicated > because it's where most of the work has to be done. > The method has to check if an exception occurred. > If there was no exception, the transaction is committed. > The transaction is rolled back if there was an exception. > > __exit__()最烦了,因为绝大多数的工作都是在这里干的。 > 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 > > In the code below, execution will just fall off the end of the function, > returning the default value of None. None is false, so the exception will > be re-raised automatically. If you wished, you could be more explicit and > add a return statement at the marked location. > > 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, > 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 > > class DatabaseConnection: > ... > def __exit__ (self, type, value, tb): > if tb is None: > # No exception, so commit > self.commit() > else: > # Exception occurred, so rollback. > self.rollback() > # return False > > > > 8.2 The contextlib module > The new contextlib module provides some functions and a decorator that > are useful > for writing objects for use with the 'with' statement. > > 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 > > The decorator is called contextfactory, and lets you write a single > generator > function instead of defining a new class. The generator should yield > exactly one value. > The code up to the yield will be executed as the __enter__() method, > and the value yielded will be the method's return value that will get > bound to the > variable in the 'with' statement's as clause, if any. The code after > the yield will be > executed in the __exit__() method. Any exception raised in the block > will be raised > by the yield statement. > > 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 > 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, > yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 > 此外,yield还会把block里面的异常再抛出来。 > > Our database example from the previous section could be written using > this decorator as: > > 我们前面讲的数据库的例子可以这样改写: > > from contextlib import contextfactory > > @contextfactory > def db_transaction (connection): > cursor = connection.cursor() > try: > yield cursor > except: > connection.rollback() > raise > else: > connection.commit() > > db = DatabaseConnection() > with db_transaction(db) as cursor: > ... > > The contextlib module also has a nested(mgr1, mgr2, ...) function > that combines a number of context managers so you don't need to write > nested > 'with' statements. In this example, the single 'with' statement both > starts a database > transaction and acquires a thread lock: > > contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, > 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 > transaction并获取了线程的锁。 > > lock = threading.Lock() > with nested (db_transaction(db), lock) as (cursor, locked): > ... > > Finally, the closing(object) function returns object so that it can be > bound > to a variable, and calls object.close() at the end of the block. > > 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, > 然后在block的最后(with会自动)调用object.close()了。 > > import urllib, sys > from contextlib import closing > > with closing(urllib.urlopen('http://www.yahoo.com')) as f: > for line in f: > sys.stdout.write(line) > > > > > > > --------------------------------------------------------------------------------------------------------- > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- ※※※※※※※※※※※※※※※※※※※※※※※※ My blog: http://blog.donews.com/ygao Forum http://groups.google.com/group/python_study ※※※※※※※※※※※※※※※※※※※※※※※※ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060624/9b7d09b8/attachment-0001.html
2006年06月25日 星期日 14:30
On 6/24/06, shhgs <shhgs.efhilt at gmail.com> wrote: > > Python 2.5的beta 1出来了。每次拿到新版本的时候,总是先看what's new。这次看with的时候,发现与先前PEP > 310的有很大不同。2.5最终实现的是PEP343。 > > 下面是我翻译的what's new。第一次接触with,谬误指出请大家包涵。 有些长,还没来得及读,先做个记号。:) --------------------------------------------------------------------------------------------------------- > 8 PEP 343: The 'with' statement > > The 'with' statement clarifies code that previously would use > try...finally > blocks to ensure that clean-up code is executed. In this section, I'll > discuss > the statement as it will commonly be used. In the next section, I'll > examine the > implementation details and show how to write objects for use with this > statement. > > 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 > 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 > > The 'with' statement is a new control-flow structure whose basic structure > is: > > 'with' statement是一个新的流程控制结构,其基本的语法如下: > > > with expression [as variable]: > with-block > > The expression is evaluated, and it should result in an object that > supports the > context management protocol. This object may return a value that can > optionally > be bound to the name variable. (Note carefully that variable is not > assigned the > result of expression.) The object can then run set-up code before > with-block is > executed and some clean-up code is executed after the block is done, > even if the > block raised an exception. > > (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, > 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 > 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) > 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, > 即便是因为发生了异常,它也会执行清理代码。 > > To enable the statement in Python 2.5, you need to add the following > directive > to your module: > > 要在Python 2.5里面用with语句,你得在module里面加上下面这行: > > > from __future__ import with_statement > > The statement will always be enabled in Python 2.6. > 等到了Python 2.6,你就不用再这么麻烦了。 > > Some standard Python objects now support the context management protocol > and > can be used with the 'with' statement. File objects are one example: > > 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 > File对象就是一例: > > with open('/etc/passwd', 'r') as f: > for line in f: > print line > ... more processing code ... > > After this statement has executed, the file object in f will have been > automatically > closed, even if the 'for' loop raised an exception part-way through the > block. > > 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, > file对象f也会自动关闭。 > > The threading module's locks and condition variables also support the > 'with' statement: > > threading模块的lock和condition对象也支持with 语句 > (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): > > > lock = threading.Lock() > with lock: > # Critical section of code > ... > > The lock is acquired before the block is executed and always released > once the block > is complete. > > 执行block之前得先得到lock,然后执行完毕之后会释放锁。 > > The decimal module's contexts, which encapsulate the desired precision > and rounding > characteristics for computations, provide a context_manager() method > for getting a > context manager: > > decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, > 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 > (context是上下文的意思)将计算的精度和近似要求封装了起来 > (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): > > import decimal > > # Displays with default precision of 28 digits > v1 = decimal.Decimal('578') > print v1.sqrt() > > ctx = decimal.Context(prec=16) > #---------------------------------------- > # 根据shhgs的试验,ctx对象是没有context_manager()方法的, > # 你得 > # with ctx.get_manager() : > #---------------------------------------- > with ctx.context_manager(): > # All code in this block uses a precision of 16 digits. > # The original context is restored on exiting the block. > print v1.sqrt() > > > > 8.1 Writing Context Managers > Under the hood, the 'with' statement is fairly complicated. > Most people will only use 'with' in company with existing objects > and don't need to know these details, so you can skip the rest of > this section if you like. Authors of new objects will need to understand > the details of the underlying implementation and should keep reading. > > 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, > 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, > 那就得受累读下去了。 > > A high-level explanation of the context management protocol is: > > context management 接口的大致概括如下: > > The expression is evaluated and should result in an object called a > ``context manager''. The context manager must have __enter__() and > __exit__() methods. > > (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 > 这个context manager必须提供__enter__()和__exit__()方法。 > > The context manager's __enter__() method is called. > The value returned is assigned to VAR. > If no 'as VAR' clause is present, the value is simply discarded. > > 然后(with)再调用context manager的__enter__()方法。 > 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 > 如果没有'as VAR',这个值就丢了。 > > > The code in BLOCK is executed. > > 然后执行BLOCK。 > > If BLOCK raises an exception, the __exit__(type, value, traceback) is > called > with the exception details, the same values returned by sys.exc_info(). > The method's return value controls whether the exception is re-raised: > any false value re-raises the exception, and True will result in > suppressing it. > You'll only rarely want to suppress the exception, because if you do the > author > of the code containing the 'with' statement will never realize > anything went wrong. > > 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 > 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 > 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, > 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 > > If BLOCK didn't raise an exception, the __exit__() method is still called, > but type, value, and traceback are all None. > > 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, > traceback都是None。 > > Let's think through an example. I won't present detailed code but will > only > sketch the methods necessary for a database that supports transactions. > > 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 > 支持transaction地数据库所必须提供的方法。 > > (For people unfamiliar with database terminology: a set of changes to > the database > are grouped into a transaction. Transactions can be either committed, > meaning that > all the changes are written into the database, or rolled back, meaning > that the > changes are all discarded and the database is unchanged. See any > database textbook > for more information.) > > (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 > 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, > 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) > > Let's assume there's an object representing a database connection. > Our goal will be to let the user write code like this: > > 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: > > db_connection = DatabaseConnection() > with db_connection as cursor: > cursor.execute('insert into ...') > cursor.execute('delete from ...') > # ... more operations ... > > The transaction should be committed if the code in the block runs > flawlessly or > rolled back if there's an exception. Here's the basic interface for > DatabaseConnection > that I'll assume: > > 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 > 下面是我所预想的这个DatabaseConnection的基本接口。 > > > class DatabaseConnection: > # Database interface > def cursor (self): > "Returns a cursor object and starts a new transaction" > def commit (self): > "Commits current transaction" > def rollback (self): > "Rolls back current transaction" > > The __enter__() method is pretty easy, having only to start a new > transaction. > For this application the resulting cursor object would be a useful result, > so the method will return it. The user can then add as cursor to their > 'with' > statement to bind the cursor to a variable name. > > __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, > cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 > > class DatabaseConnection: > ... > def __enter__ (self): > # Code to start a new transaction > cursor = self.cursor() > return cursor > > The __exit__() method is the most complicated > because it's where most of the work has to be done. > The method has to check if an exception occurred. > If there was no exception, the transaction is committed. > The transaction is rolled back if there was an exception. > > __exit__()最烦了,因为绝大多数的工作都是在这里干的。 > 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 > > In the code below, execution will just fall off the end of the function, > returning the default value of None. None is false, so the exception will > be re-raised automatically. If you wished, you could be more explicit and > add a return statement at the marked location. > > 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, > 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 > > class DatabaseConnection: > ... > def __exit__ (self, type, value, tb): > if tb is None: > # No exception, so commit > self.commit() > else: > # Exception occurred, so rollback. > self.rollback() > # return False > > > > 8.2 The contextlib module > The new contextlib module provides some functions and a decorator that > are useful > for writing objects for use with the 'with' statement. > > 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 > > The decorator is called contextfactory, and lets you write a single > generator > function instead of defining a new class. The generator should yield > exactly one value. > The code up to the yield will be executed as the __enter__() method, > and the value yielded will be the method's return value that will get > bound to the > variable in the 'with' statement's as clause, if any. The code after > the yield will be > executed in the __exit__() method. Any exception raised in the block > will be raised > by the yield statement. > > 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 > 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, > yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 > 此外,yield还会把block里面的异常再抛出来。 > > Our database example from the previous section could be written using > this decorator as: > > 我们前面讲的数据库的例子可以这样改写: > > from contextlib import contextfactory > > @contextfactory > def db_transaction (connection): > cursor = connection.cursor() > try: > yield cursor > except: > connection.rollback() > raise > else: > connection.commit() > > db = DatabaseConnection() > with db_transaction(db) as cursor: > ... > > The contextlib module also has a nested(mgr1, mgr2, ...) function > that combines a number of context managers so you don't need to write > nested > 'with' statements. In this example, the single 'with' statement both > starts a database > transaction and acquires a thread lock: > > contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, > 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 > transaction并获取了线程的锁。 > > lock = threading.Lock() > with nested (db_transaction(db), lock) as (cursor, locked): > ... > > Finally, the closing(object) function returns object so that it can be > bound > to a variable, and calls object.close() at the end of the block. > > 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, > 然后在block的最后(with会自动)调用object.close()了。 > > import urllib, sys > from contextlib import closing > > with closing(urllib.urlopen('http://www.yahoo.com')) as f: > for line in f: > sys.stdout.write(line) > > > 8 PEP 343: The 'with' statement > > The 'with' statement clarifies code that previously would use > try...finally > blocks to ensure that clean-up code is executed. In this section, I'll > discuss > the statement as it will commonly be used. In the next section, I'll > examine the > implementation details and show how to write objects for use with this > statement. > > 'with' 语句的功能是执行清理代码,它要比了我们过去用的 try ... finally清楚得多。 > 本章我会先探讨它是怎么用的,然后再研究其实现的细节,并且写一个能给 with 语句用的对象。 > > The 'with' statement is a new control-flow structure whose basic structure > is: > > 'with' statement是一个新的流程控制结构,其基本的语法如下: > > > with expression [as variable]: > with-block > > The expression is evaluated, and it should result in an object that > supports the > context management protocol. This object may return a value that can > optionally > be bound to the name variable. (Note carefully that variable is not > assigned the > result of expression.) The object can then run set-up code before > with-block is > executed and some clean-up code is executed after the block is done, > even if the > block raised an exception. > > (with语句会)先计算表达式,得到一个实现context management接口(这里pep作者使用了protocol, > 而不是大家都比较熟悉的interface的术语)的对象。这个对象可能会返回一个值,而你则可以选择 > 是不是把这个值绑定到变量名("name variable")上。(请注意,这不是将表达式到值赋值给变量。) > 然后对象先运行预备代码("set-up code"),再执行with-block,最后在离开block的时候, > 即便是因为发生了异常,它也会执行清理代码。 > > To enable the statement in Python 2.5, you need to add the following > directive > to your module: > > 要在Python 2.5里面用with语句,你得在module里面加上下面这行: > > > from __future__ import with_statement > > The statement will always be enabled in Python 2.6. > 等到了Python 2.6,你就不用再这么麻烦了。 > > Some standard Python objects now support the context management protocol > and > can be used with the 'with' statement. File objects are one example: > > 有些Python对象已经实现了context management接口,因此现在就可以用在with语句里里。 > File对象就是一例: > > with open('/etc/passwd', 'r') as f: > for line in f: > print line > ... more processing code ... > > After this statement has executed, the file object in f will have been > automatically > closed, even if the 'for' loop raised an exception part-way through the > block. > > 只要这个语句运行结束,即便是因为 for 循环运行到一半的时候抛出了异常, > file对象f也会自动关闭。 > > The threading module's locks and condition variables also support the > 'with' statement: > > threading模块的lock和condition对象也支持with 语句 > (据shhgs得理解,这里的locks表示threading里面的所有lock,如Lock, RLock都已经支持with了): > > > lock = threading.Lock() > with lock: > # Critical section of code > ... > > The lock is acquired before the block is executed and always released > once the block > is complete. > > 执行block之前得先得到lock,然后执行完毕之后会释放锁。 > > The decimal module's contexts, which encapsulate the desired precision > and rounding > characteristics for computations, provide a context_manager() method > for getting a > context manager: > > decimal模块提供了一个能返回context对象的context_manager()方法(请注意看注释, > 至少Py2.5b1里面是没有这个方法,你得用get_manager() ),这个context对象 > (context是上下文的意思)将计算的精度和近似要求封装了起来 > (什么叫上下文?这才叫上下文!Perl的那个上下文根本就是假冒伪劣): > > import decimal > > # Displays with default precision of 28 digits > v1 = decimal.Decimal('578') > print v1.sqrt() > > ctx = decimal.Context(prec=16) > #---------------------------------------- > # 根据shhgs的试验,ctx对象是没有context_manager()方法的, > # 你得 > # with ctx.get_manager() : > #---------------------------------------- > with ctx.context_manager(): > # All code in this block uses a precision of 16 digits. > # The original context is restored on exiting the block. > print v1.sqrt() > > > > 8.1 Writing Context Managers > Under the hood, the 'with' statement is fairly complicated. > Most people will only use 'with' in company with existing objects > and don't need to know these details, so you can skip the rest of > this section if you like. Authors of new objects will need to understand > the details of the underlying implementation and should keep reading. > > 'with'语句背后的实现是相当复杂的。绝大多数人只需要知道怎样把现成的对象用到with里面, > 所以只要你觉得合适,完全可以跳过下面这段。但是如果你要写能给with用的对象, > 那就得受累读下去了。 > > A high-level explanation of the context management protocol is: > > context management 接口的大致概括如下: > > The expression is evaluated and should result in an object called a > ``context manager''. The context manager must have __enter__() and > __exit__() methods. > > (with语句先)计算表达式,拿到一个被成为context manager(上下文管理器)的对象。 > 这个context manager必须提供__enter__()和__exit__()方法。 > > The context manager's __enter__() method is called. > The value returned is assigned to VAR. > If no 'as VAR' clause is present, the value is simply discarded. > > 然后(with)再调用context manager的__enter__()方法。 > 如果语句里面还有'as VAR',那么它会顺手把(__enter__()所返回的)值赋给VAR。 > 如果没有'as VAR',这个值就丢了。 > > > The code in BLOCK is executed. > > 然后执行BLOCK。 > > If BLOCK raises an exception, the __exit__(type, value, traceback) is > called > with the exception details, the same values returned by sys.exc_info(). > The method's return value controls whether the exception is re-raised: > any false value re-raises the exception, and True will result in > suppressing it. > You'll only rarely want to suppress the exception, because if you do the > author > of the code containing the 'with' statement will never realize > anything went wrong. > > 如果BLOCK引发了异常,那么它会根据这个异常去调用__exit__(type, value, traceback)。 > 这个方法所返回的值同sys.exc_info()方法是相同的。这个返回值会告诉系统是不是再把 > 异常往上抛: false值表示再抛,True表示把它压下来。一般来说你不太需要去压制异常, > 因为要是你在这里把异常压了下来,那些写with语句的人就永远也不知道这里还发生过异常了。 > > If BLOCK didn't raise an exception, the __exit__() method is still called, > but type, value, and traceback are all None. > > 如果BLOCK没有引发异常,with还是会调用__exit__()方法,只是这时type, value, > traceback都是None。 > > Let's think through an example. I won't present detailed code but will > only > sketch the methods necessary for a database that supports transactions. > > 我们举一个例子。我不会给具体的代码,只是大致地划拉一下一个 > 支持transaction地数据库所必须提供的方法。 > > (For people unfamiliar with database terminology: a set of changes to > the database > are grouped into a transaction. Transactions can be either committed, > meaning that > all the changes are written into the database, or rolled back, meaning > that the > changes are all discarded and the database is unchanged. See any > database textbook > for more information.) > > (这段话是为那些不熟悉数据库的朋友准备的: 所谓transaction就是把一组对数据库的修改捆绑起来。 > 你可以commit一个transaction,也就是说把这些修改全部写入数据库;也可以roll back, > 也就是说把这些修改全都扔掉。随便找本数据库的书都会比我这里讲的详细。) > > Let's assume there's an object representing a database connection. > Our goal will be to let the user write code like this: > > 架设这里有一个表示database connection的对象。我们的目标是要让用户能这样写代码: > > db_connection = DatabaseConnection() > with db_connection as cursor: > cursor.execute('insert into ...') > cursor.execute('delete from ...') > # ... more operations ... > > The transaction should be committed if the code in the block runs > flawlessly or > rolled back if there's an exception. Here's the basic interface for > DatabaseConnection > that I'll assume: > > 如果block运行无误的话,这个transaction就算是commit了。只要有异常,我们就roll back。 > 下面是我所预想的这个DatabaseConnection的基本接口。 > > > class DatabaseConnection: > # Database interface > def cursor (self): > "Returns a cursor object and starts a new transaction" > def commit (self): > "Commits current transaction" > def rollback (self): > "Rolls back current transaction" > > The __enter__() method is pretty easy, having only to start a new > transaction. > For this application the resulting cursor object would be a useful result, > so the method will return it. The user can then add as cursor to their > 'with' > statement to bind the cursor to a variable name. > > __enter__()方法相当简单,只需要启动一个transaction就行了。对application来说, > cursor 对象会用得着,所以 __enter__() 得把它返回出去。这样用户就能在with语句里用cursor了。 > > class DatabaseConnection: > ... > def __enter__ (self): > # Code to start a new transaction > cursor = self.cursor() > return cursor > > The __exit__() method is the most complicated > because it's where most of the work has to be done. > The method has to check if an exception occurred. > If there was no exception, the transaction is committed. > The transaction is rolled back if there was an exception. > > __exit__()最烦了,因为绝大多数的工作都是在这里干的。 > 它得检查是不是有异常。如果没有,它得负责commit,如果有它得roll back。 > > In the code below, execution will just fall off the end of the function, > returning the default value of None. None is false, so the exception will > be re-raised automatically. If you wished, you could be more explicit and > add a return statement at the marked location. > > 在下面这段代码里,真正重要的东西是函数的最后部分,返回一个None。None是false值, > 所以异常会被重新抛出来。如果你想明确一下,可以在我注释的地方加一个return语句。 > > class DatabaseConnection: > ... > def __exit__ (self, type, value, tb): > if tb is None: > # No exception, so commit > self.commit() > else: > # Exception occurred, so rollback. > self.rollback() > # return False > > > > 8.2 The contextlib module > The new contextlib module provides some functions and a decorator that > are useful > for writing objects for use with the 'with' statement. > > 2.5新加的contextlib模块提供了一些用于编写供'with'语句使用的对象的方法和decorator。 > > The decorator is called contextfactory, and lets you write a single > generator > function instead of defining a new class. The generator should yield > exactly one value. > The code up to the yield will be executed as the __enter__() method, > and the value yielded will be the method's return value that will get > bound to the > variable in the 'with' statement's as clause, if any. The code after > the yield will be > executed in the __exit__() method. Any exception raised in the block > will be raised > by the yield statement. > > 这个decorotor被称为contextfactory。有了它,你可以只写一个generator方法 > 而不用去定义一个新的类了。这个generator只能yield一个值。yield之前的代码表示__enter__()方法, > yield出来的值会绑定到 with 语句的 as 子句的变量,如果有的话。yield后面的代码是__exit__()要执行的。 > 此外,yield还会把block里面的异常再抛出来。 > > Our database example from the previous section could be written using > this decorator as: > > 我们前面讲的数据库的例子可以这样改写: > > from contextlib import contextfactory > > @contextfactory > def db_transaction (connection): > cursor = connection.cursor() > try: > yield cursor > except: > connection.rollback() > raise > else: > connection.commit() > > db = DatabaseConnection() > with db_transaction(db) as cursor: > ... > > The contextlib module also has a nested(mgr1, mgr2, ...) function > that combines a number of context managers so you don't need to write > nested > 'with' statements. In this example, the single 'with' statement both > starts a database > transaction and acquires a thread lock: > > contextlib模块还提供了一个能把多个context manager捆绑起来的nested(mgr1, mgr2, ... )函数, > 这样你就不用把with语句嵌套起来了。下面这个例子里,我们只用一次with就启动了数据库的 > transaction并获取了线程的锁。 > > lock = threading.Lock() > with nested (db_transaction(db), lock) as (cursor, locked): > ... > > Finally, the closing(object) function returns object so that it can be > bound > to a variable, and calls object.close() at the end of the block. > > 最后,(contextfactory的)closing(object)函数会返回一个对象,这样你就可以把它绑定到变量上, > 然后在block的最后(with会自动)调用object.close()了。 > > import urllib, sys > from contextlib import closing > > with closing(urllib.urlopen('http://www.yahoo.com')) as f: > for line in f: > sys.stdout.write(line) > > > > > > > --------------------------------------------------------------------------------------------------------- > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- Best Regards Shixin Zeng -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060625/7a62c415/attachment.html
2006年06月26日 星期一 07:41
赞一个先,谢谢!
2006年06月26日 星期一 17:25
对了,这是不是相当于引入了一个新关键字with? 原有的代码里如果用了这个名字是不是就不兼容了? 虽然感觉会带来不少方便,但是为此引入一条新的语句,也是增加了语言的复杂度啊。 你之前说到带返回值的yield和with可能是2.5的亮点,相比起来我对前者更有兴趣一些,虽然对于具体怎么使用还不是很有概念。 On 6/24/06, shhgs <shhgs.efhilt at gmail.com> wrote: > > Python 2.5的beta 1出来了。每次拿到新版本的时候,总是先看what's new。这次看with的时候,发现与先前PEP > 310的有很大不同。2.5最终实现的是PEP343。 > > 下面是我翻译的what's new。第一次接触with,谬误指出请大家包涵。 > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060626/f2427afb/attachment.htm
2006年06月26日 星期一 19:13
有了带返回值的yield后,stackless基本上就可以退出历史舞台了么 :) -- http://codeplayer.blogbus.com/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060626/115d0cf8/attachment.htm
2006年06月27日 星期二 04:51
yield确实是个亮点,但同时也是双刃剑。用得不好,又是一个goto。 On 6/26/06, yi huang <yi.codeplayer at gmail.com> wrote: > 有了带返回值的yield后,stackless基本上就可以退出历史舞台了么 :) > > > -- > http://codeplayer.blogbus.com/ > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to > python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to > python-chinese-request at lists.python.cn > Detail Info: > http://python.cn/mailman/listinfo/python-chinese > >
2006年06月27日 星期二 11:49
But, I love goto... Best Regards, Zachary Wu (Îâ°~ÀÚ) Software Engineer, Enterprise Content Management FVT, IBM China Software Development Lab Tel: +86 10 82782244-3235. Fax: 82782244-2886 Tie Line: 915-2244-3235 Internet: xiaoleiw at cn.ibm.com Notes ID: Xiao Lei Wu/China/Contr/IBM at IBMCN Address: 8/F, Block A, Power Creative Building, No.1, East Road, Shang Di, Beijing 100085, P.R. China python-chinese-bounces at lists.python.cn дÓÚ 2006-06-27 04:51:22: > yieldȷʵÊǸöÁÁµã£¬µ«Í¬Ê±Ò²ÊÇË«Èн£¡£Óõò»ºÃ£¬ÓÖÊÇÒ»¸ögoto¡£ > > > On 6/26/06, yi huang <yi.codeplayer at gmail.com> wrote: > > ÓÐÁË´ø·µ»ØÖµµÄyieldºó£¬stackless»ù±¾ÉϾͿÉÒÔÍ˳öÀúÊ·Îę̀ÁËô :) > > > > > > -- > > http://codeplayer.blogbus.com/ > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to > > python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to > > python-chinese-request at lists.python.cn > > Detail Info: > > http://python.cn/mailman/listinfo/python-chinese > > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/318929c9/attachment.htm
2006年06月27日 星期二 12:41
被Knuth教导了这么多年,很多人怕是和我一样已经不会用goto了... On 6/27/06, shhgs <shhgs.efhilt at gmail.com> wrote: > > yield确实是个亮点,但同时也是双刃剑。用得不好,又是一个goto。 > > > On 6/26/06, yi huang <yi.codeplayer at gmail.com> wrote: > > 有了带返回值的yield后,stackless基本上就可以退出历史舞台了么 :) > > > > > > -- > > http://codeplayer.blogbus.com/ > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to > > python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to > > python-chinese-request at lists.python.cn > > Detail Info: > > http://python.cn/mailman/listinfo/python-chinese > > > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/60a9c193/attachment.htm
2006年06月27日 星期二 13:05
在 06-6-27,shhgs<shhgs.efhilt at gmail.com> 写道: > yield确实是个亮点,但同时也是双刃剑。用得不好,又是一个goto。 > shhgs能给详细解释下yield的语法么? -- 云电清华同方小民工
2006年06月27日 星期二 15:00
On 6/27/06, swordsp <sparas2006 at gmail.com> wrote: > > 被Knuth教导了这么多年,很多人怕是和我一样已经不会用goto了... > goto有什么不会用的?不就是汇编里的jmp么。 另外,应该是dijkstra说的goto不好吧,怎么是knuth了? -- Best Regards, Leo Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/7199623b/attachment.html
2006年06月27日 星期二 19:07
coroutine和goto太不一样了,和setjmp/longjmp倒是挺象。 -- http://codeplayer.blogbus.com/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/8ceefd2f/attachment.html
2006年06月27日 星期二 21:16
记混了...《Go To Statement Considered Harmful》是Dijkstra的,Knuth那篇《Structured Programming with Goto Statements》其实是有一点为Goto辩护的意思。 goto的"语法"当然不会忘,不过"用法"其实已经不记得了。 要是现在突然不准我写循环、函数这样的结构,只准用if和goto组织程序流程,我肯定会疯掉的,毕竟结构化编程的思想已经浸入了血液里。 On 6/27/06, Leo Jay <python.leojay at gmail.com> wrote: > > On 6/27/06, swordsp <sparas2006 at gmail.com> wrote: > > > > 被Knuth教导了这么多年,很多人怕是和我一样已经不会用goto了... > > > > goto有什么不会用的?不就是汇编里的jmp么。 > 另外,应该是dijkstra说的goto不好吧,怎么是knuth了? > > > -- > Best Regards, > Leo Jay > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/f141cbf2/attachment.html
2006年06月27日 星期二 21:23
我的理解是这样的: 结构化编程的目的就是把程序划分成小的模块,将复杂度降维,用循环和函数等结构代替goto正是为了使得模块之间边界清晰。 yield使得一个函数可能有多个入口多个出口,一定程度上破坏了这种模块的封闭性,增加了模块间的耦合度,如果滥用的话就会带来如同goto一样混乱的流程控制。 On 6/27/06, yi huang <yi.codeplayer at gmail.com> wrote: > > coroutine和goto太不一样了,和setjmp/longjmp倒是挺象。 > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/0318db72/attachment.html
2006年06月27日 星期二 22:16
yield 和 goto怎么会混为一谈: goto是流程控制中的任意性。 yield不是用来控制流程的,是特性。 -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060627/253840ed/attachment.html
2006年06月28日 星期三 06:41
就是这个意思! On 6/27/06, swordsp <sparas2006 at gmail.com> wrote: > 我的理解是这样的: > 结构化编程的目的就是把程序划分成小的模块,将复杂度降维,用循环和函数等结构代替goto正是为了使得模块之间边界清晰。 > yield使得一个函数可能有多个入口多个出口,一定程度上破坏了这种模块的封闭性,增加了模块间的耦合度,如果滥用的话就会带来如同goto一样混乱的流程控制。 > > On 6/27/06, yi huang <yi.codeplayer at gmail.com> wrote: > > > > coroutine和goto太不一样了,和setjmp/longjmp倒是挺象。 > > > > > > > > > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to > python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to > python-chinese-request at lists.python.cn > Detail Info: > http://python.cn/mailman/listinfo/python-chinese > >
2006年06月28日 星期三 11:11
哪位能详细讲讲yield的用法呀? -- 云电清华同方小民工
2006年06月28日 星期三 11:16
http://qingfeng.ushared.com/blog/?p=292 On 6/28/06, 笨笨狗 <chen.ruijie at gmail.com> wrote: > 哪位能详细讲讲yield的用法呀? > > -- > 云电清华同方小民工 > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- Page Talk:http://www.51pipi.com/ Blog:http://qingfeng.ushared.com/blog/
2006年06月28日 星期三 11:26
在 06-6-28,清风<paradise.qingfeng at gmail.com> 写道: > http://qingfeng.ushared.com/blog/?p=292 > 3Q,去看看,不明白了再回来问 -- 云电清华同方小民工
Zeuux © 2025
京ICP备05028076号