python3初探

官方网站:https://www.python.org/
类库大全:https://pypi.python.org/pypi
基础类库:https://docs.python.org/3/library/index.html html

简介

Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。python

Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议[1] 。linux

Python的哲学是“作一件事情有且只有一种方法”(There should be one– and preferably only one –obvious way to do it.)。shell

Python是彻底面向对象的语言。函数、模块、数字、字符串都是对象。而且彻底支持继承、重载、派生、多继承,有益于加强源代码的复用性。Python支持重载运算符和动态类型。数据库

Python具备丰富和强大的库。它常被昵称为胶水语言,可以把用其余语言制做的各类模块(尤为是C/C++)很轻松地联结在一块儿。常见的一种应用情形是,使用Python快速生成程序的原型(有时甚至是程序的最终界面),而后对其中有特别要求的部分,用更合适的语言改写,好比3D游戏中的图形渲染模块,性能要求特别高,就能够用C/C++重写,然后封装为Python能够调用的扩展类库。须要注意的是在您使用扩展类库时可能须要考虑平台问题,某些可能不提供跨平台的实现。express

因为Python语言的简洁、易读以及可扩展性,在国外用Python作科学计算的研究机构日益增多,一些知名大学已经采用Python教授程序设计课程。例如卡耐基梅隆大学的编程基础、麻省理工学院的计算机科学及编程导论就使用Python语言讲授。众多开源的科学计算软件包都提供了Python的调用接口,例如著名的计算机视觉库OpenCV、三维可视化库VTK、医学图像处理库ITK。而Python专用的科学计算扩展库就更多了,例如以下3个十分经典的科学计算扩展库:NumPy、SciPy和matplotlib,它们分别为Python提供了快速数组处理、数值运算以及绘图功能。所以Python语言及其众多的扩展库所构成的开发环境十分适合工程技术、科研人员处理实验数据、制做图表,甚至开发科学计算应用程序。编程

Python开发人员尽可能避开不成熟或者不重要的优化。一些针对非重要部位的加快运行速度的补丁一般不会被合并到Python内。因此不少人认为Python很慢。不过,根据二八定律,大多数程序对速度要求不高。在某些对运行速度要求很高的状况,Python设计师倾向于使用JIT技术,或者用使用C/C++语言改写这部分程序。bootstrap

安装

curl -R -O https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
tar zxf Python-3.5.1.tgz z表明gzip的压缩包;x表明解压;v表明显示过程信息;f表明后面接的是文件
cd Python-3.5.1
./configure
make
make install数组

设置环境变量
export PATH=”$PATH:/usr/local/bin/python3” app

安装完成

leestar@leestar-ThinkPad-SL410:~$ python3
python3
Python 3.5.1 (default, Mar 14 2016, 22:23:55)
[GCC 5.2.1 20151010] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>>

python包管理工具pypi
https://pip.pypa.io/en/latest/installing/

curl -R -O https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
pip -V
pip 8.1.0 from /usr/local/lib/python2.7/dist-packages (python 2.7)

解释器

Linux/Unix的系统上,Python解释器一般被安装在 /usr/local/bin/python3.5 这样的有效路径(目录)里。
咱们能够将路径 /usr/local/bin 添加到您的Linux/Unix操做系统的环境变量中,这样您就能够经过 shell 终端输入下面的命令来启动 Python 。

交互式编程

咱们能够在命令提示符中输入”python3”命令来启动Python解释器:

leestar@leestar-ThinkPad-SL410:~$ python3
python3
Python 3.5.1 (default, Mar 14 2016, 22:23:55)
[GCC 5.2.1 20151010] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>>

当键入一个多行结构时,续行是必须的。咱们能够看下以下 if 语句:

>>> the_world_is_flat = True
>>> if the_world_is_flat:
… print(“Be careful not to fall off!”)

Be careful not to fall off!

脚本式编程

经过如下命令执行该脚本:

python hello.py

在Linux/Unix系统中,你能够在脚本顶部添加如下命令让Python脚本能够像SHELL脚本同样可直接执行:

#! /usr/bin/python3
而后修改脚本权限,使其有执行权限,命令以下:
$ chmod +x hello.py
执行./hello.py

基础语法

编码

默认状况下,Python 3源码文件以 UTF-8 编码,全部字符串都是 unicode 字符串。 固然你也能够为源码文件指定不一样的编码:

# -- coding: cp-1252 --

标识符

  • 第一个字符必须是字母表中字母或下划线’_’。
  • 标识符的其余的部分有字母、数字和下划线组成。
  • 标识符对大小写敏感。

关键字

Python的标准库提供了一个keyword module,能够输出当前版本的全部关键字:

>>> import keyword
>>> keyword.kwlist [‘False’, ‘None’, ‘True’, ‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]

注释

Python中单行注释以#开头,多行注释用三个单引号(”’)或者三个双引号(”“”)将注释括起来。

  1. #!/usr/bin/python3
  2. '''
  3. 这是多行注释,用三个单引号
  4. 这是多行注释,用三个单引号
  5. 这是多行注释,用三个单引号
  6. '''
  7. print("Hello, World!")

行与缩进

python最具特点的就是使用缩进来表示代码块。缩进的空格数是可变的,可是同一个代码块的语句必须包含相同的缩进空格数。

基本数据类型

Python中的变量不须要声明。每一个变量在使用前都必须赋值,变量赋值之后该变量才会被建立。
在Python中,变量就是变量,它没有类型,咱们所说的”类型”是变量所指的内存中对象的类型。
Python 3中有六个标准的数据类型:
Numbers(数字)String(字符串)List(列表)Tuple(元组)Sets(集合)Dictionaries(字典)

Numbers(数字)

Python 3支持int、float、bool、complex(复数)。
数值类型的赋值和计算都是很直观的,就像大多数语言同样。内置的type()函数能够用来查询变量所指的对象类型。

2 / 4 # 除法,获得一个浮点数 0.5
2 // 4 # 除法,获得一个整数 0
2 ** 5 # 乘方 32

一、Python能够同时为多个变量赋值,如a, b = 1, 2。
二、一个变量能够经过赋值指向不一样类型的对象。
三、数值的除法(/)老是返回一个浮点数,要获取整数使用//操做符。
四、在混合计算时,Python会把整型转换成为浮点数。

String(字符串)

Python中的字符串str用单引号(’ ‘)或双引号(” “)括起来,同时使用反斜杠()转义特殊字符。
若是你不想让反斜杠发生转义,能够在字符串前面添加一个r,表示原始字符串:

>>> print(r’C:\some\name’)
C:\some\name

另外,反斜杠能够做为续行符,表示下一行是上一行的延续。还可使用”“”…”“”或者”’…”’跨越多行。
字符串可使用 + 运算符串链接在一块儿,或者用 * 运算符重复:

>>> print(‘str’+’ing’, ‘my’*3)
string mymymy

Python中的字符串有两种索引方式,第一种是从左往右,从0开始依次增长;第二种是从右往左,从-1开始依次减小。
注意,没有单独的字符类型,一个字符就是长度为1的字符串。

>>> word = ‘Python’
>>> print(word[0], word[5])
P n
>>> print(word[-1], word[-6])
n P

还能够对字符串进行切片,获取一段子串。用冒号分隔两个索引,形式为变量[头下标:尾下标]。
截取的范围是前闭后开的,而且两个索引均可以省略:

>>> word = ‘ilovepython’
>>> word[1:5]
‘love’
>>> word[:]
‘ilovepython’
>>> word[5:]
‘python’
>>> word[-10:-6]
‘love’

与C字符串不一样的是,Python字符串不能被改变。向一个索引位置赋值,好比word[0] = ‘m’会致使错误。
一、反斜杠能够用来转义,使用r可让反斜杠不发生转义。
二、字符串能够用+运算符链接在一块儿,用*运算符重复。
三、Python中的字符串有两种索引方式,从左往右以0开始,从右往左以-1开始。
四、Python中的字符串不能改变。

List(列表)

列表是写在方括号之间、用逗号分隔开的元素列表。列表中元素的类型能够不相同
和字符串同样,列表一样能够被索引和切片,列表被切片后返回一个包含所需元素的新列表。
列表还支持串联操做,使用+操做符:

>>> a=[1,2,3,4]
>>> a+[5,6,7]
[1, 2, 3, 4, 5, 6, 7]

与Python字符串不同的是,列表中的元素是能够改变的
一、List写在方括号之间,元素用逗号隔开。
二、和字符串同样,list能够被索引和切片。
三、List可使用+操做符进行拼接。
四、List中的元素是能够改变的。

Tuple(元组)

元组(tuple)与列表相似,不一样之处在于元组的元素不能修改。元组写在小括号里,元素之间用逗号隔开。
元组中的元素类型也能够不相同:

>>> a = (1991, 2014, ‘physics’, ‘math’)

元组与字符串相似,能够被索引且下标索引从0开始,也能够进行截取/切片。
其实,能够把字符串看做一种特殊的元组。
虽然tuple的元素不可改变,但它能够包含可变的对象,好比list列表。
构造包含0个或1个元素的tuple是个特殊的问题,因此有一些额外的语法规则:

  1. tup1 =()# 空元组
  2. tup2 =(20,)# 一个元素,须要在元素后添加逗号

元组也支持用+操做符,string、list和tuple都属于sequence(序列)。
一、与字符串同样,元组的元素不能修改。
二、元组也能够被索引和切片,方法同样。
三、注意构造包含0或1个元素的元组的特殊语法规则。
四、元组也可使用+操做符进行拼接。

Sets(集合)

集合(set)是一个无序不重复元素的集。
基本功能是进行成员关系测试和消除重复元素。重复的元素被自动去掉
可使用大括号 或者 set()函数建立set集合,注意:建立一个空集合必须用 set() 而不是 { },由于{ }是用来建立一个空字典。

>>> student = {‘Tom’, ‘Jim’, ‘Mary’, ‘Tom’, ‘Jack’, ‘Rose’}
>>> print(student) # 重复的元素被自动去掉
{‘Jim’, ‘Jack’, ‘Mary’, ‘Tom’, ‘Rose’}
>>> ‘Rose’ in student # membership testing(成员测试)
True
>>> # set能够进行集合运算 …
>>> a = set(‘abracadabra’)
>>> b = set(‘alacazam’)
>>> a {‘a’, ‘b’, ‘c’, ‘d’, ‘r’}
>>> a - b # a和b的差集
{‘b’, ‘d’, ‘r’}
>>> a | b # a和b的并集
{‘l’, ‘m’, ‘a’, ‘b’, ‘c’, ‘d’, ‘z’, ‘r’}
>>> a & b # a和b的交集
{‘a’, ‘c’}
>>> a ^ b # a和b中不一样时存在的元素
{‘l’, ‘m’, ‘b’, ‘d’, ‘z’, ‘r’}

Dictionaries(字典)

字典(dictionary)是Python中另外一个很是有用的内置数据类型。
字典是一种映射类型(mapping type),它是一个无序的键 : 值对集合。
关键字必须使用不可变类型,也就是说list和包含可变类型的tuple不能作关键字。
在同一个字典中,关键字还必须互不相同。

>>> dic = {} # 建立空字典
>>> tel = {‘Jack’:1557, ‘Tom’:1320, ‘Rose’:1886}
>>> tel
{‘Tom’: 1320, ‘Jack’: 1557, ‘Rose’: 1886}
>>> tel[‘Jack’] # 主要的操做:经过key查询
1557
>>> del tel[‘Rose’] # 删除一个键值对
>>> tel[‘Mary’] = 4127 # 添加一个键值对
>>> tel
{‘Tom’: 1320, ‘Jack’: 1557, ‘Mary’: 4127}
>>> list(tel.keys()) # 返回全部key组成的list
[‘Tom’, ‘Jack’, ‘Mary’]
>>> sorted(tel.keys()) # 按key排序
[‘Jack’, ‘Mary’, ‘Tom’]
>>> ‘Tom’ in tel # 成员测试
True
>>> ‘Mary’ not in tel # 成员测试
False

构造函数 dict() 直接从键值对sequence中构建字典,固然也能够进行推导

>>> dict([(‘sape’, 4139), (‘guido’, 4127), (‘jack’, 4098)])
{‘jack’: 4098, ‘sape’: 4139, ‘guido’: 4127}
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
>>> dict(sape=4139, guido=4127, jack=4098)
{‘jack’: 4098, ‘sape’: 4139, ‘guido’: 4127}

一、字典是一种映射类型,它的元素是键值对。
二、字典的关键字必须为不可变类型,且不能重复。
三、建立空字典使用{ }。

条件控制

  1. if condition_1:
  2. statement_block_1
  3. elif condition_2:
  4. statement_block_2
  5. else:
  6. statement_block_3

一、每一个条件后面要使用冒号(:),表示接下来是知足条件后要执行的语句块。
二、使用缩进来划分语句块,相同缩进数的语句在一块儿组成一个语句块。
三、在Python中没有switch – case语句。

循环

while 循环

  1. while判断条件:
  2. statements

一样须要注意冒号和缩进。另外,在Python中没有do..while循环。

for语句

Python for循环能够遍历任何序列的项目,如一个列表或者一个字符串。

  1. for<variable>in<sequence>:
  2. <statements>
  3. else:
  4. <statements>

break语句用于跳出当前循环体

range()函数

若是你须要遍历数字序列,可使用内置range()函数。它会生成数列

>>> for i in range(5):
… print(i)

0
1
2
3
4
>>> for i in range(0, 10, 3) :
… print(i)

0
3
6
9

结合range()和len()函数以遍历一个序列的索引

>>> a = [‘Mary’, ‘had’, ‘a’, ‘little’, ‘lamb’]>>> for i in range(len(a)):
… print(i, a[i])

0 Mary
1 had
2 a
3 little
4 lamb

break和continue语句及循环中的else子句

break语句能够跳出for和while的循环体。若是你从for或while循环中终止,任何对应的循环else块将不执行。
continue语句被用来告诉Python跳过当前循环块中的剩余语句,而后继续进行下一轮循环。
循环语句能够有else子句;它在穷尽列表(以for循环)或条件变为假(以while循环)循环终止时被执行,但循环被break终止时不执行.以下查寻质数的循环例子:

pass语句

pass语句什么都不作。它只在语法上须要一条语句但程序不须要任何操做时使用.例如:

>>> while True:
… pass # 等待键盘中断 (Ctrl+C)

函数

Python 定义函数使用 def 关键字,通常格式以下:

  1. def area(width, height):
  2. return width * height
  3. def print_welcome(name):
  4. print("Welcome", name)
  5. print_welcome("Fred")
  6. w =4
  7. h =5
  8. print("width =", w," height =", h," area =", area(w, h))
  9. WelcomeFred
  10. width =4 height =5 area =20

变量做用域

定义在函数内部的变量拥有一个局部做用域,定义在函数外的拥有全局做用域。

  1. #!/usr/bin/env python3
  2. a =4# 全局变量
  3. def print_func1():
  4. a =17# 局部变量
  5. print("in print_func a = ", a)
  6. def print_func2():
  7. print("in print_func a = ", a)
  8. print_func1()
  9. print_func2()
  10. print("a = ", a)
  11. in print_func a =17
  12. in print_func a =4
  13. a =4

缺省参数

函数也可使用 kwarg=value 的关键字参数形式被调用

  1. def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
  2. print("-- This parrot wouldn't", action, end=' ')
  3. print("if you put", voltage,"volts through it.")
  4. print("-- Lovely plumage, the", type)
  5. print("-- It's", state,"!")
  6. parrot(1000)# 1 positional argument
  7. parrot(voltage=1000)# 1 keyword argument
  8. parrot(voltage=1000000, action='VOOOOOM')# 2 keyword arguments
  9. parrot(action='VOOOOOM', voltage=1000000)# 2 keyword arguments
  10. parrot('a million','bereft of life','jump')# 3 positional arguments
  11. parrot('a thousand', state='pushing up the daisies')# 1 positional, 1 keyword

返回值

  1. def return_sum(x,y):
  2. c = x + y
  3. return c
  4. res = return_sum(4,5)
  5. print(res)

可变参数

  1. def arithmetic_mean(*args):
  2. sum =0
  3. for x in args:
  4. sum += x
  5. return sum
  6. print(arithmetic_mean(45,32,89,78))
  7. print(arithmetic_mean(8989.8,78787.78,3453,78778.73))
  8. print(arithmetic_mean(45,32))
  9. print(arithmetic_mean(45))
  10. print(arithmetic_mean())
  11. 244
  12. 170009.31
  13. 77
  14. 45
  15. 0

匿名函数

匿名函数lambda x: x * x实际上就是:

  1. def f(x):
  2. return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
用匿名函数有个好处,由于函数没有名字,没必要担忧函数名冲突。此外,匿名函数也是一个函数对象,也能够把匿名函数赋值给一个变量,再利用变量来调用该函数

>>> f = lambda x: x * x
>>> f
<function at 0x101c6ef28>
>>> f(5)
25

map/reduce

Python内建了map()和reduce()函数。
咱们先看map。map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次做用到序列的每一个元素,并把结果做为新的Iterator返回。
举例说明,好比咱们有一个函数f(x)=x2,要把这个函数做用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就能够用map()实现以下:
map

  1. >>>def f(x):
  2. ...return x * x
  3. ...
  4. >>> r = map(f,[1,2,3,4,5,6,7,8,9])
  5. >>> list(r)
  6. [1,4,9,16,25,36,49,64,81]

再看reduce的用法。reduce把一个函数做用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素作累积计算

  1. >>>from functools import reduce
  2. >>>def add(x, y):
  3. ...return x + y
  4. ...
  5. >>> reduce(add,[1,3,5,7,9])
  6. 25

和其它编程语言相比,Python 在尽量不增长新的语法和语义的状况下加入了类机制。
Python中的类提供了面向对象编程的全部基本功能:类的继承机制容许多个基类,派生类能够覆盖基类中的任何方法,方法中能够调用基类中的同名方法。
对象能够包含任意数量和类型的数据。

类定义了 init() 方法的话,类的实例化操做会自动调用 init() 方法。

  1. class people:
  2. #定义基本属性
  3. name =''
  4. age =0
  5. #定义私有属性,私有属性在类外部没法直接进行访问
  6. __weight =0
  7. #定义构造方法
  8. def __init__(self,n,a,w):
  9. self.name = n
  10. self.age = a
  11. self.__weight = w
  12. #在类地内部,使用def关键字能够为类定义一个方法,与通常函数定义不一样,类方法必须包含参数self,且为第一个参数
  13. def speak(self):
  14. print("%s is speaking: I am %d years old"%(self.name,self.age))
  15. p = people('tom',10,30)
  16. p.speak()

继承

  1. #单继承示例
  2. class student(people):
  3. grade =''
  4. def __init__(self,n,a,w,g):
  5. #调用父类的构函
  6. people.__init__(self,n,a,w)
  7. self.grade = g
  8. #覆写父类的方法
  9. def speak(self):
  10. print("%s is speaking: I am %d years old,and I am in grade %d"%(self.name,self.age,self.grade))
  11. s = student('ken',20,60,3)
  12. s.speak()

Python有限的支持多继承形式。
须要注意圆括号中父类的顺序,如果父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。

  1. #另外一个类,多重继承以前的准备
  2. class speaker():
  3. topic =''
  4. name =''
  5. def __init__(self,n,t):
  6. self.name = n
  7. self.topic = t
  8. def speak(self):
  9. print("I am %s,I am a speaker!My topic is %s"%(self.name,self.topic))
  10. #多重继承
  11. class sample(speaker,student):
  12. a =''
  13. def __init__(self,n,a,w,g,t):
  14. student.__init__(self,n,a,w,g)
  15. speaker.__init__(self,n,t)
  16. test = sample("Tim",25,80,4,"Python")
  17. test.speak()#方法名同,默认调用的是在括号中排前地父类的方法

私有属性与方法

__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 slef.__private_methods。

内置方法以下:
init 构造函数,在生成对象时调用
del 析构函数,释放对象时使用
repr 打印,转换
__setitem__按照索引赋值
__getitem__按照索引获取值
__len__得到长度
__cmp__比较运算
__call__函数调用
__add__加运算
__sub__减运算
__mul__乘运算
__div__除运算
__mod__求余运算
__pow__称方

元类type

type()函数能够查看一个类型或变量的类型,Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello。
咱们说class的定义是运行时动态建立的,而建立class的方法就是使用type()函数。
type()函数既能够返回一个对象的类型,又能够建立出新的类型,好比,咱们能够经过type()函数建立出Hello类,而无需经过class Hello(object)…的定义

  1. >>>def fn(self, name='world'):# 先定义函数
  2. ...print('Hello, %s.'% name)
  3. ...
  4. >>>Hello= type('Hello',(object,), dict(hello=fn))# 建立Hello class
  5. >>> h =Hello()
  6. >>> h.hello()
  7. Hello, world.
  8. >>>print(type(Hello))
  9. <class'type'>
  10. >>>print(type(h))
  11. <class'__main__.Hello'>

要建立一个class对象,type()函数依次传入3个参数:

  1. class的名称;
  2. 继承的父类集合,注意Python支持多重继承,若是只有一个父类,别忘了tuple的单元素写法;
  3. class的方法名称与函数绑定,这里咱们把函数fn绑定到方法名hello上。
    经过type()函数建立的类和直接写class是彻底同样的,由于Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,而后调用type()函数建立出class。

正常状况下,咱们都用class Xxx…来定义类,可是,type()函数也容许咱们动态建立出类来,也就是说,动态语言自己支持运行期动态建立类,这和静态语言有很是大的不一样,要在静态语言运行期建立类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会很是复杂。

metaclass
除了使用type()动态建立类之外,要控制类的建立行为,还可使用metaclass。
metaclass,直译为元类,简单的解释就是:
当咱们定义了类之后,就能够根据这个类建立出实例,因此:先定义类,而后建立实例。
可是若是咱们想建立出类呢?那就必须根据metaclass建立出类,因此:先定义metaclass,而后建立类。
链接起来就是:先定义metaclass,就能够建立类,最后建立实例。
因此,metaclass容许你建立类或者修改类。换句话说,你能够把类当作是metaclass建立出来的“实例”。

定义ListMetaclass,按照默认习惯,metaclass的类名老是以Metaclass结尾,以便清楚地表示这是一个metaclass

  1. # metaclass是类的模板,因此必须从`type`类型派生:
  2. classListMetaclass(type):
  3. def __new__(cls, name, bases, attrs):
  4. attrs['add']=lambda self, value: self.append(value)
  5. return type.__new__(cls, name, bases, attrs)
  6. classMyList(list, metaclass=ListMetaclass):
  7. pass
  8. >>> L =MyList()
  9. >>> L.add(1)
  10. >> L
  11. [1]

动态修改有什么意义?直接在MyList定义中写上add()方法不是更简单吗?正常状况下,确实应该直接写,经过metaclass修改纯属变态。
可是,总会遇到须要经过metaclass修改类定义的。ORM就是一个典型的例子。
ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操做SQL语句。
要编写一个ORM框架,全部的类都只能动态定义,由于只有使用者才能根据表的结构定义出对应的类来。

@property

Python内置的@property装饰器就是负责把一个方法变成属性调用

  1. classStudent(object):
  2. @property
  3. def score(self):
  4. return self._score
  5. @score.setter
  6. def score(self, value):
  7. ifnot isinstance(value, int):
  8. raiseValueError('score must be an integer!')
  9. if value <0or value >100:
  10. raiseValueError('score must between 0 ~ 100!')
  11. self._score = value
  12. >>> s =Student()
  13. >>> s.score =60# OK,实际转化为s.set_score(60)
  14. >>> s.score # OK,实际转化为s.get_score()
  15. 60
  16. >>> s.score =9999
  17. Traceback(most recent call last):
  18. ...
  19. ValueError: score must between 0~100!

注意到这个神奇的@property,咱们在对实例属性操做的时候,就知道该属性极可能不是直接暴露的,而是经过getter和setter方法来实现的
还能够定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

  1. classStudent(object):
  2. @property
  3. def birth(self):
  4. return self._birth
  5. @birth.setter
  6. def birth(self, value):
  7. self._birth = value
  8. @property
  9. def age(self):
  10. return2015- self._birth

异常处理

让用户输入一个合法的整数,可是容许用户中断这个程序(使用 Control-C 或者操做系统提供的方法)。用户中断的信息会引起一个 KeyboardInterrupt 异常。

  1. whileTrue:
  2. try:
  3. x = int(input("Please enter a number: "))
  4. break
  5. exceptValueError:
  6. print("Oops! That was no valid number. Try again ")

try语句按照以下方式工做;

  1. 首先,执行try子句(在关键字try和关键字except之间的语句)
  2. 若是没有异常发生,忽略except子句,try子句执行后结束。
  3. 若是在执行try子句的过程当中发生了异常,那么try子句余下的部分将被忽略。若是异常的类型和 except 以后的名称相符,那么对应的except子句将被执行。最后执行 try 语句以后的代码。
  4. 若是一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。
    一个 try 语句可能包含多个except子句,分别来处理不一样的特定的异常。最多只有一个分支会被执行。
    处理程序将只针对对应的try子句中的异常进行处理,而不是其余的 try 的处理程序中的异常。

一个except子句能够同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

  1. except(RuntimeError,TypeError,NameError):
  2. pass

最后一个except子句能够忽略异常的名称,它将被看成通配符使用。你可使用这种方法打印一个错误信息,而后再次把异常抛出。

  1. import sys
  2. try:
  3. f = open('myfile.txt')
  4. s = f.readline()
  5. i = int(s.strip())
  6. exceptOSErroras err:
  7. print("OS error: {0}".format(err))
  8. exceptValueError:
  9. print("Could not convert data to an integer.")
  10. except:
  11. print("Unexpected error:", sys.exc_info()[0])
  12. raise

try except 语句还有一个可选的else子句,若是使用这个子句,那么必须放在全部的except子句以后。这个子句将在try子句没有发生任何异常的时候执行。

  1. for arg in sys.argv[1:]:
  2. try:
  3. f = open(arg,'r')
  4. exceptIOError:
  5. print('cannot open', arg)
  6. else:
  7. print(arg,'has', len(f.readlines()),'lines')
  8. f.close()

抛出异常

Python 使用 raise 语句抛出一个指定的异常。
raise 惟一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。

  1. try:
  2. raiseNameError('HiThere')
  3. exceptNameError:
  4. print('An exception flew by!')
  5. raise

自定义异常

  1. classError(Exception):
  2. """Base class for exceptions in this module."""
  3. pass
  4. classInputError(Error):
  5. """Exception raised for errors in the input.
  6. Attributes:
  7. expression -- input expression in which the error occurred
  8. message -- explanation of the error
  9. """
  10. def __init__(self, expression, message):
  11. self.expression = expression
  12. self.message = message
  13. classTransitionError(Error):
  14. """Raised when an operation attempts a state transition that's not
  15. allowed.
  16. Attributes:
  17. previous -- state at beginning of transition
  18. next -- attempted new state
  19. message -- explanation of why the specific transition is not allowed
  20. """
  21. def __init__(self, previous, next, message):
  22. self.previous = previous
  23. self.next = next
  24. self.message = message

finally与with

无论try子句里面有没有发生异常,finally子句都会执行。
若是一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后再次被抛出。

  1. >>>def divide(x, y):
  2. try:
  3. result = x / y
  4. exceptZeroDivisionError:
  5. print("division by zero!")
  6. else:
  7. print("result is", result)
  8. finally:
  9. print("executing finally clause")
  10. >>> divide(2,1)
  11. result is2.0
  12. executing finally clause
  13. >>> divide(2,0)
  14. division by zero!
  15. executing finally clause
  16. >>> divide("2","1")
  17. executing finally clause
  18. Traceback(most recent call last):
  19. File"<stdin>", line 1,in?
  20. File"<stdin>", line 3,in divide
  21. TypeError: unsupported operand type(s)for/:'str'and'str'

一些对象定义了标准的清理行为,不管系统是否成功的使用了它,一旦不须要它了,那么这个标准的清理行为就会执行。
当执行完毕后,文件会保持打开状态,并无被关闭。
关键词 with 语句就能够保证诸如文件之类的对象在使用完以后必定会正确的执行他的清理方法(相似C#中的using)

  1. with open("myfile.txt")as f:
  2. for line in f:
  3. print(line, end="")

自定义模块

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ ='Michael Liao'
  5. import sys
  6. def test():
  7. args = sys.argv
  8. if len(args)==1:
  9. print('Hello, world!')
  10. elif len(args)==2:
  11. print('Hello, %s!'% args[1])
  12. else:
  13. print('Too many arguments!')
  14. if __name__=='__main__':
  15. test()

以上就是Python模块的标准文件模板,固然也能够所有删掉不写,可是,按标准办事确定没错。
sys模块有一个argv变量,用list存储了命令行的全部参数。argv至少有一个元素,由于第一个参数永远是该.py文件的名称,例如:
运行python3 hello.py得到的sys.argv就是[‘hello.py’];
运行python3 hello.py Michael得到的sys.argv就是[‘hello.py’, ‘Michael]。

参考

http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
http://www.runoob.com/python/python-tutorial.html



相关文章
相关标签/搜索