Python 语法简介

2018-12-30 language python

这里介绍 Python 的基本的语法。

异常处理

python exception hierarchy

Python 的异常处理会按照继承方式处理,例如触发异常可以使用 raise ValueError("Some message") ,可以通过如下方式捕获异常。

# 捕获所有异常
try:
	//... ...
except Exception, e:
	print Exception, ":", e

# 查看异常栈信息
import traceback
try:
	//... ...
except:
	traceback.print_exc()

不同类型的异常有如下的继承关系。

BaseException
 |-BaseExceptionGroup
 |-GeneratorExit
 |-KeyboardInterrupt
 |-SystemExit
 `-Exception
   |-Exception
     |-ArithmeticError
     | |-FloatingPointError
     | |-OverflowError
     | `-ZeroDivisionError
     |-AssertionError
     |-AttributeError
     |-BufferError
     |-EOFError
     |-ExceptionGroup [BaseExceptionGroup]
     |-ImportError
     | `-ModuleNotFoundError
     |-LookupError
     | |-IndexError
     | `-KeyError
     |-MemoryError
     |-NameError
     | `-UnboundLocalError
     |-OSError
     | |-BlockingIOError
     | |-ChildProcessError
     | |-ConnectionError
     | | |-BrokenPipeError
     | | |-ConnectionAbortedError
     | | |-ConnectionRefusedError
     | | `-ConnectionResetError
     | |-FileExistsError
     | |-FileNotFoundError
     | |-InterrupedError
     | |-IsADirectoryError
     | |-NotADirectoryError
     | |-PermissionError
     | |-ProcessLookupError
     | `-TimeoutError
     |-ReferenceError
     |-RuntimeError
     | |-NotImplementedError
     | `-RecursionError
     |-StopAsyncIteration
     |-StopIteration
     |-SyntaxError
     | `-IndentationError
     |   `-TabError
     |-SystemError
     |-Typerror
     |-ValueError
     | `-UnicodeError
     |   |-UnicodeDecodeError
     |   |-UnicodeEncodeError
     |   `-UnicodeTranslateError
     |-Warning
       |-BytesWarning
       |-DeprecationWarning
       |-EncodingWarning
       |-FutureWarning
       |-ImportWarning
       |-PendingDeprecationWarning
       |-ResourceWarning
       |-RuntimeWarning
       |-SyntaxWarning
       |-UnicodeWarning
       `-UserWarning

示例代码

如下整理常用的使用场景。

#!/usr/bin/python
"This is a module to display how exception works."      # called by module.__doc__

class SimpleError(Exception):
    pass

class MyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)


def examples_except():
    '''If the exception or error not catched by any
       code, then the program will exit.'''

    try:  # normal: ACD, except: ABD
        print "This is normal operation."          # A
        #raise TypeError
        #raise IOError, 'Opps, IO error'
        #raise NameError, (2, 'Opps, Name error')
        raise MyError, 8  # OR raise MyError(8)
    except IOError:
        print 'Ooooh, IOError'
        # raise   # reraise the exception, no arguments.
        retval = 'Exception IOError:'              # B
    except TypeError, e:
        print 'Ooooh, TypeError:', e # or e.args[0], e.args[1]
        #print dir(e)
        retval = 'Exception TypeError:', e         # B
    except NameError, (errno, e):
        print 'Ooooh, NameError:', errno, e
        retval = 'Exception IOError:', e           # B
    except MyError, e:
        print 'Ooooh, MyError:', e.value
        retval = 'Exception MyError'               # B
    except (SyntaxError, TypeError):
        print 'Ooooh, SyntaxError/TypeError'
        retval = 'Exception ValueError,TypeError'  # B
    except (KeyError, TypeError), e:
        print 'Ooooh, KeyError/TypeError'
        retval = str(diag) # Maybe e.args[0] and e.args[1] can use.
    except Exception:  # or 'except:', or 'BaseException:' all errors.
        print 'Ooooh, Exception'
        retval = 'some errors cannot identify'
    else:   # This is optional, means there is no error.
        print 'This is also normal operation.'     # C
    finally: # This always execute.
        print 'Normal operation.'                  # D
    # NOTE: if using 'try ... finally ...', when finally block
    #       finished, the exceptions will be reraised.

    import time
    print "\ntest for Ctrl-C"
    try:
        try:
            time.sleep(20)
        except KeyboardInterrupt, e:
            print "inner"
            raise
    except KeyboardInterrupt, e:
        print "outer"

    print
    try:
        assert 1 == 0 , 'One does not equal zero silly!'
    except AssertionError, args:
        print '%s: %s' % (args.__class__.__name__, args)

if __name__ == '__main__': # main function, else module name.
    ret = examples_except()

类 Class

StaticMethod VS. ClassMethod

两者十分相似,但在用法上依然有一些明显的区别:A) ClassMethod 必须有一个指向类对象的引用作为第一个参数;B) StaticMethod 可以没有任何参数。

如下是几个示例:

# -*- coding: utf8 -*-

class Date(object):

    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year

    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return cls(day, month, year)

    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999

print Date.from_string('11-09-2012')
print Date.is_date_valid('11-09-2012')

也就是说,StaticMethod 没有任何必选参数,而 ClassMethod 第一个参数永远是 cls, InstanceMethod 第一个参数永远是 self。

所以,从静态方法的使用中可以看出,不会访问到 class 本身,它基本上只是一个函数,在语法上就像一个方法一样,相反 ClassMethod 会访问 cls, InstanceMethod 会访问 self。

lambda

通过 lambda 可以构造一个简单的匿名函数,几乎可以在任何需要函数的地方定义,在很多场景下会使得代码简单很多。

通常只有一个简单的表达式,做简单的运算。

>>> g = lambda x, y, z : (x + y) ** z
>>> g(1, 2, 3)
27

其功能和函数十分相似,因为是匿名函数,如果没有变量接收,那么就会无法使用,但是可以作为 list 或者 dict 的成员使用。

可以定义一系列的幂函数。

>>> fpowers = [lambda x: x, lambda x: x**2, lambda x: x**3]
>>> fpowers[0]
<function <lambda> at 0x7f0d04fe2500>
>>> fpowers[2](3)
27

在一些聚合函数中,例如 filtermapreduce 中,也很好使用。

>>> data = [2, 3, 9]
>>> filter(lambda x: x % 3 == 0, data)   # 过滤3的倍数
[3, 9]
>>> map(lambda x: x * 2, data)           # 所有成员乘以2
[4, 6, 18]
>>> reduce(lambda x, y: x + y, data)     # 所有成员的和
14

另外,在对象遍历处理方面,还可以使用 for..in..if 语法,相比来说更加强大而且易读,例如上面的例子。

>>> [x * 2 for x in data]
[4, 6, 18]
>>> [x for x in data if x % 3 == 0]
[3, 9]