用Python编辑一个上吊猜单词词的程序,必须使用Function

当前位置: >
> 在Windows环境下用Editplus打造一个Python编辑调试环境Python有很多集成开发
在Windows环境下用Editplus打造一个Python编辑调试环境Python有很多集成开发
qhl717 & at
在Windows环境下用Editplus打造一个Python编辑调试环境
  Python有很多集成开发工具,商业的有
Boa等,还有
Python自带的集成环境
windows下还有
Pythonwin等。本文
利用一个很流行的功能也非常强大的文本编辑软件
Editplus,改造成一个能够很好的支持
Python编辑,浏览,运行及调试的开发环境,并且具备语法加亮,自动完成,自动缩进,新建
python文件模板等功能支持。
epp211.rar
Editplus能够运行
python程序,首先打开
tools-&Preferences对话框,在
User tools里新建一个
group,名字叫
python,在
python group里新建一个工具也起名为
python,分别在
Menu text:填入
python,在
Command:填入
python的安装路径,
Argument:填入
$(FileName),
Initial Directory:填入
$(FileDir)。完成这一步的结果如下图(
  这样在
Editplus里打开一个
python文件,在
tools菜单下就会有一个
python选项,直接单击就可以运行
python程序了,也可以利用快捷键(
1),根据设置用户工具的个数,这个快捷键可能有所不同。如下图(
  在此处实现下面的一个功能:就是当程序出错的时候,
python解释器会给出类似如下的提示信息:
  ---------- python ----------
  File "test.py", line 6
  print 'a
  SyntaxError: EOL while scanning single-quoted string
  Output completed (1 sec consumed) - Normal Termination
  此时,可以根据提示的行号到文本中去找错误的地方,而不能够象其他的编译器一样直接双击错误的提示,将光标直接移动到错误行。此时如果直接双击某行,则会出现找不到某文件的错误。此处,可以利用
Editplus的
Output Pattern的实现这个功能。具体做法如下,在图(
Capture Output选项前的复选框要选上,然后打开
Output Pattern按钮,在
Output Pattern对话框中,首先取消
Use default output pattern选项前的复选框,在
Regular expression栏里填入正则表达式如下:
  File "(.+)", line ([0-9]+)
  File Name栏里选择
Tagged expression 1,
  Line栏里选择
Tagged expression 2,
  Column栏里为
  结果如图(
  然后直接双击错误提示信息行
  File "test.py", line 6
  光标就会直接跳到第六行,非常的方便,尤其是当多个文件互相调用的时候,这种方法可以方便打开文件找到错误的位置。
为了实现语法加亮和自动完成功能,必须下载两个文件,下载地址为
pythonfiles.zip
  解压到
editplus的安装目录下。压缩包有三个文件,此处我们用到两个,
python.acp文件和
python_extd.stx文件。
Acp文件是自动完成文件,
stx文件是语法加亮文件。加载方法如下:
  tools-&preferences-&Setting & syntax下,首先新建一个文件类型,命名为
python,扩展名(
file extensions)栏里填入
syntax file栏里找到刚才下载的
python_extd.stx文件,在
Auto completion栏里找到
python.acp文件,在
Function Pattern栏里填入:
  [ \t]*def[ \t].+:
  这样就可以通过
F11快捷键直接显示出
python文件中的函数列表。设置完成如下图(
  这时打开一个
python文件,就可以看到有语法加亮了。
editplus自动识别冒号然后直接缩进,并且如何修改缩进的长度:在图(
4)中,可以看到一个
Tab/Indent标签,打开他可以看到
Indent的选项,分别填入自己习惯的距离。
Insert spaces instead of tab和
Enable auto indent。然后在
Auto Indent open里填入一个冒号“
:”。完成设置以后如下图(
  其他的设置也可以根据类似的设置进行。
  3.还有一点很方便的是,可以通过建立一个
python文件的模板,来快速新建一个
python文件。首先建立一个名为
template.py的文件,内容自定,这里假设如下:
  ―――――――――――――――――――――
  Usage:
  ―――――――――――――――――――――
  保存,将
template.py文件放到
editplus安装目录下。
  Tools-&preferences-&templates
  打开模板设置对话框,首先添加一个名为
python的模板,把
file path设置到刚才建立的
template.py文件上。配置结果如图(
load按钮。完成。这样在
file-&New-&下就会有一个
python模板,直接可以方便的建立一个
python文件。
editplus-python.pdf
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&湘教QS2-164&&增值电信业务经营许可证湘B2-已经不记得是何时知道有pagerank这个东西了,好象就是上google时,看到google所做的关于它的工具条的宣传。只要你安装了google的工具条,除了搜索、阻挡弹出窗口外,就是可以看到正在浏览网页的pagerank。我也安装过,但那时我使用MyIE(后来改名了),google的工具条看不到,因此就又给删掉了。
后来看到别人的介绍说是可以在网页上加入我的pagerank(网页已经不记得了,不过搜索google你应该可以找到这个网站,它会给你一段代码可以放到你的主页上去,这样就可以看到了。我也试着放到我的Blog,但一方面pagerank太低,另一方面也不好看,再就是觉得没用就去掉了。
现在我常用的浏览器软件就是Firefox了。我还曾经一直因为它不象MyIE一样方便而不太使用,直到1.0出来,再加上看到 Keso 写的他常用的扩展(这篇文章很多地方都有,很容易搜到),于是装了不少插件,终于象MyIE一样方便了。而且有些地方已经超出我的想象。(顺便说一句,上新出了一种增强的中文版本,预装了不少插件,而且全部是中文化,这样很多插件在安装软件就可以使用了,不用再自已找了,很方便。不过,因为我已经用上了Firefox英文版,插件装了不少,再加上用英文版也挺习惯,就没试这,有兴趣的可以试一试)。其中我的Firefox上还装了一个可以看pagerank的插件,可以方便地看到每个浏览网页的pagerank。
前几天上网还发现一个Blog,作者提供了一个页面把现今几种对Blog进行量化的工具作成一个简单的表单,可以查询某个网址的情况,象反向链接,排名,其中就有google的pagerank。
对了,我现在的pagerank是4了。不管是在Firefox中,还是用上面的表格查询都是一样的。当然pagerank是变化的,我会努力写好Blog的。
— limodou @ 4:45 pm
Static methods and class methods
The new descriptor API(记得吗?有专门的文章介绍descriptor) makes it possible to add static methods and class methods. Static methods are easy to describe: they behave pretty much like static methods in C++ or Java(python中的静态方法同C++或Java中的静态方法很象). Here’s an example:
def foo(x, y):
print “staticmethod”, x, y
foo = staticmethod(foo)
C.foo(1, 2)c = C()c.foo(1, 2)
Both the call C.foo(1, 2) and the call c.foo(1, 2) call foo() with two arguments, and print “staticmethod 1 2″. No “self” is declared in the definition of foo()(在静态方法中不需要定义self参数), and no instance is required in the call(不需要使用实例来调用静态方法). If an instance is used, it is only used to find the class that defines the static method(如果给出实例,将用来查找对应的类). This works for classic and new classes!(这对classic和net-style class都一样)
The line “foo = staticmethod(foo)” in the class statement is the crucial element(使一个方法成为类方法需要在类中使用这样的语法,很重要。在2.4中可以使用decorator来实现): this makes foo() a static method. The built-in staticmethod() wraps its function argument in a special kind of descriptor whose __get__() method returns the original function unchanged(内置staticmethod()把传入的函数用特殊的descriptor进行封装,这个descriptor的__get__()返回原始的函数).
More on __get__ methods: in
2.2, the magic of binding methods to instances (even for classic classes!) is done through the __get__ method of the object found in the class. The __get__ method for regular function objects returns a the __get__ method for staticfunction objects returns the underlying function. If a class attribute has no __get__ method, it is never bound to an instance, or in other words there’s a default __get__ operation that returns
this is how simple class variables (for example numerical values) are handled.
这里是说所有特殊的处理都是通过对象中的__get__方法来实现的。类属性分为函数和变量。当一个函数在一个类中定义时,这个函数被处理为一个descriptor,这样,它就有__get__方法。对于一般类方法和静态方法的descriptor不同,因此会返回不同的函数。而对于其它的类变量,如果没有__get__方法,则直接返回这个对象。这样就说明,在定义类方法和变量时,Python会自动加入descriptor的处理。原来在看关于descriptor的文章时,看到类的方法可以用descriptor来实现,当然不太理解,现在想一想都是Python自动完成的。
Class methods use a similar pattern to declare methods that receive an implicit first argument that is the class for which they are invoked(类方法与静态方法的声明方式相似,不过,第一个参数为类对象。而静态方法不需要为实例对象或类对象). This has no C++ or Java equivalent(在C++或Java中没有对应的东西), and is not quite the same as what class methods are in Smalltalk(与Smalltalk中的类方法很不一样,没学过), but may serve a similar purpose. (Python also has real metaclasses, and perhaps methods defined in a metaclass have more right to the name “class method”; but I expect that most programmers won’t be using metaclasses.) Here’s an example:
def foo(cls, y):
print “classmethod”, cls, y
foo = classmethod(foo)
C.foo(1)c = C()c.foo(1)
Both the call C.foo(1) and the call c.foo(1) end up calling foo() with two arguments(使用类对象或实例对象来调用类方法最终是一样的,同静态类方法), and print “classmethod __main__.C 1″. The first argument of foo() is implied(第一个参数是隐含的), and it is the class(是类), even if the method was invoked via an instance. Now let’s continue the example:
class D(C):
D.foo(1)d = D()d.foo(1)
This prints “classmethod __main__.D 1″ in other words, the class passed as the first argument of foo() is the class involved in the call, not the class involved in the definition of foo().
But notice this:
class E(C):
def foo(cls, y): # override C.foo
print “E.foo() called”
foo = classmethod(foo)
E.foo(1)e = E()e.foo(1)
In this example, the call to C.foo() from E.foo() will see class C as its first argument, not class E. This is to be expected, since the call specifies the class C. But it stresses the difference between these class methods and methods defined in metaclasses, where an upcall to a metamethod would pass the target class as an explicit first argument. (If you don’t understand this, don’t worry, you’re not alone.
上面的例子中,在E中覆盖了基类的foo方法,并且调用了基类的方法。结果就是在调用基类方法时,传入的是基类对象。可以理解的就是因为在调用时,我们使用的是基类C来调用的。不过,如果是在元类中,我们必须明确地传入目标类作为第一个参数。
— limodou @ 2:25 pm
当然很重要了。老师不是总教育我们说:要知其然,还要知其所以然嘛。之所以想到这个话题,是因为这几天学习的感受。这几天说实在的,我并没有闲着,有时间还是在学习Python和XUL。而且还真都是原理学习为主的。但想到以前编程序并不一定要你的原理掌握得深入才可以动手,即便是掌握得不好,不一定会影响你编程。
我想,原因就是:在编程时不一定会用到很深入的原理知识,再加上现在面向对象技术、组件技术和网络信息的共享,很多东西别人都已经做好或做过了,你要么用别人的作好的东西,要么去提问,别人告诉你如何做。这样,原理的学习并不一定很重要。再加上现在开源项目很多,在你做某个项目时,当需要用到原理的时候,很有可能有类似的项目已经差不多实现的,你要做的只是参考一下,然后量身订做即可。
如果再仔细想一想,就象我以前写的关于经验之谈,其实我们很我时候在编程时还是以经验为主的,而经验是以前知识的积累:比如说做过类似的项目、学过类似的技术、犯过似类的错、做过相关的测试。再加上编程语言有时是不一样,但相互之间借鉴,许多地方反倒差不多,更使得我们的经验在新的情况下还可以应用。以至于虽然我们并不一定十分清楚正在使用的原理,但由于我们有了经验,我们只要按正确的方法去做就行了,至于为什么这样做就对,那样做就错,我们不一定需要知道。
不过,本文的目的并不是强调经验要远胜于掌握原理,而是想说:不管是学习还是编程,人的思维是分层次的。是原理重要还是经验重要呢?在不同的阶段、不同的场合、不同的目的下,侧重点是不一样的。尤以学习阶段最明显。
本人的学习就是喜欢先有一些入门的例子,有了一些感性认识之后,再学一些原理这样的效果好一些。许多原理的确是很难,不容易理解。而我比较适合学习一些感性的东西,因此先学一些例子,有了体会,再学原理才会容易理解。更有,有了一些例子,我就可以搭建一个试验环境,自已做一些测试,从而慢慢巩固已经学到的知识。
有时学习是为了快速应用,如果一点点地掌握原理,必然会影响学习的进度,再加上将要使用的东西可能不需要很多的原理,这时不如先学一些基本的,然后参考一些例子对照着学效果就好。因为,很多东西别人已经实现过了,可以直接拿过来用。但学到一定程度,或某此内容不掌握原理就不能正确运行的话,不学是不可能的,只有耐下性子来认真学才行。好在许多的教程也是先举例,再讲原理,比较符合我的学习习惯。
— limodou @ 8:43 pm
Introspecting instances of built-in types
For instances of built-in types (and for new-style classes in general), x.__class__ is now the same as type(x):
&&& type([])&type ‘list’&&&& [].__class__&type ‘list’&&&& list&type ‘list’&&&& isinstance([], list)1&&& isinstance([], dict)0&&& isinstance([], object)1&&&
对于内置类型的实例(通常是new-style class的实例),x.__class__现在与type(x)是一样的。(因此在一些文章中你会看到type(x)就表示x的父类或基类。因为object是所有类的基类,因此isinstance([], object)返回为True。这里用得是1,但现在已经改为True和False了。)
In classic , the method names of lists were available as the __methods__ attribute of list objects, with the same effect as using the built-in dir() function:
Python 2.1 (#30, Apr 18 :18) [GCC egcs-2.91.66 /Linux (egcs-1.1.2 release)] on linux2Type “copyright”, “credits” or “license” for more information.&&& [].__methods__['append', 'count', 'extend', 'index', 'insert', 'pop','remove', 'reverse', 'sort']&&& &&& dir([])['append', 'count', 'extend', 'index', 'insert', 'pop','remove', 'reverse', 'sort']
在classic Python中(python 2.2版之前),列表的方法名可以使用列表对象的__methods__来得到,这同使用内置的dir()函数的效果一样。
Under the new proposal, the __methods__ attribute no longer exists:
Python 2.2c1 (#803, Dec 13 :05) [GCC egcs-2.91.66 /Linux (egcs-1.1.2 release)] on linux2Type “copyright”, “credits” or “license” for more information.&&& [].__methods__Traceback (most recent call last):
File “&stdin&”, line 1, in ?AttributeError: ‘list’ object has no attribute ‘__methods__’&&&
但在新的提案中,__methods__属性不再存在了。
Instead, you can get the same information from the dir() function, which gives more information:
&&& dir([])['__add__', '__class__', '__contains__', '__delattr__','__delitem__', '__eq__', '__ge__', '__getattribute__','__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__','__imul__', '__init__', '__le__', '__len__', '__lt__', '__mul__','__ne__', '__new__', '__reduce__', '__repr__', '__rmul__','__setattr__', '__setitem__', '__setslice__', '__str__', 'append','count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse','sort']&&&
然而你可以使用dir()函数得到同样的信息,它还会给你更多的信息。
The new dir() gives more information than the old one: in addition to the names of instance variables and regular methods, it also shows the methods that are normally invoked through special notations, like __iadd__ (+=), __len__ (len), __ne__ (!=).
新的dir()给出的信息比新的更多:除了给出实例变量的名称和正常的方法以外,它还给出通常是通过特别标记来调用的方法,如:__iadd__(+=), __len__(len), __ne__(!=)。
More about the new dir() function:
dir() on an instance (classic or new-style) shows the instance variables as well as the methods and class attributes defined by the instance’s class and all its base classes.
对一个实例(classic或new-style)使用dir()会显示实例变量的方法也包括定义在实例变量所对应的类和基类的类属性。(类变量和类方法都是类属性。)
dir() on a class (classic or new-style) shows the contents of the __dict__ of the class and all its base classes. It does not show class attributes that are defined by a metaclass. 对一个类(classic或new-style)使用dir()会显示类的__dict__中的内容,以及所有基类中__dict__中的内容(也就是类属性)。但并不显示通过metaclass来定义的属性。
dir() on a module shows the contents of the module’s __dict__. (This is unchanged.)
dir() without arguments shows the caller’s local variables. (Again, unchanged.)
There’s a new C API that implements the dir() function: PyObject_Dir().
Th in particular, for objects that override __dict__ or __class__, these are honored, and for backwards compatibility, __members__ and __methods__ are honored if they are defined.
You can use a method of a built-in type as an “unbound method”:
&&& a = ['tic', 'tac']&&& list.__len__(a)
# same as len(a)2&&& list.append(a, ‘toe’)
# same as a.append(‘toe’)&&& a['tic', 'tac', 'toe']&&&
This is just like using an unbound method of a user-defined class – and similarly, it’s mostly useful from inside a subclass method, to call the corresponding base class method.
使用未绑定(unbound)的方法在一个子类中调用基类的相应方法时用得最多。unbound与bound的区别我的理解就是:是否与一个实例绑定。一般在一个类中定义的方法,如果是通过类名进行调用,那么这种调用方式就是未绑定的。如果是通过实例来调用,则是已绑定。类函数有一个属性是im_self,如果为空则未被绑定。如果为实例对象,则为已绑定。因此,直接通过类来调用类方法时,需要传入一个实例对象。这就是我们常用的调用基类的方式。
Unlike user-defined classes, you cannot change built-in types: attempts to assign an attribute of a built-in type raises a TypeError, and their __dict__ is a read-only proxy object. The restriction on attribute assignment is lifted for new-style user-defined classes, including subclasses of built- however even those have a read-only __dict__ proxy, and you must use attribute assignment to replace or add a method of a new-style class. Example session:
不象用户自定义的类,你不能改变built-in type:试图向一个build-in type的属性(已存在的)赋值会引发一个TypeError异常,而且它们的__dict__是一个只读的proxy(代理)对象。对属性赋值的限制也对new-style的用户自定义的类起作用,包括从built-in type派生的子类。然而尽管有着只读的__dict__代理,你也必需使用属性赋值来向new-style class替换或添加方法。(好奇怪,看下面的例子)
&&& list.append
#list有一个append方法&method ‘append’ of ‘list’ objects&&&& list.append = list.append
#不可以对built-in list的属性作出修改Traceback (most recent call last):
File “&stdin&”, line 1, in ?TypeError: can’t set attributes of built-in/extension type ‘list’&&& list.answer = 42
#也不可以向list增加新的属性Traceback (most recent call last):
File “&stdin&”, line 1, in ?TypeError: can’t set attributes of built-in/extension type ‘list’&&& list.__dict__['append'] #在list中的__dict__中可以找到append方法&method ‘append’ of ‘list’ objects&&&& list.__dict__['answer'] = 42
#list的__dict__是只读的Traceback (most recent call last):
File “&stdin&”, line 1, in ?TypeError: object does not support item assignment&&& class L(list):
#从list派生了一个子类…
pass… &&& L.append = list.append
#可以对子类使用属性赋值&&& L.answer = 42&&& L.__dict__['answer']
#L的__dict__中有新加的属性42&&& L.__dict__['answer'] = 42
#但直接使用L的__dict__是不允许的Traceback (most recent call last):
File “&stdin&”, line 1, in ?TypeError: object does not support item assignment&&&
For the curious: there are two reasons why changing built-in classes is disallowed. First, it would be too easy to break an invariant of a built-in type that is relied upon elsewhere, either by the standard library, or by the run-time code. Second, when Python is embedded in another application that creates multiple Python interpreters, the built-in class objects (being statically allocated data structures) are shared betw thus, code running in one interpreter might wreak havoc on another interpreter, which is a no-no.
为什么不允许修改built-in class有两个原因。第一,会很容易破坏那些依赖这些built-in type的不变 性的标准库或运行代码。第二,当Python嵌入到另一种创建多个Python解释器的应用程序中时,built-in class对象(静态分配数据结构)是在所有解释器中 共享的,因此运行在一个解释器中的代码可能会别的解释器造成破坏,这是要禁止的。
经过我的测试,的确象上样说的一样(注意都是对于type或类来说的,不是指实例):
对于built-in type,不可以增加新的属性,不可以修改存在的属性。通过__dict__可以读出,不能修改,因为它是dictproxy类型,是只读的。
对于new-style class或从built-in派生来的子类,可以通过属性赋值来增加属性和替换存在的属性。可以通过__dict__来读出属性,不能直接通过__dict__来增加和修改属性,因为它是只读的。
实例的__dict__不是只读的,因此可以使用。
想一想的确是有道理。类是实例的模板,它如果可以容易改变的话很可能会造成一些混乱,特别是如果可以对内置类型修改的话。最好的办法是派生不同的类。这样首先要对类进行规划,然后允分地利用实例来解决问题。
— limodou @ 4:04 pm
Built-in types as factory functions
The previous section showed that an instance of the built-in subtype defaultdict can be created by calling defaultdict(). This is expected, because this also works for classic classes. But here’s a new feature: built-in base types themselves can also be instantiated by calling the type directly.(type是可以用来生成新的类,而且它是类的工厂函数。但如何做,没试出来。)
For several built-in types, there are already factory functions named after the type in classic , for example str() and int(). I’ve changed these built-ins so that they are now names for the corresponding types. While this changes the type of these names from built-in function to built-in type, I don’t expect that this will create backward compatibility problems: I’ve made sure that the types can be called with exactly the same argument lists as the former functions. (They can also generally be called without arguments, producing an object with a suitable default value, s this is new.)
在classic python 中,对于几种内置type,已经存在工厂函数,它们的命名与类型相一致,象str()和int()。我(Guido)已经改动了这些内置方法,这样它们都是用对应的类型来命名的。同时这也导致这些类型从built-in函数变成为built-in type(变化挺大)。我(Guido)不认为这样会产生向后兼容问题:我已经确保这些类型可以用同以前一样的函数参数列表来进行调用(调用方法没有变化)。(它们也可以不用参数进行调用,这样产生的的对象带有一个合适的缺省值,如0或空。这是新的。)
These are the affected built-ins:
int([number_or_string[, base_number]])
long([number_or_string])
float([number_or_string])
complex([number_or_string[, imag_number]])
str([object])
unicode([string[, encoding_string]])
tuple([iterable])
list([iterable])
type(object) or type(name_string, bases_tuple, methods_dict)
The signature of type() requires an explanation: traditionally, type(x) returns the type of object x, and this usage is still supported. However, type(name, bases, methods) is a new usage that creates a brand new type object. (This gets into , and I won’t go into this further here except to note that this signature is the same as that used by the Don Beaudry hook of metaclass fame.)
传统上,type(x)返回对象x的类型,并且这一用法仍然是支持的。然而,type(name, bases, methods)是一种新的用法,可以生成崭新的type对象(可以理解为新的type或class,这已经属于metaclass的用法了)。
There are also a few new built-ins that follow the same pattern. These have been described above or will be described below:
dict([mapping_or_iterable]) – ret the optional argument must be either a mapping whose items are copied, or a sequence of 2-tuples of length 2 giving the (key, value) pairs to be inserted into the new dictionary
object([...]) – return a ne arguments are ignored
classmethod(function) – see below
staticmethod(function) – see below
super(class_or_type[, instance]) – see below
property([fget[, fset[, fdel[, doc]]]]) – see below
上面是一些新的内置体。象dict()可以生成字典对象,同时dict可以作为字典的类型。object()会返回一个没有任何特性的对象,你甚至不能向它增加新的属性(真不知道有什么用)。如果传入了参数,则参数被忽略。classmethod可以把一个类的成员方法变成类方法。你可以使用类名或实例名来进行调用,如:C.f()或C().f()。第一个参数为调用的类对象。staticmethod可以把一个类的成员方法变成静态方法。你可以使用类名或实例名来进行调用,同上。此时第一个参数即不是调用的类对象,也不是实例对象。super和property在后面会讲到。
The purpose of this change is twofold. First, this makes it convenient to use any of these types as a base class in a class statement. Second, it makes testing for a specific type a little easier: rather than writing type(x) is type(0), you can now write isinstance(x, int).
这种改变有双重意义。首先,可以很容易地在class语句中把它们用成基类。其次,在测试某种类型时相对容易:比起type(x) is type(0)来,你现在可以写为 isinstance(x, int)。
Which reminds me. The second argument of isinstance() may now be a tuple of classes or types. For example, isinstance(x, (int, long)) returns true when x is an int or a long (or an instance of a subclass of either of those types), and similarly isinstance(x, (str, unicode)) tests for a string of either variety. We didn’t do this to issubclass().
isinstance()的第二个参数现在可以是一个class或type的tuple。例如,isinstance(x, (int,long)),当x是一个int或long(或int和long类型的子类实例)时返回真。对于issubclass()却不能这样做(第二个参数是tuple)。
— limodou @ 10:40 pm
Subclassing built-in types
这里还用的是subclass,看有些文章已经不用subclass,而改用subtype这个词。这是为了区别于class专指classic class而来的。等到全部统一到new-style class时,使用subclass还是习惯一些吧。
这是2.2的一个明显的变化,built-in type可以被子类化了。不过,2.2版中已经把type和class合二为一统称为type了,这就非常的自然了。其实这里更主要的意思我认为是想说:以前的built-in type象list, dict原来是不可以被子类化的,现在已经可以子类化了。
Let’s start with the juiciest bit: you can subtype built-in types like dictionaries and lists. All you need is a name for a base class that is a built-in type and you’re in business.
There’s a new built-in name, “dict”, for the type of dictionaries. (In version 2.2b1 and before, this was called “dictionary”; while in general I don’t like abbreviations, “dictionary” was just too long to type, and we’ve been saying “dict” for years.)
有一个内的内置名字,“dict”,它是字典的类型。在2.2b1和它之前,字典被称为“dictionary”,Guido通常是不喜欢使用缩写的,但“dictionary”对type来说有点太长了,而且大家使用“dict”也有几年了。
Here’s an example of a simple dict subclass, which provides a “default value” that is returned when a missing key is requested:
class defaultdict(dict):
def __init__(self, default=None):
dict.__init__(self)
self.default = default
def __getitem__(self, key):
return dict.__getitem__(self, key)
except KeyError:
return self.default
上面是一个从dict派生的例子。它的作用是当访问一个不存在的元素时,返回一个缺省值。
This example shows a few things. The __init__() method extends the dict.__init__() method. Like __init__() methods are wont to do, it has a different argument list than the base class __init__() method. Likewise, the __getitem__() method extends the base class __getitem__() method.
__init__()方法扩展了dict.__init__()方法,它比基类__init__()方法多了一个不同的参数。同样,__getitem__()方法扩展了基类的__getitem__()方法。
The __getitem__() method could also be written as follows, using the new “key in dict” test introduced in
def __getitem__(self, key):
if key in self:
return dict.__getitem__(self, key)
return self.default
上面是__getitem__()方法的另一种写法,它使用了在
2.2 中新引进的”key in dict”的条件判断。(这种用法其实相当于:key in dict.keys()。)
I believe that this version is less efficient, because it does the key lookup twice. The exception would be when we expect that the requested key is almost never in the dictionary: then setting up the try/except statement is more expensive than the failing “key in self” test.
不过上面的新版本效率有些低,因为它要查找键值两次(一次是key in self,一次就是真正把值取出来)。然而使用异常机制的代价要比”key in self”判断高一些。(没做过测试,我想可能要看字典的大小吧。)
To be complete, the get() method should probably also be extended, to make it use the same default as __getitem__():
def get(self, key, *args):
if not args:
args = (self.default,)
return dict.get(self, key, *args)
(Although this function is declared with a variable-length argument list, it really should only be called with
if more are passed, the base class method call will raise a TypeError exception.)
为了完整起见,get()方法也应该进行扩展。尽管方法是使用可变长度参数列表来声明的,它应该只使用一个或两个参数来调用,如果传入更多的参数,基类方法的调用会引发一个TypeError的异常来。
We’re not restricted to extending methods defined on the base class. Here’s a useful method that does something similar to update(), but keeps existing values rather than overwriting them with new values if a key exists in both dictionaries:
def merge(self, other):
for key in other:
if key not in self:
self[key] = other[key]
This uses the new “key not in dict” test as well as the new “for key in dict:” to iterate efficiently (without making a copy of the list of keys) over all keys in a dictionary. It doesn’t require the other argument to be a defaultdict or even a dictionary: any mapping object that supports “for key in other” and other[key] will do.
我们并没有限制只可以扩展在基类中存在的方法。这里有一个有用的方法可以实现与update()相似的功能,但当一个键存在时,它是保持对应的值不变,而不是象update一样,覆盖对应的值。它也使用了新的”kek not in dict”判断和新的”for key in dict”来有效地列取(不用生成键列表的拷贝)一个字典中所有键。merge方法并不要求另一个参数是defaultdict类型或dict类型:任何支持”for key in order”和other[key]的映射类型的对象都可以使用。(其实从这里看,Python中就已经有interface的概念,但因为Python获得一个对象的方法非常容易,就是a.x就行,因此并不需要显示有一种interface的定义。不过,这也造成,我们一般是通过一些文档来描述interface的信息,而没有特别的强制手段来保证传入的对象是满足条件的。只有运行的时候引发异常,可能才会知道我们传入的对象是存在问题的。现在许多framework正在试图定制强制手段来实现interface的可见性,象zope 3x中就大量使用了interface。可以阅读我的这篇Blog看一看了解一些Python中Interface的使用习惯。)
Iterator也是Python中很大的变化,我专门有一篇Blog是讲它的,阅读。Iterator的主要好处就是减少内存占用,我想也可以提高一些速度。
Here’s the new type at work:
&&& print defaultdict # show our type&class ‘__main__.defaultdict’&&&& print type(defaultdict) # its metatype&type ‘type’&&&& a = defaultdict(default=0.0) # create an instance&&& print a # show the instance{}&&& print type(a) # show its type&class ‘__main__.defaultdict’&&&& print a.__class__ # show its class&class ‘__main__.defaultdict’&&&& print type(a) is a.__class__ # its type is its class1&&& a[1] = 3.25 # modify the instance&&& print a # show the new value{1: 3.25}&&& print a[1] # show the new item3.25&&& print a[0] # a non-existant item0.0&&& a.merge({1:100, 2:200}) # use a dictionary method&&& print a # show the result{1: 3.25, 2: 200}&&&
新的类工作很好。(为了在donews上输出我使用了全角大括号。)
We can also use the new type in contexts where classic only allows “real” dictionaries, such as the locals/globals dictionaries for the exec statement or the built-in function eval():
&&& print a.keys()[1, 2]&&& exec “x = 3; print x” in a3&&& print a.keys()['__builtins__', 1, 2, 'x']&&& print a['x']3&&&
新的type还可以用在仅允许“真正”字典的上下文中,例如,在exec语句或内置函数eval()中使用的locals/globals字典。(这样,新定义的类型与原来的dict类型没有什么区别。)
However, our __getitem__() method is not used for variable access by the interpreter:
&&& exec “print foo” in aTraceback (most recent call last):File “&stdin&”, line 1, in ?File “&string&”, line 1, in ?NameError: name ‘foo’ is not defined&&&
Why doesn’t this print 0.0? The interpreter uses an internal function to access the dictionary, which bypasses our __getitem__() override. I admit that this can be a problem (although it is only a problem in this context, when a dict subclass is used as a locals/globals dictionary); it remains to be seen if I can fix this without compromising performance in the common case.
然而,__getitem__()方法不能被解释器和来访问变量。(象上面的exec的意思就是在a这个名字空间,把变量foo打印出来。)为什么不打印0.0呢?(为什么是0.0呢?因为在生成实例a时,我们已经指定缺省值为0.0,因此,这里的意思就是说:在a中打印foo,因为foo不存在,应该可以打印缺省值0.0。)这是因为解释器使用一个内部的函数来访问字典,它会跳过我们的__getitem__()。要承认这的确是一个问题(仅管它只存在于这个上下文,当一个子类化的字典被作用一个locals/globals字典时)。
Now we’ll see that defaultdict instances have dynamic instance variables, just like classic classes:
&&& a.default = -1&&& print a["noway"]-1&&& a.default = -1000&&& print a["noway"]-1000&&& print a.__dict__.keys()['default']&&& a.x1 = 100&&& a.x2 = 200&&& print a.x1100&&& print a.__dict__.keys()['default', 'x2', 'x1']&&& print a.__dict__{’default’: -1000, *: 200, *: 100}&&&
我们可以看到defaultdict的实例拥有动态的实例变量。象classic class一样。你可以修改它。
This is not
in particular, using a separate dictionary to hold a single instance variable doubles the memory used by a defaultdict instance compared to using a regular dictionary! There’s a way to avoid this:
class defaultdict2(dict):
__slots__ = ['default']
def __init__(self, default=None):
…(like before)…
但这不总是你想要的,特别是,defaultdict使用一个分离的字典来保持一个单个实例变量,同通常的字典比较看,它占用两倍的内存。(为什么说两倍呢?因为通常的字典信息都放在字典内部。而defaultdict保存实例属性时,又多了一个字典,这样相当于存在了两个字典。因此要占两倍的空间。不过,为什么对实例变量赋值会放在__dict__中呢?我想可能是因为属性赋值(a.x)与字典赋值(a[x])不同,一个是调用__setattr__()一个是调用__setitem__()。而一般我们操作字典都是调用的__getitem__()和__setitem__()。如果你试一下,你对一般的字典使用a.x这样的形式会报错。而我们生成的的确是一个新的类,它让你这样做。)
因此上面提出了一个解决办法,那就是使用新的属性__slots__。
The __slots__ declaration takes a list of instance variables, and reserves space in the instance for exactly these in the instance. When __slots__ is used, other instance variables cannot be assigned to:
&&& a = defaultdict2(default=0.0)&&& a[1]0.0&&& a.default = -1&&& a[1]-1&&& a.x1 = 1Traceback (most recent call last):File “&stdin&”, line 1, in ?AttributeError: ‘defaultdict2′ object has no attribute *&&&
__slots__保存着实例变量的列表,并且在实例中保留空间以确定它们在实例中。一旦使用了__slots__,其它的实例变量就不能被赋值了。(象上面a.x1,因为x1不在__slots__中,因此引发异常。也就是说,你只可以访问在__slots__中存在的实例属性,对不存在的属性引用就会出错。)
这样做的结果就是值不会再生成一个__dict__字典来保存了,节省了内存。而且,限定了可以使用的属性变量。
Some noteworthy tidbits and warnings about __slots__:
An undefined slot variable will raise AttributeError as expected. (Note that in
2.2b2 and earlier, slot variables had the value None by default, and “deleting” them restores this default value.) 一个未定义的slot变量将按我们所期望地引发AttributeError异常。(注意在
2.2b2和更早的版本,slot变量缺省为None,并且“删除”它们会恢复这个缺省值。)(什么意思?经过试验,原来,当你在一个类中定义了__slots__=['x'],并不表示你就可以使用a.x来使用它了。在2.3中,这样会引发一个AttributeError异常。而a.x=1后,再使用a.x就可以了。这说明__slots__的表示只是保留,但它不会真正创建对应的变量,还是要你来创建。在你未创建之前,就叫未定义的slot变量。一旦我们执行了对slot变量的赋值操作,slot变量就创建了。因此后面补充到2.2b2之前的版本与此有所不同。在2.2b2之后,如果你删除了slot变量,再引用时,它一样变成未定义,会引发异常。)
You cannot use a class attribute to define a default value for an instance variable defined by __slots__. The __slots__ declaration creates a class attribute containing a descriptor for each slot, and setting a class attribute to a default value would overwrite this descriptor. 你不能使用类属性来为使用__slots__定义的实例变量提供缺省值。__slots__声明会为每一个slot变量创建一个包含descriptor(描述符)的类属性,而设置类属性为一个缺省值会覆盖这个descriptor。(通过在类定义中声明类属性一般可以为实例对象提供一个属性的缺省值,但是使用__slots__时不要这么做。关于descriptor又是漫漫长路,详情参见。其实在2.3+的文档中已经有descriptor的描述,但感觉不易懂,可能是语言的缘故,看这篇文章可能会好一些。)
There’s no check to prevent name conflicts between the slots defined in a class and the slots defined in its base classes. If a class defines a slot that’s also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly this could be used to rename it). Doing this renders the meaning of yo a check to prevent this may be added in the future. 没有检查来阻止一个类中定义的slots和基类中定义的slots产生的名字冲突问题。如果一个类定义了一个slot,并且这个slot也定义在基类中,那么基类中定义的实例变量是不可访问的(除非直接从基类的descriptor来获取,这样可以用来重命名)。这样做会致使你的程序未被定义(还有这种意思?)。以后会加入对此的检查。
Instances of a class that uses __slots__ don’t have a __dict__ (unless a base class defines a __dict__); but instances of derived classes of it do have a __dict__, unless their class also uses __slots__. 使用了__slots__的类实例不能再有__dict__(除非一个基类定义了__dict__)。但从它派生的类可以拥有一个__dict__,除非它也使用了__slots__。
You can define an object with no instance variables and no __dict__ by using __slots__ = []. 你不能定义通过定义__slots__=[]来定义一个即没有实例变量,又没有__dict__的对象。
You cannot use slots with “variable-length” built-in types as base class. Variable-length built-in types are long, str and tuple.你不能把slots用在以“可变长度”的built-in type作为基类的类上。可变长度built-in type是long, str和tuple。(long也算可变长度真是很奇怪,而dict却不算。)
A class using __slots__ does not support weak references to its instances, unless one of the strings in the __slots__ list equals “__weakref__”. (In Python 2.3, this feature has been extended to “__dict__”) 一个使用了__slots__的类不支持对实例的弱引用(weak reference),除非在__slots__列表中的一个字符串等于”__weakref__”。(在Python 2.3中,这一特性已经被扩展到”__dict__”上)(我试了试,如果在__slots__中加入了__dict__,我就可以定义在slots之外的实例变量了。)
&&& class A(object):…
__slots__=['x', '__dict__']&&& a=A()&&& a.b=1
The __slots__ variable doesn’ any non-string that can be iterated over will do, and the values returned by the iteration are used as the slot names. In particular, a dictionary can be used. You can also use a single string, to declare a single slot. However, in the future, an additional meaning may be assigned to using a dictionary, for example, the dictionary values may be used to restrict the type of an instance variable or
the effect of using something that’s not a list renders the meaning of your program undefined. __slots__变量不一定是一个list,任何可以被列举的非字符串都可以是,并且列举所返回的值将作为slot的名字。特别是,可以使用字典。你也可以使用单个字符串来声明一个单一slot。然而,在未来,可能对于使用字典会赋予特别的意义,例如,字典值可以用来限制一个实例变量的类型,或提供一个doc string。使用非列表的东西会致使你的程序处于非定义的意思。
注意,__slots__只是用来定义类可以有哪些实例变量名,并不生成实际的实例变量。与__slots__定义的名字对应的实例变量可以称为slot变量。你需要自已来生成它,通过赋值语句。如果未生成即进行引用,则引发异常。
Note that while in general operator overloading works just as for classic classes, there are some differences. (The biggest one is the lack of support for __coerce__; new-style classes should always use the new-style numeric API, which passes the other operand uncoerced to the __add__ and __radd__ methods, etc.)
There’s a new way of overriding attribute access. The __getattr__ hook, if defined, works the same way as it does for classic classes: it is only called if the regular way of searching for the attribute doesn’t find it. But you can now also override __getattribute__, a new operation that is called for all attribute references.
有一种新的覆盖属性访问的方式。如果定义了__getattr__钩子,它将同classic class一样的方式工作。只有当正常查找的属性找不到时它才会被调用。但你也可以覆盖__getattribute__,它可以用来对所有的属性引用进行处理。
When overriding __getattribute__, bear in mind that it is easy to cause infinite recursion: whenever __getattribute__ references an attribute of self (even self.__dict__!), it is called recursively. (This is similar to __setattr__, which gets called for all a __getattr__ can also suffer from this when it is carelessly written and references a non-existent attribute of self.)
当覆盖__getattribute__时,在心里要明白,这样很容易引起无限递归:只要__getattribute__引用self的一个属性(甚至是self.__dict__!),它都将递归调用。(很象__setattr__和__getattr__)
The correct way to get any attribute from self inside __getattribute__ is to call the base class’s __getattribute__ method, in the same way any method that overrides a base class method can call the base class method: Base.__getattribute__(self, name). (See also the discussion of
below if you want to be correct in a multiple inheritance world.)
从self获得任何属性的正确的方法是在__getattribute__中调用基类的__getattribute__方法,同其它调用基类方法一样:Base.__getattribute__(self, name)。(如果想要正确处理多得继承,看后面对super的讨论)
Here’s an example of overriding __getattribute__ (really extending it, since the overriding method calls the base class method):
class C(object):
def __getattribute__(self, name):
print “accessing %r.%s” % (self, name)
return object.__getattribute__(self, name)
这是一个正确调用的例子。
A note about __setattr__: sometimes attributes are not stored in self.__dict__ (for example when using __slots__ or properties, or when using a built-in base class). The same pattern as for __getattribute__ applies, where you call the base class __setattr__ to do the actual work. Here’s an example:
class C(object):
def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError, “attributes are write-once”
object.__setattr__(self, name, value)
注意__setattr__,有时属性不是保存在self.__dict__中(例如,当使用__slots__或property时,或使用built-in基类时)。
C++ programmers may find it useful to realize that this form of subtyping in Python is implemented very similarly to single-inheritance subclassing in C++, with __class__ in the role of the vtable.
There’s much more that could be explained (like the __metaclass__ declaration, and the __new__ method), but most of that is pretty esoteric. See
if you’re interested.
还有一些象__metaclass__声明和__new__方法,但它们非常深奥。有兴趣在后面。(的确如此)
I’ll end with a list of caveats:
You can use multiple inheritance, but you can’t multiply inherit from different built-in types (for example, you can’t create a type that inherits from both the built-in dict and list types). This is a p it would require too many changes to Python’s object implementation to lift it. However, you can create mix-in classes by inheriting from “object”. This is a new built-in, naming the featureless base type of all built-in types under the new system. 你可以使用多重继承,但不能从不同的built-in type来多重继承(例如,不能创建一种type,同时从dict和list类型继承而来)。这是永久的限制。不这样限制的话,需要对Python做非常多的改动才可以适应。然而你可以通过从object继承来创造mix-in类。object是一种新的built-in,在新系统下为所有built-in type命名的无特性的基type。(Python已经是单根继承了,要记住。)
When using multiple inheritance, you can mix classic classes and built-in types (or types derived from built-in types) in the list of base classes. (This is new in Python 2.2b2; in earlier versions you couldn’t.) 当使用多重继承,你可以混合classic class和built-in type(或从built-in type继承来的类型)在基类列表中。(在Python 2.2b2中是新的,在更早的版本则不行)(那么结果到底是什么类型呢?是&type ‘type’&类型,你可以试一试。)
See also the general .
— limodou @ 9:35 pm
我想学习还是精读一些的好。这几天看了不少关于New-Style Class的文章,资料,想到一句话是“侯门深似海”,我现在的感觉是“OO深似海”。许多概念、原理、技术如果只是平时应用的话可能并不是很关心它的细节,只要能保证我正确使用就行了。因为每个人都有一种使用的习惯,在这种习惯下很多东西也许你不是很清楚为什么会这样,但是经验告诉我们,这样就不会有问题。但光会用对我来说是远远不够的,只有深入了解Python的细节,特别是OO的知识,有些东西你才可能明白。从这一段阅读 .list 上的邮件来看,有些东西已经很深入地涉及了象 New-Style Class这样的知识。如果你不具备这样的知识和经验,你很难明白别人在说什么。就是象我前面介绍过的Lazy计算,看一看代码,别人也是用的Metaclass来实现的。因此,只有不停地学习才可以。
经过学习,很多东西的确已经慢慢理解,并有了一些感觉。我想现在更需要静下心来,对于某些文章细细地品味,并多做测试才可以更好的理解。那么就以Guido写的
来开始吧。有些内容可能我就照搬或直译了。
Introduction
2.2 introduces the first phase of “type/class unification”. This is a series of changes to Python intended to remove most of the differences between built-in types and user-defined classes. Perhaps the most obvious one is the restriction against using built-in types (such as the type of lists and dictionaries) as a base class in a class statement. Andrew Kuchling’s
paper devotes one of its longest sections to this language deficiency. Incidentally, Andrew’s paper
gives a broad overview of what else is new in Python 2.2.
从Python 2.2开始就第一次引入了“type/class统一”的术语。Python作了一系列的改变以消除大部分built-in type和用户定义的类之间的不同。其中最明显的变化可能就是可以在一个class语句中把built-in type作为基类,如list和dict。
This is one of the biggest changes to Python ever, and yet it can be done with very few backwards incompatibilities. The changes are described in minute detail in a series of
(Python Enhancement Proposals). PEPs are not designed to be tutorials, and the PEPs describing the type/class unification are sometimes hard to read. They also aren’t finished yet. That’s where this paper comes in: it introduces the key elements of the type/class unification for the average Python programmer.
这些改变在一系列的PEPs中有详细的描述。PEP不是教程,而且有时很难读懂。(的确如此,有些PEP不仅写了如何做,还有怎么做,看起来是够复杂的,至今我也没看过几篇。)这篇论文讲述了type/class unification中一些主要的元素,是给普通的Python程序员看的。
A bit of terminology: “classic Python” refers to Python 2.1 (and its patch releases such as 2.1.1) or earlier versions, while “classic classes” refer to classes defined with a class statement that does not have a built-in object amongst its bases: either because it has no bases, or because all of its bases are classic classes themselves – applying the definition recursively.
classic classes 是指在一个class语句定义中,基类不包括built-in对象的类(或者是没有基类,或者所有的基类都是classic class)。这是一种循环定义。
Classic classes are still a special category in Python 2.2. Eventually they will be totally unified with types, but because of additional backwards incompatibilities, this will be done after 2.2 is released (maybe not before Python 3.0). I’ll try to say “type” when I mean a built-in type, and “class” when I’m referring to a classic class or something
if it wouldn’t be clear from the context which interpretation is meant, I’ll try to be explicit, using “classic class” or “class or type”.
Classic class 在Python 2.2中仍然是一种特别的种类。最后它们终将被type所同化,但由于所带来的向后不兼容,这一过程将可能在2.2发布之后(也许在Python 3.0发布之前)完成。(Guido是在2.2发布时写的这篇论文,要记住。既然如此,建议大家以后编程还是直接用New-Style class好了,早用早好。)以后type是指built-in type,而class是指classic class或诸如此类的东西。如果从上下文很难分清某种解释是什么意思,将试着明确使用”classic class”或”class 或 type”。
那么我们可以理解为:type就是new-style class的称呼,而class已经专指classic class。由于现存两种不同OO机制,看上去的确挺乱的。那么在这篇文章我们可以这样理解。如果大家全部统一到new-style class上来,是用type还是class可能就无所谓了。不过,这篇文章很强调built-in type。为什么呢?因为对于new-style class来说,要么从object继承而来,要么从type继承而来,而且这种继承是在class语句中显示指明的。而object,type就是built-type。因此这一点就成为new-style class与classic class的根本区别。
— limodou @ 4:59 pm
这篇文章讲述了如何使用decorator在
中实现抽象函数(或虚函数)的方法。通常老的作法是在基类存在一个空函数,但它会引发一个异常。比如:
&&& class A(object):…
def abstract(self):…
raise “You should implement this method”
&&& class B(A):…
&&& a=B()&&& a.abstract()
Traceback (most recent call last):
File “&pyshell#8&”, line 1, in -toplevel-
a.abstract()
File “&pyshell#3&”, line 3, in abstract
raise “You should implement this method”You should implement this method
可以看出,当在子类的实例上调用未在基类实现的方法时,会引发一个异常。不过,这也有一个问题,那就是如果一直没有调用这个未实现的方法,Python 是不会告诉你哪个方法未在子类中实现的。
那么本文提出的方法是:
写一个decorator方法,它的作用是给每个指定为abstract的函数加一个属性,用于指明此函数为abstract函数。在文章中是: f.abstract = True
在所有为abstract函数前加上此decorator描述
编写一个用于所有包含abstract函数的基类,它的作用是在__init__时,检查类中的所有函数,看一看是否存在函数的属性abstract有为True的,一旦存在,则说明此函数未被覆盖(override),因此引发异常。
不过,使用这种方法要求你在基类中一定要使用super(Class, self).__init__来调用父类的初始化函数,以保证对abstract函数能在初始化时被检查出来。
不过,记得在 python.list 邮件列表中看到过有关在Python中实现纯虚函数的讨论(很有趣)。
更有人谈到,即使我覆盖了父类的abstract函数,但子类中的函数仍然为空,如就一句pass,又如何呢?真是有些较真了。其实abstract的作用是让你一定要在继承时去实现,而不是要保证你实现的一定要有意义,那完全是人的事情。在讨论中Alex还使用metaclass实现了一把,有兴趣大家可以看一看。
— limodou @ 12:59 pm
PSF是Python Software Foundation的简称。在今年它第一次发起资助项目,今年有60多个提议被发起,最终有三个项目被批准进行资助。它们是:
Brian Zimmer will manage the project
Ilya Etingof will manage the project
Greg Wilson will manage the project
Jython终于会有机会再发展了,如果再加上Sun的支持,在Java领域将会有一番作为。期待。其它两个还不太了解。
— limodou @ 12:16 pm
前面我介绍过Lazy计算,在此模块的作者Blog上还有一篇文章,,关于future–一种特殊的承诺。仔细看一下它的实现,你会发现它是使用线程来实现的。作者的想法是通过线程来实现计算的并行化。它与Lazy不同,并不是当你需要值的时候才计算,而是一上来就计算,但是与主线程并行。如果在主线程需要这个值的时候,它会阻塞住,直到future计算完成。然后继继它的运算。不过,Python解释器一次只可以有一个线程在运行,因此这种技术在Python中现在是无法实现的,作者也说是一种技术上的练习。
再仔细想一想,作者提供的Lazy方法其实只适合于函数调用。因为函数是有返回值的,当你只是把函数返回值保存起来时,这个值并没有什么用。只有与外界发生关系时,如打印,这个值才真正有用。这也是Lazy实现的方法:考察所有与外界的交互,真正需要输出值时就会去调用真正的函数,不需要时则并不进行真正的计算。如果我调用的是一个无返回值的函数(或叫过程),这一方法就无效了。因为,过程没有返回值,因此你很难自动判断何时过程的处理是立刻需要的,何时过程的处理不是立刻需要的。
能否实现过程的Lazy方法呢?这个问题很有趣。
— limodou @ 10:44 pm
本站所有内容采用许可证。
Pythoner in 中国
Python开源项目
我的开源项目}

我要回帖

更多关于 猜英文单词 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信