[Pycharm] Symbol Review

From: http://learnpythonthehardway.org/book/ex37.htmlhtml

 

1. with X as Y: passpython

1.1 yield express

2. exec编程

2.1 namespaceapp

3. lambdaide

3.1 map函数式编程

3.2 map and reduce函数

4. raise工具

  


KEYWORD DESCRIPTION EXAMPLE
and Logical and. True and False == False
as (1) Part of the with-as statement. with X as Y: pass
assert Assert (ensure) that something is true. assert False, "Error!"
break Stop this loop right now. while True: break
class Define a class. class Person(object)
continue Don't process more of the loop, do it again. while True: continue
def Define a function. def X(): pass
del Delete from dictionary. del X[Y]
elif Else if condition. if: X; elif: Y; else: J
else Else condition. if: X; elif: Y; else: J
except If an exception happens, do this. except ValueError, e: print e
exec (2) Run a string as Python. exec 'print "hello"'
finally Exceptions or not, finally do this no matter what. finally: pass
for Loop over a collection of things. for X in Y: pass
from Importing specific parts of a module. from x import Y
global Declare that you want a global variable. global X
if If condition. if: X; elif: Y; else: J
import Import a module into this one to use. import os
in Part of for-loops. Also a test of X in Y. for X in Y: pass also 1 in [1] == True
is Like == to test equality. 1 is 1 == True
lambda (3) Create a short anonymous function. s = lambda y: y ** y; s(3)
not Logical not. not True == False
or Logical or. True or False == True
pass
This block is empty. def empty(): pass
print Print this string. print 'this string'
raise (4) Raise an exception when things go wrong. raise ValueError("No")
return Exit the function with a return value. def X(): return Y
try Try this block, and if exception, go to except. try: pass
while While loop. while X: pass
with With an expression as a variable do. with X as Y: pass
yield (1.1) Pause here and return to caller. def X(): yield Y; X().next()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 


1. with-as statement(也称context manager)


From: http://zhoutall.com/archives/325oop

 

(1) 常见写法,但比较啰嗦

try:
    f = open('xxx')
except:
    print 'fail to open'
    exit(-1)
try:
    do something
except:
    do something
finally:
    f.close()

 

(2) 使用封装如何?不用反复写finally,但致使:全部的函数都要被 controlled_execution( ) 下,太累赘。

def controlled_execution(callback):
    set things up
    try:
        callback(thing)
    finally:
        tear things down
 
def my_function(thing):
    do something
 
controlled_execution(my_function)

 

(3) 另外一个办法是使用生成器,可是只须要生成一次数据,咱们用for-in结构去调用他:

def controlled_execution():  //由于thing只有一个,因此yield语句只须要执行一次,从代码可读性也就是优雅的角度来讲这简直是糟糕透了
    set things up
    try:
        yield thing  //--> see "yield" finally:
        tear things down
         
for thing in controlled_execution():
    do something with thing

 

(4) with-as新方案

class controlled_execution:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback):
        tear things down
         
with controlled_execution() as thing:
        do something

当python执行这一句时,会调用__enter__函数,而后把该函数return的值传给as后指定的变量。以后,python会执行下面do something的语句块。最后不论在该语句块出现了什么异常,都会在离开时执行__exit__。

另外,__exit__除了用于tear things down,还能够进行异常的监控和处理,注意后几个参数。要跳过一个异常,只须要返回该函数True便可。

 

在python2.5及之后,file对象已经写好了__enter____exit__函数,咱们能够这样测试:

>>> f = open("x.txt")
>>> f
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.__enter__()
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.read(1)
'X'
>>> f.__exit__(None, None, None)
>>> f.read(1)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>

 

以后,咱们若是要打开文件并保证最后关闭他,只须要这么作:

with open("x.txt") as f:
    data = f.read()
    do something with data

 

若是有多个项,咱们能够这么写:

with open("x.txt") as f1, open('xxx.txt') as f2:
    do something with f1,f2

 

上文说了__exit__函数能够进行部分异常的处理,若是咱们不在这个函数中处理异常,他会正常抛出,这时候咱们能够这样写(python 2.7及以上版本,以前的版本参考使用contextlib.nested这个库函数):

try:
    with open( "a.txt" ) as f :
        do something
except xxxError:
    do something about exception

 

总之,with-as表达式极大的简化了每次写finally的工做,这对保持代码的优雅性是有极大帮助的。

 

 


1.1 yield


 From: http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/

  
清单 1. 简单输出斐波那契數列前 N 个数
 def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        print b         // 不太好! 其实改成yield就行了。
        a, b = b, a + b 
        n = n + 1

执行 fab(5),咱们能够获得以下输出:

 >>> fab(5) 
 1 
 1 
 2 
 3 
 5

结果没有问题,但有经验的开发者会指出,直接在 fab 函数中用 print 打印数字会致使该函数可复用性较差,由于 fab 函数返回 None,其余函数没法得到该函数生成的数列。

要提升 fab 函数的可复用性,最好不要直接打印出数列,而是返回一个 List。

 

如下是 fab 函数改写后的第二个版本:

清单 2. 输出斐波那契數列前 N 个数第二版
 def fab(max): 
    n, a, b = 0, 0, 1 
    L = [] 
    while n < max: 
        L.append(b) 
        a, b = b, a + b 
        n = n + 1 
    return L       // 暂用内存太大!

可使用以下方式打印出 fab 函数返回的 List:

 >>> for n in fab(5): 
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5

改写后的 fab 函数经过返回 List 能知足复用性的要求,可是更有经验的开发者会指出,该函数在运行中占用的内存会随着参数 max 的增大而增大。

 

若是要控制内存占用,最好不要用 List来保存中间结果,而是经过 iterable 对象来迭代。例如,在 Python2.x 中,代码:

清单 3. 经过 iterable 对象来迭代
for i in range(1000): pass  //会致使生成一个 1000 个元素的 List

for i in xrange(1000): pass // iterable对象是解决的办法!

在每次迭代中返回下一个数值,内存空间占用很小。由于 xrange 不返回 List,而是返回一个 iterable 对象。

 

利用 iterable 咱们能够把 fab 函数改写为一个支持 iterable 的 class,如下是第三个版本的 Fab:

清单 4. 第三个版本
 class Fab(object): 

    def __init__(self, max): 
        self.max = max 
        self.n, self.a, self.b = 0, 0, 1 

    def __iter__(self): 
        return self 

    def next(self): 
        if self.n < self.max: 
            r = self.b 
            self.a, self.b = self.b, self.a + self.b 
            self.n = self.n + 1 
            return r 
        raise StopIteration()

Fab 类经过 next() 不断返回数列的下一个数,内存占用始终为常数:

 >>> for n in Fab(5): 
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5

然而,使用 class 改写的这个版本,代码远远没有初版的 fab 函数来得简洁。

 

若是咱们想要保持初版 fab 函数的简洁性,同时又要得到 iterable 的效果,yield 就派上用场了:

清单 5. 使用 yield 的第四版
 def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b 
        # print b 
        a, b = b, a + b 
        n = n + 1 

第四个版本的 fab 和初版相比,仅仅把 print b 改成了 yield b,就在保持简洁性的同时得到了 iterable 的效果。

调用第四版的 fab 和第二版的 fab 彻底一致:

 >>> for n in fab(5):   // for执行一次函数,其实只是调用了函数内的一次运算;再调一次就再继续算一次!
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5
 

也能够手动调用 fab(5) 的 next() 方法(由于 fab(5) 是一个 generator 对象,该对象具备 next() 方法),这样咱们就能够更清楚地看到 fab 的执行流程:

清单 6. 执行流程
 >>> f = fab(5)  // fab(5) 是iterable function,这里就是指的fab的实例
 >>> f.next()    // 与清单4 中的next比较下,实际上是相同的思想
 1 
 >>> f.next() 
 1 
 >>> f.next() 
 2 
 >>> f.next() 
 3 
 >>> f.next() 
 5 
 >>> f.next() 
 Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
 StopIteration

当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。

 

 

 

 


2. exec


 From: http://blog.sina.com.cn/s/blog_76e94d210100w1bl.html

 

exec语句用来执行储存在字符串文件中的Python语句

例如,咱们能够在运行时生成一个包含Python代码的字符串,而后使用exec语句执行这些语句。

下面是一个简单的例子。

>>> exec 'print "Hello World"'
Hello World

 

eval语句用来计算存储在字符串中的有效Python表达式。下面是一个简单的例子。

>>> eval_r('2*3')
6

eval_r(str [ globals [ locals ]])函数将字符串str当成有效python表达式来求值,并返回计算结果。

一样地, exec语句将字符串str当成有效Python代码来执。.提供给exec的代码的名称空间和exec语句的名称空间相同。

最后,execfile(filename [, globals [, locals ]]) 函数能够用来执行一个文件。

 
  
>>> eval_r('3+4')
7
>>> exec 'a=100' 
>>> a 
100 
>>> execfile(r'd:\code\ex\test.py')
hello world!
>>>
 
  

默认的,eval_r(), exec, execfile() 所运行的代码都位于当前的名字空间中.

eval_r(), exec 和 execfile()函数 也能够接受一个或两个可选字典参数做为代码执行的全局名字空间局部名字空间。

 

 

 

 


2.1 Python命名空间和做用域


From: http://blog.cipherc.com/2015/04/25/python_namespace_and_scope/#assignment-rule

 

Namespace(只)是 从名字到对象的一个映射 (a mapping from name to objects) 

大部分namespace都是按Python中的字典来实现的。

 

有一些常见的namespace:built-in中的集合( abs() 函数等)、一个模块中的全局变量等。

从某种意义上来讲,一个对象(object)的全部属性(attribute)也构成了一个namespace.

 

在程序执行期间,可能(实际上是确定)会有多个名空间同时存在。不一样namespace的建立/销毁时间也不一样。此外,两个不一样namespace中的两个相同名字的变量之间没有任何联系。

 

scope

Scope是Python程序的一块文本区域(textual region)

在该文本区域中,对namespace是能够直接访问,而不须要经过属性来访问。

Scope是定义程序该如何搜索确切地“名字-对象”的名空间的层级关系。(The “scope” in Python defines the “hirerchy level” in which we search namespaces for certain “name-to-object” mappings.)

直接访问:对一个变量名的引用会在全部namespace中查找该变量,而不是经过属性访问。

属性访问:全部名字后加.的都认为是属性访问。如 module_name.func_name,须要指定 func_name 的名空间,属于属性访问;而 abs(-1),abs 属于直接访问。

  

scope 与 namespace的关系

在Python中,scope是由namespace按特定的层级结构组合起来的。

scope必定是namespace,但namespace不必定是scope。 // 感受namespace范围更大?

 

LEGB-rule

在一个Python程序运行中,至少有4个scopes是存在的

直接访问一个变量可能在这四个namespace中逐一搜索。

  • Local (innermost) 

    包含局部变量。
    好比一个函数/方法内部。

  • Enclosing

    包含了非局部(non-local)也非全局(non-global)的变量。
    好比两个嵌套函数,内层函数可能搜索外层函数的namespace,但该namespace对内层函数而言既非局部也非全局。

  • Global (next-to-last)

    当前脚本的最外层。
    好比当前模块的全局变量。

  • Built-in (outtermost)

    Python __builtin__ 模块。
    包含了内建的变量/关键字等。

     

* 那么,这么多的做用域,Python是按什么顺序搜索对应做用域的呢?

* 著名的”LEGB-rule”,即scope的搜索顺序:

Local -> Enclosing -> Global -> Built-in

 

当有一个变量在 local 域中找不到时,Python会找上一层的做用域,即 enclosing 域(该域不必定存在)。
enclosing 域还找不到的时候,再往上一层,搜索模块内的 global 域。最后,会在 built-in 域中搜索。
对于最终没有搜索到时,Python会抛出一个 NameError 异常。

做用域能够嵌套。好比模块导入时。

这也是为何不推荐使用 from a_module import * 的缘由,导入的变量可能被当前模块覆盖。

 

两条很重要的规则:

  1. 赋值语句一般隐式地会建立一个局部(local)变量,即使该变量名已存在于赋值语句发生的上一层做用域中;
  2. 若是没有global关键字声明变量,对一个变量的赋值老是认为该变量存在于最内层(innermost)的做用域中;

也就是说在做用域内有没有发生赋值是不同的。

 

可是,在这点上,Python 2和Python 3又有不一样, Python access non-local variable:

Python’s scoping rules indicate that a function defines a new scope level,
and a name is bound to a value in only one scope level – it is statically scoped.

…

In Python 2.x, it is not possible to modify a non-local variable;
1) you have either read-only access to a global or non-local variable,
2) or read-write access to a global variable by using the global statement,
3) or read-write access to a local variable (by default).

In Python 3.x, the nonlocal statement has been introduced with a similar effect
to global, but for an intermediate scope.
View Code

 

 

循环中的大坑

CipherChen@CIPHERC ~/Development/Workspace/test_python $ python2
Python 2.7.9 (default, Jan 25 2015, 13:42:57)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> for i in range(10): print i
...
0
1
2
3
4
5
6
7
8
9
>>> print i
9                <---- 大坑
>>>

for 后面跟着的变量(target list)在循环结束后是不会被删除的,
但若是 for 循环的序列为空,这些变量是彻底不会被赋值的。

这在Python中是个大坑啊。

避免这个坑的解决办法就是规范命名规范。
好比用于循环的变量尽可能使用单字符。在任何有疑议的状况能够直接将索引值初始化。

很不幸,Python 3中这点没有改变。

 

 

是否 引入新的做用域

class A(object):
    a = 3
    b = list(a + i for i in range(10))

cipher@Rachel ~/Development/Workspace/test_Python $ python a.py
Traceback (most recent call last): File "a.py", line 3, in <module> class A(object): File "a.py", line 5, in A b = list(a + i for i in range(10)) File "a.py", line 5, in <genexpr> b = list(a + i for i in range(10)) NameError: global name 'a' is not defined

class没有做用域(scope),但有一个局部的名空间(namespace),它并不构成一个做用域。
---- 这意味着在类定义中的表达式能够访问该名空间。

但在类体(class body)中, 对 b 的赋值表达式中,该表达式引入了一个新的做用域该做用域并不能访问类的名空间

就像刚刚说的,函数会引入一个新的做用域(以前定义的a失效了),因此报错!

class C(object):
    a = 2
    def foo(self):
        return a    # NameError: name 'a' is not defined, use return self.__class__.a

 

未引入新的做用域的例子,因此能够执行 print a

Python 2.7.9 (default, Jan 25 2015, 13:42:57)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> [a for a in range(3)]
[0, 1, 2]  
>>> print a   //未引入新的做用域 就能够直接读出持续的值 2

 

要解决这个问题(哪一个问题?),有几种解决办法:

1. 用生成器表达式

b = [a + i for i in range(10)]

 

2. 用函数/lambda引入新的做用域

b = (lambda a: ((a + i for i in range(10))))(a)

 

 

访问权限表 (难点

Can access class attributes Python 2 Python 3
list comp. iterable Y Y
list comp. expression Y N
gen expr. iterable Y Y
gen expr. expression N N
dict comp. iterable Y Y
dict comp. expression N N
 
 
 

3. lambda


 
简单来讲,编程中提到的 lambda 表达式,一般是在 须要一个函数,可是又不想费神去命名一个函数的场合下使用,也就是指 匿名函数
举一个普通的 Python 例子:将一个 list 里的每一个元素都平方:
map( lambda x: x*x, [y for y in range(10)] )
这个写法要好过
def sq(x):
    return x * x

map(sq, [y for y in range(10)])
由于后者多定义了一个(污染环境的)函数, 尤为若是这个函数只会使用一次的话
并且第一种写法实际上更易读,由于那个映射到列表上的函数具体是要作什么,很是一目了然。若是你仔细观察本身的代码,会发现这种场景其实很常见:你在某处就真的只须要一个能作一件事情的函数而已,连它叫什么名字都可有可无。Lambda 表达式就能够用来作这件事。

进一步讲,匿名函数本质上就是一个函数,它所抽象出来的东西是一组运算。这是什么意思呢?类比
a = [1, 2, 3]
f = lambda x : x + 1
你会发现, 等号右边的东西 彻底能够脱离 等号左边的东西而存在,等号左边的 名字只是右边之 实体的标识符。
若是你能习惯 [1, 2, 3] 单独存在,那么 lambda x : x + 1 也能单独存在其实也就不难理解了,它的意义就是给「某个数加一」这一运算自己。

如今回头来看 map() 函数,它能够将一个函数映射到一个可枚举类型上面。沿用上面给出的 a 和 f,能够写:
map(f, a)
也就是将函数 f 依次套用在 a 的每个元素上面,得到结果 [2, 3, 4]。如今用 lambda 表达式来替换 f,就变成:
map( lambda x : x + 1, [1, 2, 3] )
若是能将「遍历列表,给遇到的每一个元素都作某种 运算」的过程从一个循环里抽象出来成为一个函数 map,而后用 lambda 表达式将这种 运算做为参数传给 map 的话,考虑事情的思惟层级会高出一些来,须要顾及的细节也少了一点。
Python 之中,相似能用到 lambda 表达式的「高级」函数还有 reduce、filter 等等,不少语言也都有这样的工具(不过这些特性最好不要在 Python 中用太多,缘由详见 的评论部分)。
这种可以接受一个函数做为参数的函数叫作「高阶函数」(higher-order function),是来自函数式编程(functional programming)的思想。

和其余不少语言相比,Python 的 lambda 限制多多,最严重的当属它只能由一条表达式组成。这个限制主要是为了防止滥用,由于当人们发觉 lambda 很方便,就比较容易滥用,但是用多了会让程序看起来不那么清晰,毕竟每一个人 对于抽象层级的忍耐 / 理解程度都有所不一样。
 
 

 

lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。

lambda表达式是起到一个函数速写的做用。容许在代码内嵌入一个函数的定义。

以下例子:定义了一个lambda表达式,求三个数的和。

一种表达式,能够带参数的表达式,参数即给最外层的lambda的赋值,而后return表达式的计算结果。

  

  • lambda表达式也能够用在def函数中。

看例子:

这里定义了一个action函数,返回了一个lambda表达式。其中lambda表达式获取到了上层def做用域的变量名x的值。

a是action函数的返回值,a(22),便是调用了action返回的lambda表达式。

 

  • 这里也能够把def直接写成lambda形式。以下

 

 
lambdarange/list 的结合, 如何理解逻辑
 
 一个例子:用lambda表达式求n的阶乘。

 
 
 
 

3.1 map


 
map函数会根据提供的函数对指定序列作映射。
map函数的定义:
map(function, sequence[, sequence, ...]) -> list
经过定义能够看到,这个函数的第一个参数是一个函数,剩下的参数是一个或多个序列,返回值是一个集合。
function能够理解为是一个一对一或多对一函数,map的做用是以参数序列中的每个元素调用function函数,返回包含每次function函数返回值的list。
好比要对一个序列中的每一个元素进行平方运算:
map(lambda x: x ** 2, [1, 2, 3, 4, 5])

返回结果为:
[1, 4, 9, 16, 25]
在参数存在多个序列时,会依次以每一个序列中相同位置的元素作参数调用function函数。
好比要对两个序列中的元素依次求和。
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

map返回的list中第一个元素为,参数序列1的第一个元素加参数序列2中的第一个元素(1 + 2),
list中的第二个元素为,参数序列1中的第二个元素加参数序列2中的第二个元素(3 + 4),
依次类推,最后的返回结果为:
[3, 7, 11, 15, 19]
要注意function函数的 参数数量,要和map中提供的 集合数量相匹配。
 
若是集合长度不相等,会以最小长度对全部集合进行截取。
当函数为None时,操做和zip类似:
map(None, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

返回结果为:
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
 
 
 

3.2 map and reduce


 

提起map和reduce想必你们并不陌生,Google公司2003年提出了一个名为MapReduce的编程模型[1],用于处理大规模海量数据,并在以后普遍的应用于Google的各项应用中,2006年Apache的Hadoop项目[2]正式将MapReduce归入到项目中。

好吧,闲话少说,今天要介绍的是Python函数式编程中的另外两个内建函数 map()reduce(),而不是Google的MapReduce。

 

1.map()

格式:map( func, seq1[, seq2...] )

Python函数式编程中的map()函数是将func做用于seq中的每个元素,并用一个列表给出返回值。若是func为None,做用同zip()// 同3.1

当seq只有一个时,将func函数做用于这个seq的每一个元素上,获得一个新的seq。

下图说明了只有一个seq的时候map()函数是如何工做的(本文图片来源:《Core Python Programming (2nd edition)》)。

map-一个seq

能够看出,seq中的每一个元素都通过了func函数的做用,获得了func(seq[n])组成的列表。

 

下面举一个例子进行说明。假设咱们想要获得一个列表中数字%3的余数,那么能够写成下面的代码。 
# 使用map
print map( lambda x: x%3, range(6) )  # [0, 1, 2, 3, 4, 5] --> [0, 1, 2, 0, 1, 2]
 
#使用列表解析
print [x%3 for x in range(6)]         # [0, 1, 2, 0, 1, 2] 多于一个range,就没办法搞了

这里又和上次的filter()同样,使用了列表解析的方法代替map执行。那么,何时是列表解析没法代替map的呢

原来,当seq多于一个时,map能够并行地对每一个seq执行以下图所示的过程:

map-多个seq

也就是说每一个seq的同一位置的元素在执行过一个多元的func函数以后,获得一个返回值,这些返回值放在一个结果列表中。

下面的例子是求两个列表对应元素的积,能够想象,这是一种可能会常常出现的情况,而若是不是用map的话,就要使用一个for循环,依次对每一个位置执行该函数。

print map( lambda x, y: x*y, [1, 2, 3], [4, 5, 6] )  # [4, 10, 18]

 

也能够是一个元组。下面的代码不止实现了乘法,也实现了加法,并把积与和放在一个元组中。

还有就是上面说的func是None的状况,它的目的是将多个列表相同位置的元素归并到一个元组,在如今已经有了专用的函数zip()了。

print map( None, [1, 2, 3], [4, 5, 6] )  # [(1, 4), (2, 5), (3, 6)]
print zip( [1, 2, 3], [4, 5, 6] )        # [(1, 4), (2, 5), (3, 6)]

须要注意的是,不一样长度的多个seq是没法执行map函数的,会出现类型错误。

 

2.reduce()

格式:reduce( func, seq[, init] )

reduce函数即为化简,它是这样一个过程:

"每次迭代,将上一次的迭代结果(第一次时为init的元素,如没有init则为seq的第一个元素)与下一个元素一同执行一个二元的func函数。"

在reduce函数中,init是可选的,若是使用,则做为第一次迭代的第一个元素使用。

简单来讲,能够用这样一个形象化的式子来讲明:

reduce( func, [1, 2, 3] ) = func( func(1, 2), 3)

下面是reduce函数的工做过程图:

reduce

举个例子来讲,阶乘是一个常见的数学方法,Python中并无给出一个阶乘的内建函数,咱们可使用reduce实现一个阶乘的代码。

n = 5
print reduce(lambda x,y: x*y, range(1, n + 1))  # 120

那么,若是咱们但愿获得2倍阶乘的值呢?这就能够用到init这个可选参数了。

m = 2
n = 5
print reduce( lambda x,y: x*y, range( 1, n + 1 ), m )  # 240

 

 

 

4. raise


From: http://www.cnblogs.com/IPrograming/p/Python_error_handler.html

 

1. 抛出异常和自定义异常

Python用异常对象(exception object)表示异常状况,遇到错误后,会引起异常。

若是异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行。

 

1.1 raise 语句

Python中的raise 关键字用于引起一个异常,基本上和C#和Java中的throw关键字相同,以下所示:

复制代码
1 # -- coding: utf-8 --
2 
3 def ThorwErr():
4     raise Exception("抛出一个异常")     # 关键字后面是抛出是一个通用的异常类型(Exception),
5 
6 # Exception: 抛出一个异常
7 ThorwErr()raise
复制代码

通常来讲抛出的异常越详细越好,Python在exceptions模块内建了不少的异常类型,经过使用dir函数来查看exceptions中的异常类型,以下:

import exceptions

# ['ArithmeticError', 'AssertionError'.....]
print dir(exceptions)

 

传递异常

捕捉到了异常,可是又想从新引起它(传递异常),可使用不带参数的raise语句便可:

复制代码
 1 # -- coding: utf-8 --
 2 class MuffledCalculator:
 3     muffled = False
 4     def calc(self,expr):
 5         try:
 6             return eval(expr)
 7         except ZeroDivisionError:
 8             if self.muffled:
 9                 print 'Division by zero is illegal'
10             else:
11                 raise
复制代码

 

1.2 自定义异常类型

Python中也能够自定义本身的特殊类型的异常,只须要要从Exception类继承(直接或间接)便可:

class SomeCustomException(Exception):
    pass

 

2. 捕捉异常

和C#中的try/catch相似,Python中使用try/except关键字来捕捉异常,以下:

# -- coding: utf-8 --

try:
    print 2/0
except ZeroDivisionError:
    print '除数不能为0'

 

2.1 捕捉多个异常 (如下两种选择)

在一个except语句只捕捉其后声明的异常类型,若是可能会抛出的是其余类型的异常就须要再增长一个except语句了,或者也能够指定一个更通用的异常类型好比:Exception,以下:

复制代码
# -- coding: utf-8 --
try:
    print 2/'0'
except ZeroDivisionError:
    print '除数不能为0'
except Exception:
    print '其余类型异常'
复制代码

 为了捕获多个异常,除了声明多个except语句以外,还能够在一个except语句以后将多个异常做为元组列出来便可:

# -- coding: utf-8 --
try:
    print 2/'0'
except (ZeroDivisionError,Exception):
    print '发生了一个异常'

 

2.2获取异常信息

每一个异常都会有一些异常信息,通常状况下咱们应该把这些异常信息记录下来:

# -- coding: utf-8 --
try:
    print 2/'0'
except (ZeroDivisionError,Exception) as e:
    # unsupported operand type(s) for /: 'int' and 'str'
    print e

 

3. finally子句

finally子句和try子句联合使用可是和except语句不一样,finally无论try子句内部是否有异常发生,都会执行finally子句内的代码。全部通常状况下,finally本身经常用于关闭文件或者在Socket中。

复制代码
# -- coding: utf-8 --
try:
    print 2/'0'
except (ZeroDivisionError,Exception):
    print '发生了一个异常'
finally:
    print '无论是否发生异常都执行'
复制代码
相关文章
相关标签/搜索