自己学习python 3.x的笔记,主要内容来源于A byte of python(已看完)和python官网文档Python 3.4.3 documentation(其中的Tutorial已看完)。
To-Do:
1.配置好Hexo及VIM在windows下的环境。2.在windows下编辑完本文其他内容。3.回顾markdown语法,排版本文。4.完成python官网Tutorial
5.使用python实现一个采集系统
6.使用pyton实现一个图像处理功能
一、python的基本知识
1.helloworld字符串的输出格式为print('Hello world!')
2.python可以以多数模式运行.eg:python -c command [arg]
#以命令行模式运行等,如果手动指定其运行模式则sys.argv[0]
中存储的将是相应的参数-c,-m等否则是sourcename,即sys.argv[0]
存储python命令后面的第一个参数。
3.python默认的源码文件为UTF-8格式,可以通过将语句# -*- coding: encoding -*-
放在源码第一行或者第二行来手动指定源文件格式。或者直接写成# encoding=utf-8
4.python注释以#开头,物理行结束,可以放在整行,空格或者代码后。
5.python的变量必须先赋值再使用,赋值相当于同时定义了变量,支持并列赋值和表达式中赋值。eg: a,b = 1,2
6.交互模式下最后一次被打印的表达式存储在变量”_”中,这个变量对用户是只读的,但可以创建同名变量覆盖它。
7.python内建支持int,float,decimal,fraction,complex number
,使用”J”或“j”指定虚数位。
8.单引号与双引号的功能一样,类似于C里面的printf()
中的双引号,三引号可以打印多行字符,也就是可以在程序中字符串的地方直接输入回车。反斜杠表示转义字符与C中一样,行尾的反斜杠”"表示下一行是上一行的继续。在字符串引号前加R/r表示自然语言,也就是说里面的所有字符就只是单纯的字符,无法使用格式化输出,可以用于正则表达式。单引号内的双引号和双引号内的单引号不需要转义。
9.format为格式化输出,即使用参变量的值代替格式符{n}中的内容,format()
可以有多个参数,例如:
'{0:.3}'.format(1/3)
输出为1/3保留3位小数0.333
'{0:*^10}'.format('blueyi')
以”*“在两边填充占用11位的”blueyi” 输出为 **blueyi***
'{name} {age}'.format(name = "blueyi",age = 3+2)
输出为 blueyi5
“{}”中的数字或者说内容是可选的
print()函数打印时会自动在字符串结尾加上”\n”,可以手动指定结尾内容,如print("he", end = "")
不会换行,name = "blueyi";print("I'm",name);
会打印I'm blueyi
input()
获取输入,eg: age = int(input("Enter your age:"))
10.操作符和表达式
大部分操作符与C语言一样,数学运算时a ^ b
表示异或,即有且仅有一个真时为真。a ** b
表示a的b次方,a // b
表示取a对b取整,a << b
和a >> b
表示a对应的二进制左移或者右移b位,C语言里面的位运算也能用,~a
表示对a取反,~a == -(a + 1)
,and、or、not对应逻辑中的与或非
可以使用a += b
,不过没有“a++”类型的操作符。
11.可以使用分号;让两个逻辑行放在一个物理行里面,例如:i = 1;print(i);
12.字符串是序列的一种,所有序列都可以通过“+”操作符连接,“*”操作符重复,都支持索引、切片以及使用len返回长度等。两个或者多个字符串紧挨在一起会被自动连接。eg: 'max' + 'wi' == 'maxwi' == 'max''wi'
13.字符串可以通过下标索引,索引可以为负数,但不能越界,str[-1]为最后一个最符,str[-0] == str[0]
。
14.字符串支持所有序列都支持的切片操作,切片操作str[n1:n2]
返回n1到n2之间的字符串,含头不含尾。切片越界不会报错,会返回到字符串结尾。如果n1已经越界则返回空字符串。s[:i] + s[i:] == s
15.字符串是不可变的,也就是不能对单一某一位上的字符进行修改。eg:str[0] = 'a'
会返回TypeError
16.python中所有非0值为true,非空序列为true,空序列为false。
17.一般以双下划线开头和结尾的变量都是python内建或者程序中自己定义的具有特殊意义的变量。
二、控制流
1、if-elif-else记得加:,eg:
1 | if True: |
2、while语句与C类似,可选else,else语句将在循环结束后执行一次
3、for...in...
语句in后面可以跟任何序列,也有一个与while类似的可选else。for语句和list()函数相当于一个遍历器。list()可以从可遍历序列创建一个列表。eg:list(rang(5)) => [0,1,2,3,4]
3.1 for循环可用于遍历任何序列中的元素,遍历时若在循环内修改序列,则for循环的条件序列也会立即改变。所以for循环不会默认以副本形式的序列作为条件,最好以序列的拷贝进行遍历。eg:for w in words[:];
该切片返回的是列表的拷贝。
3.2 遍历数字序列时,可以使用内建的range()
函数。eg:for i in range(1, 5): pass;
3.3 range(n)
为从0到n遍历数字,含头不含尾。range(start, end, step)
表示以步长step从start遍历到end,step可以为负数。索引序列时可以混合使用range()
和len()
。eg:
1 | a = ['I', 'am', 'blueyi'] |
也可以使用枚举实现上述例子。eg:list(enumerate(a));
3.4 range()
为了节省空间,只在遍历时才返回连续的元素。实际上不会在内存中生成一个元素列表,所以print(range(10)) =>range(0,10)
3.5 enumerate(iterable, start = 0)
表示默认从0开始遍历可遍历的序列对象。
4、continue和break在循环中与C中用法类似,分别表示继续下一次循环和跳出最近的for或while循环,pass表示空语句。
5、语句块以关键字加冒号再配合缩进组成,包括if,while,for,def
6、关键字in可用于测试序列中是否包含一个确定的值。eg:
1 | if 5 in range(5): |
三、函数
使用def定义函数,函数中的变量有全局,局部和非局部三种作用域。
函数中的所有变量都存储在一个局部列表中,引用变量时首先会查找局部列表,然后查找外部函数的局部列表,再然后是全局列表,最后是内建名称。
在函数体内部可以使用global关键字修饰全局变量,以便能在函数体内修改函数体外的变量。在函数体内定义的函数体中,可以使用关键字nonlocal修饰局部变量,使其成为非局部变量,以便可以在嵌套的内部函数中修改。一个关于作用域的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)定义形参时可以给形参赋值,为形参指定一个默认参数,只有参数表末尾的参数可以有默认值。当然也可以是这样
def func(a=5):
print(string * n)
表示打印n次string,其中n为整数,string为字符串
6.为函数形参赋值时,实参按顺序赋给形参,也可以通过赋值语句而不考虑顺序,eg:
1 | def func(a, b=5, c=6): |
func(1, 2, 3)
则a=1, b=2, c=3
func(3, c=2)
则a=3, b=5, c=2
func(c=3, a=2)
则a=2, b=5, c=3
注意:未指定默认值的参数必须赋值
6.形参所赋的默认值只会被计算一次,当拥有默认值的形参默认值是个可变列表时,要特别注意。eg:
1 | def func(a, list=[]): |
l1 = func(1)
=> l1 = [1]
l2 = func(2)
=> l2 = [1,2]
1 | def func2(a, list=None): |
l3 = func2(1)
=> l3 = [1]l4 = func2(2)
=> l4 = [2]
7.可以使用列表和字典来定义一个能获取任意个数参数的函数。eg:
1 | def func(a=5, *numbers, **keywords): |
8.可以在带*的参数后面声明keyword-only参数.eg:
1 | def func(a=5, *b, c): |
调用func时c必须赋值,eg:func(1, 2, 3, 4, c=8)
9.return返回函数值,无需指定函数的返回类型,没有return的函数默认返回None
10.Docstring文档字符串位于函数的第一个逻辑行,放在6个双引号”之间。可以使用__doc__
(双下划线)引用eg:print(func.__doc__)
11.lambda关键字可用于创建匿名函数,形式为lambda parameters : expression
。也可以利用它创建返回函数的嵌套函数。eg:
1 | def make_func(n): |
f(0)
=> 42f(1)
=> 43
12.程序的元数据以字典形式存储在__annotations__
变量中。可通过func.__annotations__
读取。
四.数据结构
列表,元组,字典,集合都属于结构化数据,有可变和不可变之分。
1.1列表:可变的序列,类方法操作后直接修改而不返回。可使用for element in list:
遍历,使用[]定义。eg:list = ['I','am','blueyi']
,可以通过list[n]
来访问第n个元素,list.append('rice')
在列表尾添加一个元素,通过del list[n]
删除第n个无素,list.sort()
排序,len(list)
查看其长度。
1.2 列表支持层叠.eg: a = str1;b = str2;c = [a,b];
1.3 常的list类方法。
list.append(x)
列表尾添加一个元素。<=> a[len(a):] = [x]
list.extend(L)
将列表L添加到list <=> a[len(a):] = L
list.insert(i, x)
在i位置前插入元素x。a.insert(len(a), x)
<=> a.append(x)
list.remove(x)
移除值为x的元素
list.pop([i])
移除并返回位置i处的元素。[]表示可选项。list.pop()
为移除最后一个元素
list.clear()
删除list中所有元素 <=> del a[:]
list.index(x)
返回列表中第一个值为x的元素索引,若无x则报错。
list.count(x)
返回列表中x出现的次数
list.sort()
直接对当前列表进行排序
list.reverse()
颠倒列表中的元素
list.copy()
返回一个列表的浅拷贝 <=> a[:]
。关于深浅拷贝http://www.01happy.com/python-shallow-copy-and-deep-copy/
list的pop和append可以方便地将其当作堆栈来使用。利用collections.deque()
可将列表当队列使用。
2.元组:不可变序列,可以将多样的对象集合到一起。使用for element in tuple:
遍历,使用()定义,使用tuple[n]
访问。eg:tuple = ('python','perl','ruby','php');tuple_plus = ('C', 'C++', tuple);
则tuple_plus[2][1][1] = +
2.1 声明含有0个元素的元组可以直接tuple = ()
,仅含一个元素时后面必须要有个逗号,eg:tuple = ('blueyi',)
3.字典:就是键值对的集合,且没有顺序,其中键必须是惟一且不可变的,值是可变或者不可变的。可以使用for key, value in dict.items():
遍历,声明方式为dict = {key1 : value1, key2 : value2}
del dict[key1]
删除键值对,if key2 in dict
检验键值对是否存在。定义一个空字典:dic = {}
4.列表,元组,字符串都属于序列,有着许多共同之处,他们者支持索引操作符”[ ]”,也支持切片操作。eg:list[1:3]
返回list[1],list[2]
,切片操作返回值包含首不包含尾,list[:]
返回整个序列,list[1:]
返回第一个到最后一个,list[1:4:2]
以部长n返回,即list[1],list[3],list[5]....
5.集合:没有顺序的,简单对象的聚类。声明方式为sets = set(['Pear', 'Apple', 'Orange'])
,支持一些集合上的逻辑运算。
6.切片操作获得的是拷贝,而赋值操作获得的只是引用
7.记得使用help,查看更多相应类方法
8.一些常见的序列遍历方法
9.1 items()
方法可以同时遍历字典中的key和value。eg:
1 | for k,v in dict.items(): |
9.2 enumerate()
函数可同时遍历序列中的index和value。eg:
1 | for i,v in enumerate(list): |
9.3 reversed()函数以相反的方向遍历序列。eg:
1 | for i in reversed(range(1,10,2)): |
=>9 7 5 3 1
9.4 zip()
函数可同时遍历多个序列。eg:
1 | questions = ['name', 'quest', 'favorite color'] |
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
9.5 sorted()
函数返回一个已排序的序列而不改变原序列。eg:
1 | for i in sorted(set(list)): |
10.条件检查和比较
10.1 操作符”in”和”not in” 检查值是否出现在某个序列中
10.2 “is”和”is not” 检验两对象是否是同一对象,它们仅用于可变对象,如list.
10.3 所有的比较操作符优先级一样
10.4 比较可以级联。eg: a < b == c <=> a < b and b == c
10.5 比较时可以混合使用布尔操作符and,or,not.它们的优先级比比较操作符低。其中not优先级最高,or优先级最低
10.6 布尔操作符中的and,or遵循短路原则
10.7 相同类型的序列对象之间可相互比较,遵照字典顺序。如果某一序列是另一序列的子序列,则较短的较小。序列元素为数字比较时,如果类型不一样,则近似比较。eg:
1 | (1, 2, 3) < (1, 2, 4) |
五.模块
1.每一个’.py’文件的python都是一个模块,模块中可以包含函数,变量等
2.使用关键字import导入模块,eg:import A
表示导入A到当前程序,引用时需要使用点操作符’.’来确定命名空间。from A import B
表示导入A中的B到当前程序,from A import *
导入A中的所有变量或者函数到当前程序(双下划线开始的变量除外),这种导入方式引用时不需要”.”操作符,但容易与当前同名变量冲突,所以不推荐使用
3.模块的__name__
可以控制主块的运行。这样模块就可以像脚本一样运行。eg:
1 | if __name__ == '__main__': |
4.sys.argv
中存储的是传递参数列表,sys.argv[0]
是程序名,sys.path
为sys的路径,os.getcwd()
可以获取当前程序所在路径
5.dir()
可用于显示模块的所有名称列表.eg:dir(sys)
显示sys模块中的所有名称列表,dir()
则显示当前模块中的名称列表。dir()不会列出内建程序名和变量名,要列出它们需要使用内建模块builtins。eg:
1 | import builtins |
6.del a
语句用于删除变量/名称a
7.包可用于组织模块,是模块的文件夹,使用__init__.py
文件来在模块文件夹根目录标明当前文件夹为包。包包含模块,模块包含函数和全局变量,函数中又包含变量
- 一个模块在一次程序进程期间只会导入一次,修改模块后需要重启解释器,如果只是为了交互式的测试可使用imp.
reload()
重新载入模块。eg:1
2import imp;
imp.reload(modulename)
9.编译模块为.pyc文件或者.pyo(通过-o参数,pyo为优化后的pyc文件,通常更小)。pyc文件通常为__pycache__
目录下的module.version.pyc
。这些文件有平台依赖性。
10..pyc或.pyo文件并不会使python程序运行更快,只是加快了载入速度。
11.python标准库就是python的标准模块,部分标准库依赖操作系统平台。eg:winreg模块仅在windows下有
sys.ps1
存储的是交互模式下的提示符’>>>’,sys.path.append('string')
可追加PYTHONPATH
13.使用包管理模块时可嵌套目录,使用点操作符引用。eg: import item.subitem.subsubitem
最后一个元素可以是个模块或者包,但不能是类、函数或变量。
六、类
1.类使用关键字class创建,eg:
1 | class Person: |
属于一个类或者对象的变量称为域,域又可称为属于实例的实例变量,和属于对象或者类本身的类变量。
2.类对象支持2种操作,一种是属性引用。eg:
1 | class Myclass: |
另一种是实例引用,即创建一个Myclass的实例。eg:
1 | x = Myclass() |
3.类方法与普通函数的区别是类方法必须有第一个参数且指向对象本身,通常称为self.注意不是指定类,而是指定类创建的对象本身。eg:
1 | class Person: |
4.类可以通过__init__()
方法初始化,__init__
函数会在类对象创建时立即运行,相当于C++的构造函数。__del__()
方法用于在对象被删除时运行,例如使用del语句删除对象。它们也必须要有self参数。
5.与类变量名字相同的实例变量会隐藏类变量。类变量在所有实例之间共享,可以被它们修改,而实例变量是由各个实例所私有。eg:
1 | class Dog: |
6.同名的数据属性会覆盖掉方法属性。
7.以双下划线开头的变量都是私有变量。如果某个变量想只在对象和类中使用,最好以单下划线开关。pep8规范
8.类继承是通过元组在定义子类时将父类作为元组元素来实现继承。eg:
1 | class Company: |
9.python支持多重继承,继承的属性从第一个父类开始从左至右搜索到为止。
10.所有类都继承自object。
11.一些常用的特殊类方法
object.__init__(self,[...])
新创建的对象返回之前调用,用于初始化对象
object.__del__(self)
对象被销毁前调用
object.__str__(self)
当使用print函数或者str()
函数时调用
object.__lt__(self,other)
当使用<操作符时调用,对应的有object.__eq__(self, other) object.__ne__(self, other) object.__gt__(self, other)object.__ge__(self, other)
object.__getitem__(self, key)
使用索引操作符x[index]
时调用
object.__len__(self)
当内建的len()
函数对序列对象使用时调用
12.检查类的两个方法:
isinstance(obj, class)
检查实例类型
issubclass(class1, class2)
检查class是否继承自class2
七、输入输出
1.字符串的输入输出是通过input(prompt)
和print(string)
.eg:
1 | text = input('Enter your string:') |
2.repr()
和str()
都会强制将任何值强制转换为一个字符串并返回,其中repr()
返回一个解释器易于处理的形式,而str()
会返回一个人易读的形式。
3.str.rjust(width[ ,filechar])
右对齐并以fillchar填充,相应的有ljust()
,center()
。这些方法不会修改原str,只是返回一个新的str。str.format()
可对字符串进行格式化转化。
4.对于文件的读写使用open(filename, mode),close(),write(),read(),readline()
等方法,以UTF-8格式打开文件,打开方式可选且多数与C类似,默认为以文本方式读或者写,默认mode为r
。
默认的这些文件读写方法由os包提供,是较低级的文件读写接口,尽量使得io包提供的文件读写接口:
1 | # encoding=utf-8 |
5.文件读写的文本模式下,默认读取时会自动转换换行符(\n on unix,\r\n on windows
)为\n
,写会进行相反的操作。
6.File的常用类方法(假定已经创建了名为f的file对象):
6.1 f.read([size])
读取size bytes大小的数据,返回一个字符串或字节对象,若省略size则返回整个文件内容,若文件过大则会出错,达到文件尾会返回空字符串。
6.2 f.readline()
读取单独的一行,包含\n
。返回空字符串时表示到达文件尾。可使用更高效的循环代替。eg:
1 | for line in f: |
6.3 f.readlines()
读取文件中的所有行到列表。也可使用list(f)
6.4 f.write(string)
将string写入文件并返回写入的字符数。若写入的内容不是字符串则需要手动转换。eg:
1 | value = ('the answer', 42) |
6.5 f.tell()
返回一个标示当前文件对象所指向文件位置的整数,二进制模式表示从文件头到当前位置的字节数。文本模式下为一个opaque number。
6.6 f.seek(offset[, from_what])
以frome_what为参考位置修改f的指向位置。from_what可取0、1、2分别表示文件开头、当前位置、文件结尾,默认为0。
6.7 f.close()
关闭文件并释放资源。
6.8 f.closed()
查看当前文件是否已被关闭。
7.建议使用with...as...
语句读写文件 eg:
1 | with open('temp.txt', 'r') as f: |
with 获取open返回的对象,以f引用,在执行它后的语句块之前会先执行返回对象的enter方法。执行完语句块之后会执行返回对象的exit方法。无需手动关闭文件。
8.open()
方法默认以utf-8格式打开文件,也可以手动指定编码格式。eg: f = open('temp.txt', 'wt', encoding='utf-8')
9.利用pickle模块的dump()和load()方法可以将对象存储到文件中然后在需要的时候读取,存取时要以二进制模式读写,且存储的文件仅能用于python中。eg:
1 | import pickle |
10.json模块与pickle相反,它可将结构化的数据存储到可交换的数据文件格式json中,使用json.dump(x, f)
将x写入f,x = json.load(f)
,将f内容读入到x。
八.异常
1.通过try...except...else
语句处理异常,功能语句放在try块中,错误处理语句放在except块中,没有任何异常则运行else中的语句,else语句可选。
如:
1 | try: |
2.except中可加入多个异常。eg:except(RuntimeError, TypeError, NameError):
,最后一个异常名可以使用通配符。
3.自己可以创建继承至Error或者Exception类的异常,使用raise可以引发错误或者异常,用户定义的异常应该直接或者间接地继承自Exception。
4.使用try...finally...
可以在无论异常发生与否的情况下都执行finally语句块中的内容
5.可选的finally语句在实际应用中可用于释放外部资源,如关闭文件或网络连接。
6.有些对象预定义了清理动作,如file,可通过with...as...
语句体现。with语句处理完文件后,无论哪种情况下都会关闭文件。
九.其他
1.利用元组可以获得函数一次返回的两个值。eg:
1 | def getStudent(): |
a, *b = [1,2,3,4]
则a = 1,b = [2,3,4]
2.Python中的迭代器。
2.1迭代器遍布于python之中,最常见是for循环通过调用可迭代对象的iter()
方法来进行循环迭代。其中iter()
方法相当于一个对象容器,每次返回一个迭代器对象,迭代器对象中定义的__next__()
方法用来在每次迭代时返回iter()
中的下一个元素,当没有任何元素时,__next__()
将引发StopIteration
异常。可以使用内置函数next()
来调用__next__()
方法。eg:
1 | for element in [1, 2, 3]: |
1 | s = 'abc' |
2.2 可通过在类中增加__iter()__
方法返回对象本身给__next__()
方法来为自己的类增加迭代功能。eg:
1 | class Reverse: |
3.Python中的生成器。
yield
语句可以用于创建迭代器,能够实现通过__iter__()
和__next__()
实现的功能。每次 next() 被调用时, 生成器会从它上次离开的地方继续执行,它会记住所有的数据值和最后一次执行的语句。eg:
1 | def reverse(data): |
4.Generator表达式比列表实现的相同功能更省内存。
sum(i*i for i in range(10))
#计算平方和,输出为285
十.标准库
1.sys包含系统指定的函数功能
2.os用来和系统交互
3.plantform用来获得平台信息
4.logging用来记录信息
5.urllib网络相关
拾遗
函数装饰器:@classmethod, @staticmethod, @property
函数装饰器通常用于放在类方法前面修饰类内部定义的函数。
类的成员函数可以通过上述提到的3个装饰器来修饰,区别主要如下:
- 普通成员函数,即不使用任何装饰器来修饰的成员函数即为方法,它属于类的实例化对象,且只能通过实例化之后的类对象调用,而不能通过类本身来直接调用(当然可以通过显示传递实例的方式调用),即普通成员函数与类的实例绑定。普通成员函数的第一个参数默认为当前类的实例,即通常用的self。
- @classmethod修饰的方法属于类方法,类方法属于类本身,且被所有类的实例共有,该方法的第一个参数默认为类本身,而不是类的实例,通常使用cls来表示第一个形参。该方法可以通过类名来直接调用,或者通过类的实例来调用,即该方法与类本身绑定。它可以访问数据成员及成员函数
- @staticmethod修饰的方法为静态方法,类似C++中的静态方法,该方法不与类及类对象绑定,它的第一个参数也不要求必须是谁,可以没有第一个参数(其他类方法第一个参数都默认为类本身或实例本身)。该方法即可以直接通过类来调用,也可以通过类的实例调用。它不能访问实例的属性(数据成员或成员函数)
- @property装饰器可以将方法设置为对象的属性,当一个函数被@property修饰时,python默认会为该类增加一个相应函数的getter, setter和deleter属性,默认的@property修饰的方法就是getter方法,如下面的官方示例:
1 | class C(object): |
一个针对性举例:
1 | #! /usr/bin/env python |
运行结果:
1 | I am common function |
从结果中可以看到com_method绑定到了C的对象,class_method与类本身绑定,st_method没有绑定
requirements.txt
pip freeze > requirements.txt
生成依赖pip install -r requirements.txt
安装依赖
参考:
http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
http://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner
http://blog.csdn.net/slvher/article/details/42497781
https://docs.python.org/2/library/functions.html#property