大家看到什么翻译错误,格式错误,或是感觉可以有更好的翻译的,欢迎大家直接参与翻译 (如果是修改,你可以在已有翻译的旁边标注一下。),谢谢
附录 —— 选择性的令人印象深刻的 python 简短回顾
APPENDIX -- A Selective and Impressionistic Short Review of Python
- A reader who is coming to Python for the first time would be well served reading Guido van Rossum's _Python Tutorial_, which can be
downloaded from <http://python.org/>, or picking up one of the several excellent books devoted to teaching Python to novices. As indicated in the Preface, the audience of this book is a bit different.
第一次接触 python 的读者适合去读 Guido van Rossum 的 Python Tutorial, 可以从 http://python.org/ 下载, 或者选一本针对 python 初学者的好书。 就像序言中说过的那样,本书针对的读者会稍微不太一样。
- The above said, some readers of this book might use Python only infrequently, or not have used Python for a while, or may be sufficiently versed in numerous other programming languages, that a quick review on Python constructs suffices for understanding. This appendix will briefly mention each major element of the Python language itself, but will not address any libraries (even standard and ubiquitous ones that may be discussed in the main chapters). Not all fine points of syntax and semantics will be covered here, either. This review, however, should suffice for a reader to understand all the examples in this book.
上面说了,本书的读者也许只是不常使用 python,或是有一段时间没有过 python , 或是精通许多其它语言,对他们来说只要对 python 来一点简短的回顾他们就懂了。 本附录将会简要地谈谈 python 语言本身的每一个重要组成部分,但不会涉及任何库
- (甚至是标准库和在本书主要章节中讨论过的常用库)。也不会涉及到所有语法和语义的细节。
不过,这篇回顾应该足够让读者理解本书中所有例子了。
- Even readers who are familiar with Python might enjoy skimming this review. The focus and spin of this summary are a bit different from most introductions. I believe that the way I categorize and explain a number of language features can provide a moderately novel--but equally accurate--perspective on the Python language. Ideally, a Python programmer will come away from this review with a few new insights on the familiar constructs she uses every day. This appendix does not shy away from using some abstract terms from computer science--if a particular term is not familiar to you, you will not lose much by skipping over the sentence it occurs in; some of these terms are explained briefly in the Glossary.
甚至可能连那些对 python 已经很熟悉了的读者都会喜欢这篇回顾的。 这个摘要的目的和 spin 和大部分介绍文章都不一样。 我相信我的这种对语言特色进行分类和解释的方式能为您提供一种新鲜的——也是同样准确的——看待 python 语言的角度。 理想的情况下,python 程序员看完这篇回顾后,应该会让他对自己经常使用的熟知的东西(constructs)有一些新的看法。 这篇附录不会刻意回避一些计算机科学中的抽象术语——如果你对某一术语不熟,大可直接跳过那一段,并不会有什么损失的; 某些术语在术语表中有简短的解释。
python 属于哪种类型的语言
SECTION -- What Kind of Language is Python?
--------------------------------------------------------------------
- Python is a byte-code compiled programming language that supports multiple programming paradigms. Python is sometimes called an interpreted and/or scripting language because no separate compilation step is required to run a Python program; in more precise terms, Python uses a virtual machine (much like Java or Smalltalk) to run machine-abstracted instructions. In most situations a byte-code compiled version of an application is cached to speed future runs, but wherever necessary compilation is performed "behind the scenes."
python 是一个字节码编译型的语言,它支持多种编程范式。 由于运行一个 python 程序并不需要单独的编译步骤,所以有时候 python 也被叫做是解释型的 和/或 脚本语言; 用更精确的术语来说,python 使用一个虚拟机 (很像 Java 或是 Smalltalk) 来运行抽象机器的指令 (machine-abstracted instructions)。 在大部分情况下,一个被编译成字节码的应用程序会被缓存起来,这样在以后运行的时候可以加快速度, 不过不管在什么地方进行的必要的编译过程都是在“幕后”悄悄完成的。
- In the broadest terms, Python is an imperative programming language, rather than a declarative (functional or logical) one. Python is dynamically and strongly typed, with very late binding compared to most languages. In addition, Python is an object-oriented language with strong introspective facilities, and one that generally relies on conventions rather than enforcement mechanisms to control access and visibility of names. Despite its object-oriented core, much of the syntax of Python is designed to allow a convenient procedural style that masks the underlying OOP mechanisms. Although Python allows basic functional programming (FP) techniques, side effects are the norm, evaluation is always strict, and no compiler optimization is performed for tail recursion (nor on almost any other construct).
用最宽泛的术语来说,python 是一种命令式 (imperative) 的编程语言,而非声明式 (函数式或逻辑式) 的。 python 是动态类型且是强类型的语言,相对大部分语言来说它拥有真正的迟绑定。 另外 python 还是一个拥有强大内省 (introspective) 机制的面向对象语言, 它依赖于约定而非强制机制来进行访问控制和名字的可见性控制。 撇开它的面向对象的核心,python 的大部分语法都设计成方便的面向过程式 (procedural) 的风格, 通过它来 (mask) 底层的面向对象机制。 虽然 python 允许基本的函数式编程 (FP) 技术,不过边界效应 (side effects) 还是正常的 (norm), 求值也总是严格的,而且还不会对尾递归(还有几乎所有其它的东西)进行编译器优化。
- Python has a small set of reserved words, delimits blocks and structure based on indentation only, has a fairly rich collection of built-in data structures, and is generally both terse and readable compared to other programming languages. Much of the strength of Python lies in its standard library and in a flexible system of importable modules and packages.
python 有一个不大的保留字集合,分界块 (delimits blocks) 和仅基于缩进的层次结构, 还拥有一组相当丰富的内置数据结构,而且相对其它语言来说很简洁,可读性也很强。 python 很多强大能力存在于它的标准库和灵活的模块/包系统之中。
名字空间与绑定
SECTION -- Namespaces and Bindings
--------------------------------------------------------------------
- The central concept in Python programming is that of a namespace. Each context (i.e., scope) in a Python program has available to it a hierarchically organized collection of namespaces; each namespace contains a set of names, and each name is bound to an object. In older versions of Python, namespaces were arranged according to the "three-scope rule" (builtin/global/local), but Python version 2.1 and later add lexically nested scoping. In most cases you do not need to worry about this subtlety, and scoping works the way you would expect (the special cases that prompted the addition of lexical scoping are mostly ones with nested functions and/or classes).
使用 python 编程的核心概念就是名字空间。 python 程序中的每一个上下文 (或者说是作用范围) 都拥有一组层次结构的名字空间; 每一个名字空间包含一组名字,每一个名字绑定到一个对象。 在老版本的 python 中,使用 “三层范围规则” (内置/全局/局部) 对名字空间进行组织, 不过 python 2.1 及其后的版本都增加了嵌套的作用范围。 在大部分情况下你并不需要考虑这种微妙的东西,而且作用范围工作的方式和你所期待的是一样的。 (需要增加另外的 lexical scoping 的特例大部分都是嵌套函数 和/或 嵌套类)
- There are quite a few ways of binding a name to an object within the current namespace/scope and/or within some other scope. These various ways are listed below.
有好几种方法可以在当前的名字空间/作用范围 和/或 一些其它的作用范围中将一个名字绑定到对象上去。 这些方法有:
赋值和解除引用
- TOPIC -- Assignment and Dereferencing
--------------------------------------------------------------------
A Python statement like x=37 or y="foo" does a few things. If an object--e.g., 37 or "foo"--does not exist, Python creates one. If such an object -does- exist, Python locates it. Next, the name x or y is added to the current namespace, if it does not exist already, and that name is bound to the corresponding object. If a name already exists in the current namespace, it is re-bound. Multiple names, perhaps in multiple scopes/namespaces, can be bound to the same object.
像 x=37 或 y="foo" 这样的 python 表达式干了好几件事: 如果该对象—— 比如说 37 或是 "foo" ——不存在,那 python 就先创建这个对象。 如果该对象存在,python 就先找到它。 然后,如果名字 x 或 y 不存在的话,就先把它们加到当前名字空间中来, 并且将这个名字绑定到相应的对象。如果该名字在当前名字空间中已经存在,那它就会被重新绑定。 多个名字,可能还是处在多个作用范围/名字空间中的多个名字,都可以绑定到同一个对象。
- A simple assignment statement binds a name into the current namespace, unless that name has been declared as global. A name declared as global is bound to the global (module-level) namespace instead. A qualified name used on the left of an assignment statement binds a name into a specified namespace--either to the attributes of an object, or to the namespace of a module/package, for example:
一个简单的赋值语句会将一个名字绑定到当前的名字空间中,除非该名字已经被声明成 global 了。 一个定义为 global 的名字被绑定到全局 (模块级) 名字空间中。 在赋值语句左边出现的受限名字 (qualified name) 将一个名字绑定到一个指定的名字空间——可能是对象的属性,或是模块/包的名字空间, 比如:
1 >>> x = "foo" # bind `x` in global namespace
2 >>> def myfunc(): # bind `myfunc` in global namespace
3 ... global x, y # specify namespace for `x`, `y`
4 ... x = 1 # rebind global `x` to 1 object
5 ... y = 2 # create global name `y` and 2 object
6 ... z = 3 # create local name `z` and 3 object
7 ...
8 >>> import package.module # bind name `package.module`
9 >>> package.module.w = 4 # bind `w` in namespace package.module
10 >>> from mymod import obj # bind object `obj` to global namespace
11 >>> obj.attr = 5 # bind name `attr` to object `obj`
1 >>> x = "foo" # 将 `x` 绑定到全局名字空间
2 >>> def myfunc(): # 将 `myfunc` 绑定到全局名字空间
3 ... global x, y # 为 `x`, `y` 指定名字空间
4 ... x = 1 # 将全局名字 `x` 重绑定到对象 1
5 ... y = 2 # 创建全局名字 `y` 和对象 2
6 ... z = 3 # 创建局部名字 `z` 和对象 3
7 ...
8 >>> import package.module # 绑定名字 `package.module`
9 >>> package.module.w = 4 # 将 `w` 绑定到名字空间 package.module
10 >>> from mymod import obj # 将对象 `obj` 绑定到全局名字空间
11 >>> obj.attr = 5 # 将名字 `attr` 绑定到对象 `obj`
- Whenever a (possibly qualified) name occurs on the right side of an assignment, or on a line by itself, the name is dereferenced to the object itself. If a name has not been bound inside some accessible scope, it cannot be dereferenced; attempting to do so
raises a NameError exception. If the name is followed by left and right parentheses (possibly with comma-separated expressions between them), the object is invoked/called after it is dereferenced. Exactly what happens upon invocation can be controlled and overridden for Python objects; but in general, invoking a function or method runs some code, and invoking a class creates an instance. For example:
无论何时一个名字(可能是受限的)出现在赋值语句的右边,或者在只有它自己的行中, 该名字都会被解除引用而得到它引用的对象。 如果一个名字没有被绑定到某个可访问的作用范围里面,它就不能被解除引用; 如果试图这样做的话会抛出一个 NameError 的异常。如果名字后面跟着左右两个括号 (其中可能还有逗号分割的表达式), 在解除引用后,该对象会被调用。调用期间实际干些什么事情可以被 python 对象控制和重写。 不过通常调用一个函数或方法会执行一些代码,调用一个 class 会创建一个实例。 比如:
函数和类的定义
- TOPIC -- Function and Class Definitions
--------------------------------------------------------------------
describing an object and binding it to a name. But the def and class declarations are "deep down" just types of assignments. In the case of functions, the lambda operator can also be used on the right of an assignment to bind an "anonymous" function to a name. There is no equally direct technique for classes, but their declaration is still similar in effect:
定义一个函数或类简直是描述一个对象并将它绑定到一个名字的首选方式了。 不过 def 和 class 声明本质上 (deep down) 只是赋值的不同形式罢了。 拿函数来说,我们还可以在赋值语句的右边使用lambda 运算符,这样可以绑定一个“匿名”函数到一个名字。 对于类来说没有和它等价的便捷技术,不过在效果上它们的声明还是很相似的:
import 表达式
TOPIC -- import Statements
--------------------------------------------------------------------
modifies bindings in the current namespace. The import statement has two forms, each with a bit different effect. Statements of the forms:
导入——或者从某处导——一个模块或者一个包,会在当前名字空间中添加或修改一些绑定。 import 表达式有两种形式,每一种都有稍微不同的效果。
这种形式的表达式:
- add a new module object to the current namespace. These module objects themselves define namespaces that you can bind values in or utilize objects within.
在当前名字空间中增加一个新的模块对象。 这些模块对象本身定义了名字空间,你可以绑定值到其中,也可以利用其中的对象。
- Statements of the forms:
这种形式的表达式:
..instead add the names foo or bar to the current namespace. In any of these forms of import, any statements in the imported module are executed--the difference between the forms is simply the effect upon namespaces.
则向当前名字空间添加名字 foo 或 bar。 import 表达式的任何一个形式中,被导入的模块中的所有表达式都会被执行——区别只在于对名字空间产生的效果。
There is one more special form of the import statement; for example:
这是 import 表达式的一种更特殊的形式:
1 >>> from modname import *
- The asterisk in this form is not a generalized glob or regular expression pattern, it is a special syntactic form. "Import star" imports every name in a module namespace into the current namespace (except those named with a leading underscore, which can still be explicitly imported if needed). Use of this form is somewhat discouraged because it risks adding names to the current namespace that you do not explicitly request and that may rebind existing names.
这种形式中的星号不是一个通用形式的 glob 也不是正则表达式的模式,它是一个特殊的语法形式。 "Import star" 会将模块名字空间中的所有名字导入到当前名字空间中来 (除了那些以下划线开头的名字,如果需要的话它们也可以被显示地导入进来)。 我们不太提倡这种形式的 import ,因为它可能会添加一些你明显并不需要的名字到当前名字空间, 还可能重绑定已有名字。
for 表达式
TOPIC -- for Statements
--------------------------------------------------------------------
Although for is a looping construct, the way it works is by binding successive elements of an iterable object to a name (in the current namespace). The following constructs are (almost) equivalent:
虽然 for 是用来建立循环的,不过它工作的方式是通过将一个可迭代 (iterable) 对象中的连续元素绑定到一个名字 (在当前名字空间中)
来完成的。以下语句是 (几乎) 等价的:
except 表达式
TOPIC -- except Statements
--------------------------------------------------------------------
The except statement can optionally bind a name to an exception argument:
except 表达式可选地将一个名字绑定到一个异常参数上:
数据类型
SECTION -- Datatypes
--------------------------------------------------------------------
- Python has a rich collection of basic datatypes. All of Python's collection types allow you to hold heterogeneous elements inside them, including other collection types (with minor limitations). It is straightforward, therefore, to build complex data structures in Python.
python 有一组丰富的基本数据类型。所有 python 的 collection 类型 都可以在其中包含不同类型的元素,甚至其它 collection 类型 (会稍微有点限制)。 因此,在 python 中构建复杂数据结构变得非常简单。
- Unlike many languages, Python datatypes come in two varieties: mutable and immutable. All of the atomic datatypes are immutable,
as is the collection type tuple. The collections list and dict are mutable, as are class instances. The mutability of a datatype is simply a question of whether objects of that type can be changed "in place"--an immutable object can only be created and destroyed, but never altered during its existence. One upshot of this distinction is that immutable objects may act as dictionary keys, but mutable objects may not. Another upshot is that when you want a data structure--especially a large one--that will be modified frequently during program operation, you should choose a mutable datatype (usually a list).
和许多其他语言都不一样的是,python 的数据类型分为两种:可变的和不可变的。 所有原子数据类型都是不可变的数据类型,还有 collection 类型 tuple 也是属于这一类的。 而 collection 类型 list 和 dict 是可变的,还有类、实例也都是属于这一类的。 所谓数据类型的可变性指的就是该类型的对象是否可以“就地” (in-place) 修改—— 不可变的对象就只能够对它们进行创建和销毁,不可以在它们存在的期间中进行修改。 这种区别导致的一个结果就是不可变对象可以作为字典的 key,而可变对象则不能。 导致的另外一个结果就是如果一个数据结构——特别是很大的数据结构—— 需要在程序操作期间经常被修改,那你就应该选择一个可变的数据结构了(通常是一个 list)。
- Most of the time, if you want to convert values between different Python datatypes, an explicit conversion/encoding call is required, but numeric types contain promotion rules to allow numeric expressions over a mixture of types. The built-in datatypes are listed below with discussions of each. The built-in
function type() can be used to check the datatype of an object.
大部分时候,如果你想在不同 python 数据类型之间对值进行转换, 需要显示地进行转换(或者说编码)调用, 不过数值类型包含有提升 (promotion) 规则, 可以允许数值表达式中混合多种类型。 下面列出所有内置数据类型和相关的讨论。 内置函数 type() 可以用来查看一个对象的类型。
简单类型
- TOPIC -- Simple Types
--------------------------------------------------------------------
- Python 2.3+ supports a Boolean datatype with the possible
values True and False. In earlier versions of Python, these values are typically called 1 and 0; even in Python 2.3+, the Boolean values behave like numbers in numeric contexts. Some earlier micro-releases of Python (e.g., 2.2.1) include the -names- True and False, but not the Boolean datatype.
python 2.3 及其后续版本支持布尔数据类型,只能取 True 和 False 两个值。 在 python 更早期的版本中,这两个值被象征性地叫做 1 和 0;甚至在 python2.3 及其后续版本中,布尔型的值在数值环境中的行为也还是跟数字很像。有一些更早的 python micro-releases (比如 2.2.1) 中也包含有名字 True 和 False,不过它们并不是 布尔类型。
- int
- A signed integer in the range indicated by the register size of the interpreter's CPU/OS platform. For most current platforms, integers range from (2**31)-1 to negative (2**31)-1. You can find the size on your platform by
examining sys.maxint. Integers are the bottom numeric type in terms of promotions; nothing gets promoted -to- an integer, but integers are sometimes promoted to other numeric types. A float, long, or string may be explicitly converted to an int using the int() function. SEE ALSO, [int]
- A signed integer in the range indicated by the register size of the interpreter's CPU/OS platform. For most current platforms, integers range from (2**31)-1 to negative (2**31)-1. You can find the size on your platform by
有符号整数的范围由解释器所处的 CPU/OS 平台的寄存器大小所决定。 对于目前大部分平台来说,整数的范围是从负 (2**31)-1 到正 (2**31)-1 的。 你可以通过 sys.maxint 查看在你的平台上的大小。 对于提升 (promotion) 规则来说整数是最基础的数值类型; 没有东西可以被提升 (promotion) 为一个整数,而整数有时候可以被提升为其他数值类型。 浮点数、长整型,或者字符串都可以通过 int() 函数显式地转换成整数。
- long
- An (almost) unlimited size integral number. A long literal
is indicated by an integer followed by an l or L (e.g., 34L, 9876543210l). In Python 2.2+, operations on ints that overflow sys.maxint are automatically promoted to longs. An int, float, or string may be explicitly converted to a long using the long() function.
- An (almost) unlimited size integral number. A long literal
这是个 (几乎) 没有大小限制的整数。 后面跟着一个 l 或 L 的整数表示一个长整数(比如 34L, 9876543210l)。 python 2.2 及其后续版本中,在超过 sys.maxint 的整数上进行操作会将该整数自动提升为长整数。 整数、浮点数或字符串可以通过 long() 函数显式地转换为长整数。
- float
- An IEEE754 floating point number. A literal floating point number is distinguished from an int or long by containing a
decimal point and/or exponent notation (e.g., 1.0, 1e3, .453e-12, 37.). A numeric expression that involves both int/long types and float types promotes all component types to floats before performing the computation. An int, long, or string may be explicitly converted to a float using the float() function. SEE ALSO, [float]
- An IEEE754 floating point number. A literal floating point number is distinguished from an int or long by containing a
这是 IEEE754 浮点数。 浮点数于整数或长整数在字面上的区别在于包含十进制的小数部分 和/或 指数符号(比如 1.0, 1e3, .453e-12, 37.)。 一个同时涉及到 整数/长整数 和浮点数的数值表达式会先将所有类型提升为浮点型,然后再进行计算。 整数、长整数或字符串都可以通过 float() 函数显式转换为浮点数。
- complex
- An object containing two floats, representing real and imaginary components of a number. A numeric expression that involves both int/long/float types and complex types promotes all component types to complex before performing the computation. There is no way to spell a literal
complex in Python, but an addition such as 1.1+2j is the usual way of computing a complex value. A j or J following a float or int literal indicates an imaginary number. An int, long, or string may be explicitly converted to a complex using the complex() function. If two float/int arguments are passed to complex(), the second is the imaginary component of the constructed number (e.g., complex(1.1,2)).
- An object containing two floats, representing real and imaginary components of a number. A numeric expression that involves both int/long/float types and complex types promotes all component types to complex before performing the computation. There is no way to spell a literal
这是个包含有两个浮点数的对象,分别表示数字中的实数部和虚数部分。 同时涉及到 整数/长整数/浮点数 和复数的数值表达式会先将所有类型都提升为复数, 然后再进行计算。 在 python 中没有用来表达复数的字面量 (literal), 不过像 1.1+2j 这样的加法运算常常用来计算一个复数。 在一个浮点数后面跟一个 j 或 J 表示一个虚数。 整数、长整数或字符串都可以通过 complex() 函数显式转换地为复数。 如果给 complex() 传递两个浮点型/整型参数,那么第二个将作为虚数部分。
- string
- An immutable sequence of 8-bit character values. Unlike in many programming languages, there is no "character" type in Python, merely strings that happen to have length one. String objects have a variety of methods to modify strings, but such methods always return a new string object rather than modify the initial object itself. The built-in
chr() function will return a length-one string whose ordinal value is the passed integer. The str() function will return a string representation of a passed in object. For example:
- An immutable sequence of 8-bit character values. Unlike in many programming languages, there is no "character" type in Python, merely strings that happen to have length one. String objects have a variety of methods to modify strings, but such methods always return a new string object rather than modify the initial object itself. The built-in
一个不可变的8位字符的序列。 和许多其他编程语言不同的是,python 中没有字符型,只有长度为1的字符串。 字符串对象有许多方法可以用来修改字符串, 不过这些方法总是返回一个新的字符串对象,而不是修改开始的那个对象。 内置函数 chr() 会返回一个长度为1的字符串,其 ascil 码值为传入的整数。 str() 函数返回传入对象的字符串表现形式。比如:
- SEE ALSO, [string]
- unicode
- An immutable sequence of Unicode characters. There is no datatype for a single Unicode character, but unicode strings of length-one contain a single character. Unicode strings contain a similar collection of methods to string objects, and like the latter, unicode methods return new unicode objects rather than modify the initial object. See Chapter 2 and Appendix C for additional discussion, of Unicode.
一个不可变的 Unicode 字符序列。 没有表达单个 Unicode 字符的数据类型,不过长度为1的 unicode 字符串包含单个字符。 Unicode 字符串包含有一组和字符串对象类似的方法,而且和后者一样, unicode的方法也总是返回新的 unicode 对象,而非修改开始那个。 第2章和 附录 C 中有更多 Unicode 的讨论。
字符串替代(Interpolation)
- TOPIC -- String Interpolation
--------------------------------------------------------------------
-interpolated- into the string using the % operator and a tuple or dictionary giving the values to substitute in.
字面上的 (Literal) 字符串和 unicode 字符串可以包含内嵌的格式码。 如果字符串包含有格式码,那么使用 % 运算符和一个给出用来替换的值的元组 (tuple) 或者字典就可以向字符串中插入值。
- Strings that contain format codes may follow either of two patterns. The simpler pattern uses format codes with the syntax
%[flags][len[.precision]]<type>. Interpolating a string with format codes on this pattern requires % combination with a tuple of matching length and content datatypes. If only one value is being interpolated, you may give the bare item rather than a tuple of length one. For example:
包含格式码的字符串可以有两种模式。 简单点的模式是通过这种语法 %[标记][长度[.精度]]<类型> 来使用格式码。 在这种模式下的字符串需要一个 % 外加一个相应长度和相应数据类型组成的元组来 对字符串进行替代。如果只有一个值被替代,你还可以直接给出这个值, 就不需要写一个长度为1的元组了。比如:
- The (slightly) more complex pattern for format codes embeds a name within the format code, which is then used as a string key to an interpolation dictionary. The syntax of this pattern is
%(key)[flags][len[.precision]]<type>. Interpolating a string with this style of format codes requires % combination with a dictionary that contains all the named keys, and whose corresponding values contain acceptable datatypes. For example:
稍微复杂点的模式是给格式码内嵌一个名字, 随后它会被作为替代字典的 key。 这个模式的语法是 %(key)[标记][长度[.精度]]<类型>。 对这种形式的字符串进行替代需要一个 % 外加一个字典, 这个字典的 key 中要包含了所有名字,并且名字对应的值要拥有相应的数据类型。 比如:
- You -may not- mix tuple interpolation and dictionary interpolation within the same string.
你不能在同一个字符串中混合使用这两种模式。
- I mentioned that datatypes must match format codes. Different format codes accept a different range of datatypes, but the rules are almost always what you would expect. Generally, numeric data will be promoted or demoted as necessary, but strings and complex types cannot be used for numbers.
我刚才提到过数据类型一定要和格式码匹配。 不同的格式码接受不同范围的数据类型,不过这些规则几乎都和你期望的相同。 通常来说数值数据在必要的时候会被提升或降级 (demoted), 但是字符串和复数类型不能被当做数字来用。
- One useful style of using dictionary interpolation is against the global and/or local namespace dictionary. Regular bound names defined in scope can be interpolated into strings.
使用字典进行替代的一个有点用处的形式就是:使用全局 和/或 局部名字空间字典。 在作用范围内正常绑定的名字都可以被替代到字符串中去。
- If you want to look for names across scope, you can create an ad hoc dictionary with both local and global names:
如果你想要在越过作用范围查找名字, 你可以创建一个特殊的同时拥有局部和全局变量的字典:
- The flags for format codes consist of the following:
格式码使用的标记包括:
#*--------------- Format code flags ----------------------# 0 Pad to length with leading zeros - Align the value to the left within its length _ (space) Pad to length with leading spaces + Explicitly indicate the sign of positive values
#*--------------- 格式码标记 ----------------------# 0 通过在前面加 0 进行长度补齐 - 在值的长度范围内对值进行左对齐 _ (空格) 通过在前面加空格进行长度补齐 + 显示出正数的符号
- When a length is included, it specifies the -minimum- length of the interpolated formatting. Numbers that will not fit within a length simply occupy more bytes than specified. When a precision is included, the length of those digits to the right of the decimal are included in the total length:
如果指定了长度值,它表示的是替代格式的最小长度。 超出这个长度的数字就会占据比指定的更多字节了。 如果指定了精度值,数字右边数字的长度会被包含到总长度里面来:
- The formatting types consist of the following:
格式类型由以下组成:
#*-------------- Format type codes -----------------------# d Signed integer decimal i Signed integer decimal o Unsigned octal u Unsigned decimal x Lowercase unsigned hexadecimal X Uppercase unsigned hexadecimal e Lowercase exponential format floating point E Uppercase exponential format floating point f Floating point decimal format g Floating point: exponential format if -4 < exp < precision G Uppercase version of `g` c Single character: integer for chr(i) or length-one string r Converts any Python object using repr() s Converts any Python object using str() % The `%` character, e.g.: '%%%d' % (1) --> '%1'
#*-------------- 格式类型码 -----------------------# d 有符号整数 i 有符号整数 o 无符号八进制数 u 无符号十进制数 x 小写无符号十六进制数 X 大写无符号十六进制数 e 小写指数格式浮点数 E 大写指数格式浮点数 f 浮点数格式 g 浮点: 如果 -4 < exp < precision 则用指数格式 G 大写版本的 `g` c 单个字符: 传给 chr(i) 整数 或是 长度为一的字符串 r 使用 repr() 转换任何 python 对象 s 使用 str() 转换任何 python 对象 % `%` 字符, 比如: '%%%d' % (1) --> '%1'
One more special format code style allows the use of a * in place of a length. In this case, the interpolated tuple must contain an extra element for the formatted length of each format code, preceding the value to format. For example:
另外还有一种格式码风格,可以在指定长度的地方使用 *。在这种情况下, 用来替代的元组必须另外再提供一个元素来给所有格式码指定长度, 还是使用元组前面的值来进行格式化。比如:
打印
- TOPIC -- Printing
--------------------------------------------------------------------
streams can be accessed using the pseudo-files sys.stdout and sys.stderr. Writing to these is just like writing to any other file; for example:
在 python 中最原始的 (least-sophisticated) 文本输出形式就是写到文件中去。 STDOUT 和 STDERR 流还可以通过伪文件对象 (pseudo-files) sys.stdout 和 sys.stderr 来进行访问。 对它们进行写和写其他文件是一样的;比如:
- You cannot seek within STDOUT or STDERR--generally you should consider these as pure sequential outputs.
你不能在 STDOUT 或 STDERR 中定位探针 (seek) ——通常你应该把它们当作是纯粹连续的输出。
- Writing to STDOUT and STDERR is fairly inflexible, and most of
the time the print statement accomplishes the same purpose more flexibly. In particular, methods like sys.stdout.write() only accept a single string as an argument, while print can handle any number of arguments of any type. Each argument is coerced to a string using the equivalent of repr(obj). For example:
向 STDOUT 和 STDERR 里面写东西并不灵活 (inflexible), 而且大多数时候使用 print 语句可以更灵活地 (flexibly) 达到相同的目的。
Each argument to the print statment is evaluated before it is printed, just as when an argument is passed to a function. As a consequence, the canonical representation of an object is printed, rather than the exact form passed as an argument. In my example, the dictionary prints in a different order than it was defined in, and the spacing of the list and dictionary is slightly different. String interpolation is also peformed and is a very common means of defining an output format precisely.
传递给 print 语句的所有参数都会在被打印之前先进行求值,就像传递给函数的参数一样。 这样才可以打印出对象的规范形式,而非作为参数传递时的形式。 在我上面那个的例子中,打印出的字典的顺序和它们定义的顺序不太一样, 而且列表和字典里面的空格也不太一样。 另外字符串替代也被执行了,而且正是按照输出格式所定义的那样。
There are a few things to watch for with the print statement. A space is printed between each argument to the statement. If you want to print several objects without a separating space, you will need to use string concatenation or string interpolation to get the right result. For example:
使用 print 语句时还有几件事情需要注意。 在所有参数之间都会打印一个空格。 如果你想要同时打印几个对象而不想在中间夹杂空格, 你可以使用字符串连接操作 (concatenation) 或者字符串替代 (interpolation)。
By default, a print statement adds a linefeed to the end of its output. You may eliminate the linefeed by adding a trailing comma to the statement, but you still wind up with a space added to the end:
默认情况下,print 语句会在输出的末尾添加一个换行符。 你可以通过在语句的末尾添加一个逗号来去掉这个换行, 不过这样的话,输出的末尾就会添加一个空格了:
- Assuming these spaces are unwanted, you must either use
sys.stdout.write() or otherwise calculate the space-free string you want:
如果连这些空格也不想要,那你就只能用 sys.stdout.write() 或者是先计算出你想要打印的字符串:
There is a special form of the print statement that redirects its output somewhere other than STDOUT. The print statement itself can be followed by two greater-than signs, then a writable file-like object, then a comma, then the remainder of the (printed) arguments. For example:
print 语句还有一种特殊的形式,它可以将输出重定向到 STDOUT 以外的某个地方。 print 语句本身后面可以跟两个大于号, 然后是一个可写的文件对象 (file-like object),然后是一个逗号, 然后就是其他的 (将被打印) 的参数。比如:
- Some Python programmers (including your author) consider this special form overly "noisy," but it -is- occassionally useful for quick configuration of output destinations.
有些 python 程序员 (包括笔者) 都认为这种特殊的形式过于 "noisy," 不过对于快速指定输出目的文件偶尔还是很有用的。
- If you want a function that would do the same thing as a
print statement, the following one does so, but without any facility to eliminate the trailing linefeed or redirect output:
如果你想要一个和 print 语句干着相同事情的函数的话,下面这个就是了, 不过它没有消除末尾的换行符和重定向输出的机制:
- Readers could enhance this to add the missing capabilities, but
using print as a statement is the clearest approach, generally.
您也可以给它增加一些缺失的功能,不过通常来说使用语句形式的 print 还是最清晰的方式。
SEE ALSO, sys.stderr, sys.stdout
容器类型
- TOPIC -- Container Types
--------------------------------------------------------------------
- An immutable sequence of (heterogeneous) objects. Being immutable, the membership and length of a tuple cannot be modified after creation. However, tuple elements and subsequences can be accessed by subscripting and slicing, and new tuples can be constructed from such elements and slices. Tuples are similar to "records" in some other programming languages.
元组
它是一个不可变的 (不同类型的) 对象序列。 既然是不可变的,那么元组的成员和长度在创建后都不能修改。 不过元组的元素和子序列可以通过下标和切片访问到, 而且可以使用这些元素和切片构建新的元组。 元组和某些其他编程语言中的记录(records)比较类似。
- The constructor syntax for a tuple is commas between listed items; in many contexts, parentheses around a constructed list are required to disambiguate a tuple for other constructs such as function arguments, but it is the commas not the parentheses that construct a tuple. Some examples:
构造元组的语法是使用逗号分隔一列元素; 在许多环境中,为了消除与其他东西(比如函数参数)之间的歧义, 还需要用圆括号括起来,但是构造元组的是逗号而非圆括号。几个例子:
The function tuple() may also be used to construct a tuple from another sequence type (either a list or custom sequence type).
函数 tuple() 还可以使用另一个序列类型(可以是 list 或者子定义的序列类型)来构造元组
- SEE ALSO, [tuple]
- list
- A mutable sequence of objects. Like a tuple, list elements can be accessed by subscripting and slicing; unlike a tuple, list methods and index and slice assignments can modify the length and membership of a list object.
列表
它是一个可变的对象序列。像元组一样,列表元素也可以通过下标和切片访问到; 而跟元组不一样的是,列表的方法和对索引和切片赋值会改变列表对象的元素和长度。
- The constructor syntax for a list is surrounding square braces. An empty list may be constructed with no objects between the braces; a length-one list can contain simply an object name; longer lists separate each element object with commas. Indexing and slices, of course, also use square braces, but the syntactic contexts are different in the Python grammar (and common sense usually points out the difference). Some examples:
构造列表的语法是一对中括号。 空列表的中括号中可以没有对象;长度为1的列表可以只包含一个对象; 再长点的列表使用逗号来分隔其中的每一个元素。 当然,索引和切片也是使用的中括号,不过它们在python文法中的语法上下文并不一样 ( 通常只要有点常识就可以识别出来了 )。比如:
The function list() may also be used to construct a list from another sequence type (either a tuple or custom sequence type).
函数 list() 还可以使用另一个序列类型 (可以是一个元组或是子定义的序列类型) 来构造一个列表。
- SEE ALSO, [list]
- dict
- A mutable mapping between immutable keys and object values. At most one entry in a dict exists for a given key; adding the same key to a dictionary a second time overrides the previous entry (much as with binding a name in a namespace). Dicts are unordered, and entries are accessed either by key as index; by creating lists of contained
objects using the methods .keys(), .values(), and .items(); or--in recent Python versions--with the .popitem() method. All the dict methods generate contained objects in an unspecified order.
- A mutable mapping between immutable keys and object values. At most one entry in a dict exists for a given key; adding the same key to a dictionary a second time overrides the previous entry (much as with binding a name in a namespace). Dicts are unordered, and entries are accessed either by key as index; by creating lists of contained
字典
一个在不可变类型的 key 和对象值之间的可变的映射。 一个 key 最多只能对应一个条目; 在字典中第二次添加相同的 key 会覆盖掉以前那个条目(很像在名字空间中绑定名字)。 字典是没有顺序的,并且可以通过把 key 当作索引对条目进行访问; 或者通过方法 .keys(), .values(), 和 .items() 创建其包含的对象的列表; 或者——在最近的 python 版本中——还可以使用 .popitem() 方法。 所有这些字典方法都是生成其包含的对象的无序的列表。
- The constructor syntax for a dict is surrounding curly brackets. An empty dict may be constructed with no objects between the brackets. Each key/value pair entered into a dict is separated by a colon, and successive pairs are separated by commas. For example:
字典的构造语法是一对大括号。 构造空字典时大括号之间可以没有对象。 字典中的键值对自身使用冒号分隔, 而连续的键值对之间使用逗号分隔。比如:
>>> dct = {1:2, 3.14:(1+2j), 'spam':'eggs'} >>> dct['spam'] 'eggs' >>> dct['a'] = 'b' # add item to dict >>> dct.items() [('a', 'b'), (1, 2), ('spam', 'eggs'), (3.14, (1+2j))] >>> dct.popitem() ('a', 'b') >>> dct {1: 2, 'spam': 'eggs', 3.14: (1+2j)}
In Python 2.2+, the function dict() may also be used to construct a dict from a sequence of pairs or from a custom mapping type. For example:
在 python2.2 及其后续版本中, 函数 dict() 还可以使用一个键值对的序列或者是一个自定义的映射类型来构造字典。 比如:
- SEE ALSO, [dict]
- sets.Set
- Python 2.3+ includes a standard module that implements a set datatype. For earlier Python versions, a number of developers have created third-party implementations of sets. If you have at least Python 2.2, you can download and
use the [sets] module from <http://tinyurl.com/2d31> (or browse the Python CVS)--you will need to add the definition True,False=1,0 to your local version, though.
- Python 2.3+ includes a standard module that implements a set datatype. For earlier Python versions, a number of developers have created third-party implementations of sets. If you have at least Python 2.2, you can download and
集合
python 2.3 及其以后的版本中包含了一个实现集合类型的标准模块。 对于更早的 python 版本,许多开发者已经创建了许多第三方的集合类型的实现。 如果你有 python2.2 版本,你可以从 http://tinyurl.com/2d31 或者 python cvs 中下载并使用 sets 模块——不过你需要在你本地的版本中添加True,False=1,0。
- A set is an unordered collection of hashable objects. Unlike a list, no object can occur in a set more than once; a set resembles a dict that has only keys but no values. Sets utilize bitwise and Boolean syntax to perform basic set-theoretic operations; a subset test does not have a
special syntactic form, instead using the .issubset() and .issuperset() methods. You may also loop through set members in an unspecified order. Some examples illustrate the type:
一个集合是一个可哈希对象的无序集合。 和列表不同的是,在集合中对象不能重复; 集合和只有 key 没有 value 的字典很像。 集合利用位逻辑和布尔语法来执行基本的集合理论中的操作; 子集测试没有特殊的语法形式, 而是通过 .issubset() 和 .issuperset() 方法。 你也可以无序地遍历集合的成员。 下面是一些演示该数据类型的例子:
1 >>> from sets import Set
2 >>> x = Set([1,2,3])
3 >>> y = Set((3,4,4,6,6,2)) # 使用任何序列初始化
4 >>> print x, '//', y # 保证重复的元素已被移除
5 Set([1, 2, 3]) // Set([2, 3, 4, 6])
6 >>> print x | y # 集合的并
7 Set([1, 2, 3, 4, 6])
8 >>> print x & y # 集合的交
9 Set([2, 3])
10 >>> print y-x # 集合的减
11 Set([4, 6])
12 >>> print x ^ y # symmetric difference
13 Set([1, 4, 6])
- You can also check membership and iterate over set members:
你还可以对集合成员进行迭代和对成员进行存在性 (membership) 检查:
sets.Set also supports in-place modification of sets; sets.ImmutableSet, naturally, does not allow modification.
sets.Set 支持对集合的直接 (in-place) 修改; 而sets.ImmutableSet, 顾名思义,就不支持修改了。
组合类型
- TOPIC -- Compound Types
--------------------------------------------------------------------
- A class instance defines a namespace, but this namespace's main purpose is usually to act as a data container (but a container that also knows how to perform actions; i.e., has methods). A class instance (or any namespace) acts very much like a dict in terms of creating a mapping between names and values. Attributes of a class instance may be set or modified using standard qualified names and may also be set within class methods by qualifying with the namespace of the first (implicit) method argument,
conventionally called self. For example:
实例对象
每一个实例对象其实都定义了一个名字空间,只不过这个名字空间通常是作为一个数据容器 (而且是一个知道如何对数据执行一定操作的容器,也就是说,它还拥有方法)而存在的。 任何一个实例对象(也包括任何的名字空间)在某种意义上说都很像是字典, 因为它们其实都只是名字与值之间的一个映射。 我们可以使用 . 号对名字进行限定以达到对实例对象的属性进行存取的目的, 我们也可以在方法中使用其(隐式传入的)第一个参数对其属性进行存取, 按照约定我们把这个参数叫做 self。比如:
- Instance attributes often dereference to other class instances, thereby allowing hierarchically organized namespace quantification to indicate a data structure. Moreover, a number of "magic" methods named with leading and trailing double-underscores provide optional syntactic conveniences for working with instance data. The most
common of these magic methods is .__init__(), which initializes an instance (often utilizing arguments). For example:
实例对象的属性通常引用着其他的实例对象,这样就可以使用层次结构的名字空间来表达一个数据结构。 另外实例对象还拥有一些前后都是双下划线的 magic 方法,它们为实例对象提供一些可选的约定的语法。 其中最常用的就是 .__init__() 方法, 它用来 (通常是通过传入的参数) 初始化一个实例对象。 比如:
1 >>> class Klass2:
2 ... def __init__(self, *args, **kw):
3 ... self.listargs = args
4 ... for key, val in kw.items():
5 ... setattr(self, key, val)
6 ...
7 >>> obj = Klass2(1, 2, 3, foo='FOO', bar=Klass2(baz='BAZ'))
8 >>> obj.bar.blam = 'BLAM'
9 >>> obj.listargs, obj.foo, obj.bar.baz, obj.bar.blam
10 ((1, 2, 3), 'FOO', 'BAZ', 'BLAM')
- There are quite a few additional "magic" methods that Python classes may define. Many of these methods let class instances behave more like basic datatypes (while still maintaining special class behaviors). For example, the
.__str__() and .__repr__() methods control the string representation of an instance; the .__getitem__() and .__setitem__() methods allow indexed access to instance data (either dict-like named indices, or list-like numbered indices); methods like .__add__(), .__mul__(), .__pow__(), and .__abs__() allow instances to behave in number-like ways. The _Python Reference Manual_ discusses magic methods in detail.
python class 中还可以定义好些个这种 magic 方法。 它们中许多都是为了让实例对象的行为更像基本数据类型 (当然同时还保持着 class 特殊的行为)。 比如,.__str__() 和 .__repr__() 方法控制着一个实例对象的字符串表示形式; .__getitem__() 和 .__setitem__() 方法提供通过索引获取实例对象中的数据的功能 (可以是类似字典的名字索引,也可以是类似列表的数字索引); 而像 .__add__(), .__mul__(), .__pow__(), 和 .__abs__() 这样的方法则让实例对象拥有了类似数值对象的行为。 _Python Reference Manual_ 详细地讨论了这些 magic 方法。
- In Python 2.2 and above, you can also let instances behave more like basic datatypes by inheriting classes from these built-in types. For example, suppose you need a datatype whose "shape" contains both a mutable sequence of elements and a '.foo' attribute. Two ways to define this datatype are:
在 python2.2 及其后的版本中,你还可以通过继承内置类型, 来让实例对象的行为更像基本数据类型。 举个例子,假设你需要一个实例对象,它同时包含着一个可变的序列和一个 .foo 属性。 那么你有两种定义该类型的方法:
1 >>> class FooList(list): # 只在 python2.2 及其后的版本中有用
2 ... def __init__(self, lst=[], foo=None):
3 ... list.__init__(self, lst)
4 ... self.foo = foo
5 ...
6 >>> foolist = FooList([1,2,3], 'FOO')
7 >>> foolist[1], foolist.foo
8 (2, 'FOO')
9 >>> class OldFooList: # works in older Pythons
10 ... def __init__(self, lst=[], foo=None):
11 ... self._lst, self.foo = lst, foo
12 ... def append(self, item):
13 ... self._lst.append(item)
14 ... def __getitem__(self, item):
15 ... return self._lst[item]
16 ... def __setitem__(self, item, val):
17 ... self._lst[item] = val
18 ... def __delitem__(self, item):
19 ... del self._lst[item]
20 ...
21 >>> foolst2 = OldFooList([1,2,3], 'FOO')
22 >>> foolst2[1], foolst2.foo
23 (2, 'FOO')
- If you need more complex datatypes than the basic types, or even than an instance whose class has magic methods, often these can be constructed by using instances whose attributes are bound in link-like fashion to other instances. Such bindings can be constructed according to various topologies, including circular ones (such as for modeling graphs). As a simple example, you can construct a binary tree in Python using the following node class:
如果你需要比基本数据类型更复杂的数据类型, or even than an instance whose class has magic methods, 通常我们可以通过将实例对象的属性“链接”到其他实例对象来做到这一点。 这样的“链接”可以构造出不同的拓扑结构,包括环(如果你要对图进行建模的话)。 下面是一个简单的例子,你可以使用如下的 node 类来构建一颗二叉树:
1 >>> class Node:
2 ... def __init__(self, left=None, value=None, right=None):
3 ... self.left, self.value, self.right = left, value, right
4 ... def __repr__(self):
5 ... return self.value
6 ...
7 >>> tree = Node(Node(value="Left Leaf"),
8 ... "Tree Root",
9 ... Node(left=Node(value="RightLeft Leaf"),
10 ... right=Node(value="RightRight Leaf") ))
11 >>> tree,tree.left,tree.left.left,tree.right.left,tree.right.right
12 (Tree Root, Left Leaf, None, RightLeft Leaf, RightRight Leaf)
- In practice, you would probably bind intermediate nodes to names, in order to allow easy pruning and rearrangement.
实际上,你很可能会使用另外的名字来绑定一些中间节点,以便于对树进行修剪 (pruning) 和整理 (rearrangement)
- SEE ALSO, [int], [float], [list], [string], [tuple],
[UserDict], [UserList], [UserString]
流程控制机制
SECTION -- Flow Control
--------------------------------------------------------------------
- Depending on how you count it, Python has about a half-dozen flow control mechanisms, which is much simpler than most programming languages. Fortunately, Python's collection of mechanisms is well chosen, with a high--but not obsessively high--degree of orthogonality between them.
python 里面大概有半打的流程控制机制,当然这个取决于你怎么数了, 这些流程控制机制比大部分编程语言中的都要简单。 而且幸运的是,python 中的这些机制都是经过精心挑选过的, 它们中间存在着高度的——但并非 obsessively high ——正交性。
- From the point of view of this introduction, exception handling is mostly one of Python's flow control techniques. In a language like Java, an application is probably considered "happy" if it does not throw any exceptions at all, but Python programmers find exceptions less "exceptional"--a perfectly good design might exit a block of code -only- when an exception is raised.
从本文的角度来说,异常处理也算得上是 python 的流程控制技术之一了。 像 java 这样的语言中,如果一个应用程序根本不抛出任何异常, 那么它很可能就会被认为是好程序, 但是 python 程序员认为异常其实并不是那么“异常”的 —— 完美的设计应该是 当且仅当某一个异常被抛出的时候就退出某一段代码。
- Two additional aspects of the Python language are not usually introduced in terms of flow control, but nonetheless amount to such when considered abstractly. Both functional programming style operations on lists and Boolean shortcutting are, at the heart, flow control constructs.
python 语言还有另外两个特殊的方面 (aspects),它们通常不会在流程控制中介绍, 但是理论上说它们还是应该被算其内的就是:列表的函数式操作和布尔快捷方式。 它们两个本质上说都属于流程控制的范畴。
if/then/else 语句
TOPIC -- if/then/else Statements
--------------------------------------------------------------------
the if statement and its optional elif and else components. An if block is followed by zero or more elif blocks; at the end of the compound statement, zero or one else blocks occur. An if statement is followed by a Boolean expression and a colon. Each elif is likewise followed by a Boolean expression and colon. The else statement, if it occurs, has no Boolean expression after it, just a colon. Each statement introduces a block containing one or more statements (indented on the following lines or on the same line, after the colon).
if 语句配合其可选的 elif 和 else 子句可以在不同的代码执行路径之间进行选择。 一个 if 代码块后面可以跟零或多个 elif 代码块; 在该组合语句的结尾,还可以跟零或一个 else 代码块。 if 语句后面应该跟一个布尔表达式和一个冒号。 else 语句,如果存在的话,在它后面不应该跟布尔表达式,而应该只有一个冒号。 每一个语句都会引入一个代码块,该代码块可以包含一条或多条语句 (这些语句可以是在随后的行中进行缩进,也可以是直接跟在冒号后面)。
- Every expression in Python has a Boolean value, including every bare object name or literal. Any empty container (list, dict, tuple) is considered false; an empty string or unicode string is false; the number 0 (of any numeric type) is false. As well, an
instance whose class defines a .__nonzero__() or .__len__() method is false if these methods return a false value. Without these special methods, every instance is true. Much of the time, Boolean expressions consist of comparisons between objects, where comparisons actually evaluate to the canonical objects "0" or "1". Comparisons are <, >, ==, >=, <=, <>, !=, is, is not, in, and not in. Sometimes the unary operator not precedes such an expression.
在 python 中对于每一个表达式,包括所有对象和字面量,都存在相应的一个布尔值。 所有空容器 (列表,字典,元组) 都被当作 false; 空字符串或unicode字符串也是 false。 任何数值类型表示的数字 0 都是 false。 同样的,如果一个实例对象的 class 定义了 .__nonzero__() 或 .__len__() 方法, 而且它们的返回值会被当作 false,那么它也被当作 false 。 所有没有这些特殊方法的实例对象都为 true 。 多数时候,布尔表达式都是由对象之间的比较操作组成,这些比较操作会产生实际的规范对象:0 或 1。这些比较操作有:<, >, ==, >=, <=, <>, !=, is, is not, in, 和 not in。 有些时候还可以在这样的表达式的前面加上一元操作符 not。
- Only one block in an "if/elif/else" compound statement is executed during any pass--if multiple conditions hold, the first one that evaluates as true is followed. For example:
每次经过 if/elif/else 组合语句的时候,都只有一个分支被执行—— 如果有多个条件有效的话,选择第一个为 true 的条件执行。比如:
1 >>> if 2+2 <= 4:
2 ... print "Happy math"
3 ...
4 Happy math
5 >>> x = 3
6 >>> if x > 4: print "More than 4"
7 ... elif x > 3: print "More than 3"
8 ... elif x > 2: print "More than 2"
9 ... else: print "2 or less"
10 ...
11 More than 2
12 >>> if isinstance(2, int):
13 ... print "2 is an int" # 2.2+ test
14 ... else:
15 ... print "2 is not an int"
- Python has no "switch" statement to compare one value with multiple candidate matches. Occasionally, the repetition of
an expression being compared on multiple elif lines looks awkward. A "trick" in such a case is to use a dict as a pseudo-switch. The following are equivalent, for example:
python 中没有使用同一个值来和多个候选值进行比较的 switch 语句。 有的时候,在多个 elif 行中重复同一个用来比较的表达式确实比较麻烦。 在这种情况下可以使用这样一个小技巧:使用字典来实现 伪-switch。 以下示例代码是等价的:
布尔短路
- TOPIC -- Boolean Shortcutting
The Boolean operators or and and are "lazy." That is, an expression containing or or and evaluates only as far as it needs to determine the overall value. Specifically, if the first disjoin of an or is true, the value of that disjoin becomes the value of the expression, without evaluating the rest; if the first conjoin of an and is false, its value likewise becomes the value of the whole expression.
布尔操作符 or 和 and 都是“懒惰”的。也就是说, 包含有 or 或 and 的表达式仅为对于取得总结果来说必需的那一部分进行求值。 具体地说,如果 or 表达式的左边部分为 true,那么就不用对其他部分进行求值了, 这部分的值直接成为整个表达式的值了;如果 and 表达式的左边部分为 false, 那么同样这部分的值也是直接成为整个表达式的值了。
- Shortcutting is formally sufficient for switching and is sometimes more readable and concise than "if/elif/else" blocks. For example:
布尔短路是一个很有效的分支的形式,并且有的时候比 if/elif/else 语句块更可读 也更简练。比如:
- Compound shortcutting is also possible, but not necessarily easy to read; for example:
我们还可以对布尔短路进行组合,只不过不是那么可读;比如:
1 >>> (cond1 and func1()) or (cond2 and func2()) or func3()
for/continue/break 语句
TOPIC -- for/continue/break Statements
The for statement loops over the elements of a sequence. In Python 2.2+, looping utilizes an iterator object (which may not have a predetermined length)--but standard sequences like lists, tuples, and strings are automatically transformed to iterators in for statements. In earlier Python versions, a few special functions like xreadlines() and xrange() also act as iterators.
for 语句在一个序列的元素上进行循环。python 2.2及其后的版本中, 循环需要一个迭代器对象 (迭代器可以没有预定的大小) —— 而像列表、元组、字符串这样的标准序列在 for 语句中会自动地转换成迭代器。 在 python 更早期的版本中,有少数像 xreadlines() 和 xrange() 这样的特殊函数在行为上和迭代器很像。
Each time a for statement loops, a sequence/iterator element is bound to the loop variable. The loop variable may be a tuple with named items, thereby creating bindings for multiple names in each loop. For example:
for 语句的每一次循环,都有一个序列/迭代器的元素被绑定到循环变量上。 循环变量可以是多个名字的元组,这样在每次循环中都会为这些名字绑定对象。 比如:
- A particularly common idiom for operating on each item in a dictionary is:
操作字典条目有一个特殊的惯用法就是:
- When you wish to loop through a block a certain number of
times, a common idiom is to use the range() or xrange() built-in functions to create ad hoc sequences of the needed length. For example:
如果你想要重复执行某个代码块特定的次数,通常是使用内置函数 range() 或 xrange() 来创建一个指定长度的序列。比如:
- However, if you find yourself binding over a range just to repeat a block, this often indicates that you have not properly understood the loop. Usually repetition is a way of operating on a collection of related -things- that could instead be explicitly bound in the loop, not just a need to do exactly the same thing multiple times.
然而,如果你发现你自己在一个数列上重复绑定只是为了重复执行某个代码块, 这通常意味着你并未真正理解循环。 通常循环是用来在一组相关事物(这些事物本来需要在循环中显式进行绑定)上执行操作, 而不仅仅是重复做着完全相同的事情。
If the continue statement occurs in a for loop, the next loop iteration proceeds without executing later lines in the block. If the break statement occurs in a for loop, control passes past the loop without executing later lines (except the finally block if the break occurs in a try).
如果在 for 循环中出现 continue 语句, 则跳过后面的语句而直接执行下一次循环; 如果在 for 循环中出现 break 语句, 则直接跳出循环,不会执行代码块中剩下的语句 (有一个例外就是 break 出现在拥有 finally 代码块的 try 语句中,这时 finally 代码块仍会被执行)。