Python学习 进了一家新公司,后端代码是用 Python 写的,就自己带着学习了一下 Python 语言,总结一些用法,不定时更新……
Python2 和 Python3分别安装pip
python -m pip install
python3 -m pip install
Python虚拟环境virtualenv 安装 pip install virtualenv
使用 选择一个目录,比如我们把这个工程放在 /path/to/project/spider/ 目录下,我们在这个目录下建立一个虚拟环境
virtualenv /path/to/project/spider
虚拟环境就建立好了。此时可以看到,在这个目录下面会有三个目录被建立:
激活虚拟环境 在上述目录中
bin 目录中包含一些在这个虚拟环境中可用的命令,以及开启虚拟环境的脚本 activate;
include 中包含虚拟环境中的头文件,包括 Python 的头文件;
lib 中就是一些依赖库啦~~
source /path/to/project/spider/bin/activate
接下来就可以使用 安装工程需要的 requests 库
pip install requests
退出虚拟环境 deactivate
补充一句,如果想要删除虚拟环境,只要把这个目录下的 bin、include 和 lib 三个目录删掉就好了。
Python简单操作 if __name__ == "__main__"
如果.py文件被其他文件引入,不执行对应的函数
Python判断数据类型与提示用户输入 判断数据类型 type(a)与type(a) is str与isinstance(a, int)
1 2 3 4 temp = '18' print (type (temp))print (type (temp) is str )print (isinstance (temp, int ))
结果如下:
1 2 3 <class 'str' > True False
提示用户输入 提示用户输入: input('请输入密码:'),用户输入内容均为字符串
1 2 3 4 >>> a = input ('请输入密码:' )请输入密码:222222 >>> print ('你的密码是%s' %a)你的密码是222222
运算符 //: 取整(地板除)
% : 取余
and: 相当于js的&&
or: 相当于js的||
not: 表示取非
列表操作 列表推导式[x for x in args] 1 2 3 4 >>> y = [1 ,3 ,5 ,7 ,9 ]>>> a = [x for x in y]>>> a[1 , 3 , 5 , 7 , 9 ]
append
直接在list列表后面追加
只能追加一个元素 1 2 member = ['舞蹈' , '陆远' , '剑无尘' ] member.append('云峰' )
extend
追加list列表1 member.extend(['沧海' , '傲雪' ])
insert
remove
del
del(member[1])等价于del member[1]
del member删除整个列表
pop
不加参数表示从后面删除一个元素
参数表示从指定索引位置删除元素
列表切片(分片)
使用冒号获取列表指定位置元素拷贝,原列表不变1 2 3 4 member[1 :3 ] member[:3 ] member[1 :] member[:]
列表比较
比较列表中的第一个元素,第一个赢了,整个列表就赢了
列表相加
只有数据类型相同才能相加
原列表不变 1 2 member + '比利' member + ['比利' ]
列表翻倍
原列表不变
member * 3
member *= 2
成员操作符 in & not in
适用于一元列表,二元列表里的元素需要list[n]1 2 '云峰' in member '陆云' not in member
列表元素数目统计=>list.count('123')
列表元素出现索引位置
list.index(xxx)=>表示从列表起始位置查找,显示第一次找到的索引
list.index(xxx, 3, 7)=>表示从指定位置开始查找
找不到会报错
列表排序
list.sort()=>从小到大排序
list.sort(reverse=True)=>从大到小排序
列表翻转=>list.reverse()
元组操作 元组类似于列表,但是其内元素不可改变
创建元组(逗号是关键)
tuple=(1, 3, 5, 7, 9)
tuple=()=>空元组
tuple=(1)=>整数1
tuple=1, || tuple=(1,)=>元组(1)
元组的元素几乎不可以直接删除,可以像列表那样采用切片删除
删除元组
字符串操作
大写与小写–> 字符串方法参考网址
capitalize() & casefold()
center(width)=>字符串居中,使用空格填充至长度width的新字符串
count(sub[,start[,end]])=>返回sub在字符串里出现的次数
encode(encoding='utf-8', errors='strict')
endswith(sub[,start[,end]])
expandtabs([tabsize=8])=>将字符串中的tab符号(\t)转换为空格,默认8个空格
find(sub[,start[,end]])=>返回sub在字符串里的索引值,找不到返回-1
index(sub[,start[,end]])=>同find,找不到报异常
isalnum()
isalpha()
isdecimal()=>十进制
isdigital()=>数字
islower()
isnumeric()
isspace()
istitle()
isupper()
join(sub)=>以sub为分隔符插入到字符串中
split()=>找到空格就切
strip([chars])
swapcase()=>翻转大小写
translate(str.maketrans('a', 'b'))
格式化输出(字符串格式化符号%)
format –> 字符串格式化符号含义 1 2 3 4 5 6 "{0} love {1}.{2}" .format ("I" , "FishC" , "com" ) "{a} love {b}.{c}" .format (a="I" , b="FishC" , c="com" ) "{0} love {b}.{c}" .format ("I" , b="FishC" , c="com" ) "{a} love {b}.{0}" .format (a="I" , b="FishC" , "com" ) "{0:.1f}{1}" .format (27.699 , "GB" ) "{{0}}" .format ("不打印" )
%c (格式化字符及ASCII码) 1 >>> '%a %c %c' %(97 , 98 , 99 )
打印整数(%d)和百分号(%%) 1 2 >>> print ("his score is %d%%" %24 )his score is 24 %
打印字符串(%s) 1 2 3 >>> a = 'xiaoming' >>> print ("his name is %s" %a)his name is xiaoming
打印浮点数(%f) 1 2 >>> print ("his height is %f m" %1.83 )his height is 1.830000 m
打印浮点数,指定保留小数点位数(%.2f) 1 2 >>> print ("his height is %.2f m" %1.83 )his height is 1.83 m
指定占位符宽度 1 2 >>> print ("Name:%10s Age:%8d Height:%8.2f" %("Aviad" ,25 ,1.83 ))Name: Aviad Age: 25 Height: 1.83
指定占位符宽度(左对齐) 1 2 >>> print ("Name:%-10s Age:%-8d Height:%-8.2f" %("Aviad" , 25 , 1.83 ))Name:Aviad Age:25 Height:1.83
指定占位符(只能用0当占位符?),且字符串无法使用0占位 1 2 >>> print ("Name:%-10s Age:%08d Height:%08.2f" %("Aviad" ,25 ,1.83 ))Name:Aviad Age:00000025 Height:00001.83
科学计数法(保留小数点位数科学计数法) 1 2 >>> format (0.0015 ,'.5e' )'1.50000e-03'
列表、元组和字符串共同点(可统称为序列) 三者统称为序列 ,下面介绍几个内置函数:
list([iterable])=>把一个可迭代对象转化为列表
tuple([iterable])=>转化为元组
str(object)=>把obj对象转化为字符串
len() => 返回序列长度
max() => 返回序列或者参数集合中最大值,同理还有min()
sum(iterable[,start])
sorted()
reversed() => 返回一个迭代器对象,可使用list转化
enumerate() => 返回一个迭代器对象,可使用list转化
zip(a, b) => 将a与b中元素一一对应拼接为tuple类型,例如list(zip('123456789', '56789'))
字典(dict)
类似于js的对象,设置本来不存在的键会自动创建
dict(mapping) –> a mapping object’s (key, value) pairs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> dict1 = dict ((('a' , 1 ), ('b' , 2 ), ('c' , 3 )))>>> dict1{'a' : 1 , 'b' : 2 , 'c' : 3 } >>> dict2 = dict ((['d' ,4 ], ['e' ,5 ], ['f' ,6 ]))>>> dict2{'d' : 4 , 'e' : 5 , 'f' : 6 } >>> dict3 = dict ([['g' ,7 ],['h' ,8 ]])>>> dict3{'g' : 7 , 'h' : 8 } >>> dict4 = dict (one = 'hello' , two = 'man' , three = 'how are you' )>>> dict4{'one' : 'hello' , 'two' : 'man' , 'three' : 'how are you' } >>> dict (zip (['one' , 'two' , 'three' ], [1 , 2 , 3 , 4 ])){'one' : 1 , 'two' : 2 , 'three' : 3 }
json字符串转化为字典
eval() 或 exec()1 2 3 4 5 6 7 8 >>> user"{'name' : 'jim', 'sex' : 'male', 'age': 18}" >>> b=eval (user)>>> b{'age' : 18 , 'name' : 'jim' , 'sex' : 'male' } >>> exec ("c=" +user)>>> c{'age' : 18 , 'name' : 'jim' , 'sex' : 'male' }
json.loads() –> json字符串转python字典
json.dumps() –> python对象转json字符串
字典常用方法
fromkeys
keys/values/items
get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 >>> dict .fromkeys(('a' ,'b' ,'c' )){'a' : None , 'b' : None , 'c' : None } >>> dict .fromkeys(('one' ,'two' ,'three' ), 'school' ){'one' : 'school' , 'two' : 'school' , 'three' : 'school' } >>> dict1 = dict .fromkeys(range (10 ), '赞' )>>> dict1{0 : '赞' , 1 : '赞' , 2 : '赞' , 3 : '赞' , 4 : '赞' , 5 : '赞' , 6 : '赞' , 7 : '赞' , 8 : '赞' , 9 : '赞' } >>> dict1.fromkeys((1 , 3 ), '不攒' ){1 : '不攒' , 3 : '不攒' } >>> for key in dict1.keys():... print (key)>>> for value in dict1.values():... print (value)>>> for item in dict1.items():... print (item)... (0 , '赞' ) (1 , '赞' ) (2 , '赞' ) (3 , '赞' ) (4 , '赞' ) (5 , '赞' ) (6 , '赞' ) (7 , '赞' ) (8 , '赞' ) (9 , '赞' ) >>> dict1[9 ]'赞' >>> dict1[10 ] >>> dict1.get(9 )'赞' >>> print (dict1.get(10 )) None >>> dict1.get(10 , '找不到' ) '找不到'
清空字典 clear
浅拷贝 copy
弹出指定值 pop(key)
弹出最后一个值 popitem 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 >>> dict1 = {'one' : 1 , 'two' : 2 , 'three' : 3 }>>> dict1.clear()>>> dict1{} >>> a = {'one' : 1 , 'two' : 2 , 'three' : 3 }>>> b = a.copy()>>> c = a>>> c{'one' : 1 , 'two' : 2 , 'three' : 3 } >>> b{'one' : 1 , 'two' : 2 , 'three' : 3 } >>> a{'one' : 1 , 'two' : 2 , 'three' : 3 } >>> id (a)4329539984 >>> id (b)4329538328 >>> id (c)>>> c["four" ] = 4 >>> c{'one' : 1 , 'two' : 2 , 'three' : 3 , 'four' : 4 } >>> a{'one' : 1 , 'two' : 2 , 'three' : 3 , 'four' : 4 } >>> b{'one' : 1 , 'two' : 2 , 'three' : 3 } >>> a.pop('three' )3 >>> a{'one' : 1 , 'two' : 2 , 'four' : 4 } >>> c.popitem()('four' , 4 ) >>> c{'one' : 1 , 'two' : 2 }
setdefault –> 设置默认值
update(dict) –> 更新字典值 1 2 3 4 5 6 7 8 9 10 11 >>> a{'one' : 1 , 'two' : 2 } >>> a.setdefault('小白' , 6 )>>> a{'one' : 1 , 'two' : 2 , '小白' : 6 } >>> c.setdefault('红豆' )>>> c{'one' : 1 , 'two' : 2 , '小白' : 6 , '红豆' : None } >>> a.update({'小白' : '够' })>>> a{'one' : 1 , 'two' : 2 , '小白' : '够' , '红豆' : None }
集合(set)
集合内元素唯一,利用该性质可以给list(列表)去重 1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> num = [1 ,2 ,3 ,4 ,5 ,5 ,3 ,1 ,0 ]>>> new_num = list (set (num))>>> new_num[0 , 1 , 2 , 3 , 4 , 5 ] >>> temp = []>>> for item in num:... if item not in temp:... temp.append(item)... >>> temp[1 , 2 , 3 , 4 , 5 , 0 ]
集合类型内建方法–> 参考网址
add
remove(如果删除对象不存在,报错)
discard(删除对象不存在没事)
pop, clear
不可变集合 1 2 3 4 5 6 >>> alpha = {1 , 3 , 5 , 7 }>>> alpha.add(9 )>>> alpha{1 , 3 , 5 , 7 , 9 } >>> beta = frozenset ({2 , 4 , 6 , 8 })>>> beta.add(10 )
循环 for xx in aaa:: 遍历aaa
range([start,] stop[, step=1]): 内置函数,range[2,5]表示从2到5的整数,不包括5
Python导入模块与包 导入模块
import 模块名
form 模块名 import 函数名
import 模块名 as 新名字
搜索路径 原始python包搜索路径如下:
1 2 3 4 5 6 >>> import sys>>> sys.path['' , '/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python36.zip' , '/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6' ,'/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload' ,'/usr/local/lib/python3.6/site-packages' ]
搜索包的路径可以增加, 例如
1 sys.path.append('/usr/local/add' )
导入包 .代表当前目录,..代表上一层目录,…代表上上层目录。
例如:在模块A.B.C中的代码:
1 2 3 from . import D from .. import E from ..F import G
Python内建函数(BIF: build in function)与模块
range(1, 10)
for i in range(1, 10):表示i从1循环到9, 不包括10
issubclass(B, A) –> B是否是A的子类 ==> 自身是自身的子类issubclass(B, B) –>True
isinstance(B, A) –> B是否是A的实例对象
hasattr(object, attr) –> 第二个参数用字符串
getattr(object, attr[, default]) –> 第三个参数可以设置不存在属性的默认值
setattr(object, attr[, value]) –> 设置属性
delattr(object, attr) –> 删除属性
property(getattr, setattr, delattr)
random模块
1 2 3 4 import randomfor i in range (1 , 50 ): print (random.randint(1 , 10 ), i)
os模块
os.path模块
python路径操作模块
os.path.basename
os.path.dirname
pickle模块 1 2 3 4 5 6 7 8 9 import picklemy_list = ['xyz' , 123 , 'bbc' , ['hello' , 'lady' ]] pkl_file = open ('my_list.pkl' , 'wb' ) pickle.dump(my_list, pkl_file) pkl_file.close pkl_file = open ('my_list.pkl' , 'rb' ) my_list2 = pickle.load(pkl_file) print (my_list2)
Python普通函数 函数返回值
如果python函数没有return语句,默认返回None对象 不要在函数中试图定义或修改全局变量的值,否则python会新建一个与全局变量名字相同的局部变量代替(屏蔽保护全局变量) 在函数内部使用global关键字修饰需要修改的全局变量,调用函数,全局变量发生改变
1 2 3 4 5 6 7 8 9 10 11 >>> def display ():... global count... count = 99 ... print (count)... >>> print (count)5 >>> display()99 >>> print (count)99
lambda x : 2 * x + 1相当于定义了函数,冒号前面是参数,后面是返回值
1 2 3 4 5 6 7 8 >>> def ds (x ):... return 2 * x + 1 ... >>> ds(5 )11 >>> g = lambda x : 2 * x + 1 >>> g(5 )11
默认参数 1 2 3 4 5 6 7 >>> def eat (a="apple" , b="banana" ):... print ("正在吃" + a, b)... >>> eat("pear" , "peach" )正在吃pear peach >>> eat()正在吃apple banana
关键字参数 1 2 3 4 5 6 7 >>> def write (name, address ):... print (name + "在" + address)... >>> write("小明" , "杭州" )小明在杭州 >>> write(address = "武汉" , name = "小萌" )小萌在武汉
可变参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 >>> def test (*params ):... print ("参数长度是:" , len (params))... print ("第三个参数是:" , params[2 ])... >>> test("今天" , "明天" , "后天" , "大后天" , "大大后天" )参数长度是: 5 第三个参数是: 后天 >>> def hello (*params, extra="萨瓦迪卡" ):... print ("参数长度是:" , len (params))... print ("其他参数是:" , extra)... >>> hello("hi" , "hello" , "你好" )参数长度是: 3 其他参数是: 萨瓦迪 >>> def hello (*params, extra ):... print ("参数长度是:" , len (params))... print ("其他参数是:" , extra)... >>> hello("hi" , "hello" , "你好" , "萨瓦迪卡" , extra="阿妮哈赛呦" )参数长度是: 4 其他参数是: 阿妮哈赛呦
内嵌函数和闭包 1 2 3 4 5 6 7 8 9 >>> def f1 ():... x = 5 ... def f2 ():... x *= x... return x... return f2()... >>> f1()
解决办法1(Python2.0): 1 2 3 4 5 6 7 8 9 >>> def f1 ():... x = [5 ]... def f2 ():... x[0 ] *= x[0 ]... return x[0 ]... return f2()... >>> f1()25
解决方法2(Python3.0) –> nonlocal关键字: 1 2 3 4 5 6 7 8 9 10 >>> def f1 ():... x = 5 ... def f2 ():... nonlocal x... x *= x... return x... return f2()... >>> f1()25
两个牛逼的BIF(内置函数 build in function)
filter(function or None, iterable) –> filter object1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> list (filter (None , (1 , 0 , False , True )))[1 , True ] >>> def odd (x ):... return x % 2 ... >>> temp = range (10 )>>> show = filter (odd, temp)>>> list (show)[1 , 3 , 5 , 7 , 9 ] >>> list (filter (lambda x : x % 2 , range (10 )))[1 , 3 , 5 , 7 , 9 ]
map(func, *iterables) –> map object1 2 >>> list (map (lambda x : x * 2 , range (10 )))[0 , 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 ]
递归调用
设置递归深度1 2 import syssys.setrecursionlimit(100000 )
阶乘的非递归版本实现:1 2 3 4 5 6 7 8 9 def factorial (n ): result = n for i in range (1 , n): result *= i return result num = int (input ("请输入一个正整数:" )) result = factorial(num) print ("%d 的阶乘是: %d" % (num, result))
阶乘的递归实现1 2 3 4 5 6 7 8 9 def factorial (n ): if n == 1 : return 1 else : return n * factorial(n - 1 ) num = int (input ("请输入一个正整数:" )) result = factorial(num) print ("%d 的阶乘是: %d" % (num, result))
斐波那契数列非递归实现:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def fibonacci (n ): n1 = 1 n2 = 1 n3 = 1 if n < 1 : print ("输入有误!" ) return -1 while (n - 2 ) > 0 : n3 = n2 + n1 n1 = n2 n2 = n3 n -= 1 return n3 result = fibonacci(20 ) if result != -1 : print ("总共有%d对兔子诞生~" % result)
斐波那契数列递归实现:1 2 3 4 5 6 7 8 9 10 11 12 13 def fibonacci (n ): if n < 1 : print ("输入有误!" ) return -1 if n == 1 or n == 2 : return 1 else : return fibonacci(n - 1 ) + fibonacci(n - 2 ) result = fibonacci(20 ) if result != -1 : print ("总共有%d对兔子诞生~" % result)
汉诺塔递归实现1 2 3 4 5 6 7 8 9 10 11 12 def hanoi (n, x, y, z ): if n < 1 : return -1 if n == 1 : print (x, '-->' , z) else : hanoi(n - 1 , x, z, y) print (x, '-->' , z) hanoi(n - 1 , y, x, z) n = int (input ("请输入汉诺塔的层数:" )) hanoi(n, 'X' , 'Y' , 'Z' )
Python文件读写
读取文件–> 参考网址
打开模式
'r' –> 只读方式(默认)
'w' –> 写入方式打开,会覆盖已存在的文件(用于写入文件)
'a' –> 写入模式打开文件,如果文件存在,则在末尾追加1 2 3 >>> f = open ('test.txt' ) >>> list (f) ['hello my name is liming\n' , 'where are you from\n' , 'i am from america\n' ]
文件对象方法
f.close() –> 关闭文件流
f.read([size=-1]) –> 从文件流中读取size个字符, 当未给定size或给定负值, 读取剩余的所有字符
f.readline([size=-1]) –> 读取一行(遇到\n和EOF结束), 如果定义了size,有可能返回的只是一行的一部分
f.readlines([size=-1]) –> 把文件每一行作为一个list的一个成员,并返回这个list, 它的内部是通过循环调用readline()来实现的. 如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分
f.write(str) –> 将字符串写入文件, write()并不会在str后加上一个换行符
f.writelines(seq) –> 向文件中写入字符串序列seq(list, tuple, str), seq应该是一个返回字符串的可迭代对象. 这个函数也只是忠实地写入,不会在每行后面加上任何东西
f.seek(offset, from) –> 在文件中移动文件指针, 从from(0代表文件起始位置, 1代表当前位置, 2代表文件末尾)偏移offset个字节
f.tell() –> 返回当前在文件中的位置1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 f = open ('test.txt' ) for line in f: print (line) f.seek(10 , 0 ) print (f) lines = list (f) print (lines)count = 0 for line in lines: count += 1 print ('第%d行:' % count, line) f.close()
一个Python文件读写任务
文本文件molest.txt(调戏), 任务是将其中小甲鱼和小客服的三次对话分别读出来, 每次对话分为boy*.txt和girl*.txt1 2 3 4 5 6 7 8 9 10 11 12 13 14 小客服: 小甲鱼, 今天有客服问你有没有女朋友? 小甲鱼: 咦?? 小客服: 我跟她说了你已经有女朋友了! 小甲鱼: ...... ========== 小客服: 小甲鱼, 有个好评很好笑哈. 小甲鱼: 哦? 小客服: "有了小甲鱼, 妈妈再也不用担心我的学习了~" 小甲鱼: 哈哈哈. ========== 小客服: 小甲鱼, 今天一个会员想找你. 小甲鱼: 哦? 什么事? 小客服: 他说他妈喊他回家吃饭. 小甲鱼: 滚!
代码如下1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 def save_file (boy, girl, count ):file_name_boy = 'boy_%d.txt' % count file_name_girl = 'girl_%d.txt' % count boy_file = open (file_name_boy, 'w' ) girl_file = open (file_name_girl, 'w' ) boy_file.writelines(boy) girl_file.writelines(girl) def split_file (file_name ): f = open (file_name) boy = [] girl = [] count = 1 for each_line in f: if each_line[:5 ] != '=====' : (role, line_say) = each_line.split(':' , 1 ) if role == '小甲鱼' : boy.append(line_say.lstrip()) if role == '小客服' : girl.append(line_say.lstrip()) else : save_file(boy, girl, count) boy = [] girl = [] count += 1 save_file(boy, girl, count) f.close() split_file('molest.txt' )
Python异常处理
try ---> except --> except --> finally
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 try : f = open ('boy_1.txt' , 'w' ) print (f.write('好冷啊' )) print (f.read()) sum = 1 + '1' f.close() except OSError as reason: print ('文件出错啦T_T\n错误原因是:' + str (reason), '==' * 10 , type (reason)) except TypeError as reason: print ('类型出错啦T_T\n错误原因是:' + str (reason), '==' * 10 , type (reason)) else : print ('没有异常' ) finally : f.close() print ('这里收个尾' ) print ('来来来,见面分一半' )raise ZeroDivisionError('除数不能为0' )
结果如下:
1 2 3 4 5 6 7 8 9 3 文件出错啦T_T 错误原因是:not readable ==================== <class 'io.UnsupportedOperation' > 这里收个尾 来来来,见面分一半 Traceback (most recent call last): File "/Users/hushiking/hu/python/littleTurtle/exception.py" , line 17 , in <module> raise ZeroDivisionError('除数不能为0' ) ZeroDivisionError: 除数不能为0
with用法
用在文件读写中, 不用手动关闭文件流, with自动搞定. 例如:
1 2 3 4 5 6 7 8 9 try : with open ('data.txt' , 'w' ) as f: f.write('with处理文件读写不用手动关闭文件流' ) for each_line in f: print (each_line) except OSError as reason: print ('出错啦' + str (reason))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Sample : def __enter__ (self ): return self def __exit__ (self, type , value, trace ): print ("type:" , type ) print ("value:" , value) print ("trace:" , trace) def do_something (self ): bar = 1 / 0 return bar + 10 with Sample() as sample: sample.do_something()
Python面向对象 类似js的构造方法
__init__(self, name, ...)
__init__()函数必须返回None, 否则报错
1 2 3 4 5 6 7 8 9 class Person : def __init__ (self, name ): self .name = name def kick (self ): print ("我叫%s, shit, 谁踢我..." % self .name) >>> p = Person("李世民" )>>> p.kick()我叫李世民, shit, 谁踢我...
设置私有变量
__name = "xxx"
可使用p._Person__name访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Person : __name = '小甲鱼' def getName (self ): return self .__name >>> p = Person()>>> p.__nameTraceback (most recent call last): File "<console>" , line 1 , in <module> AttributeError: 'Person' object has no attribute '__name' >>> p.getName()'小甲鱼' >>> p._Person__name'小甲鱼'
通过property绑定属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class C : def __init__ (self, size=10 ): self .size = size def getSize (self ): return self .size def setSize (self, value ): self .size = value def delSize (self ): del self .size x = property (getSize, setSize, delSize) c = C() print (c.size) c.x = 28 print (c.size) c.size = 30 print (c.x) del c.xprint (c.size)
property绑定属性原理 , 自定义property类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class MyProperty : def __init__ (self, fget=None , fset=None , fdel=None ): self .fget = fget self .fset = fset self .fdel = fdel def __get__ (self, instance, owner ): return self .fget(instance) def __set__ (self, instance, value ): self .fset(instance, value) def __delete__ (self, instance ): self .fdel(instance) class C : def __init__ (self ): self ._x = None def getX (self ): return self ._x def setX (self, value ): self ._x = value def delX (self ): del self ._x x = MyProperty(getX, setX, delX) c = C() c.x = 'xxx' print (c._x) del c.xprint (c._x)
继承(用于纵向关系的类)
其中pass是占位符, 表示不做任何处理
自己创建的MyList类继承系统的list类
1 2 3 4 5 6 7 8 9 10 11 12 class MyList (list ): pass >>> list1 = MyList()>>> list1.append(5 )>>> list1.append(3 )>>> list1.append(7 )>>> list1[5 , 3 , 7 ] >>> list1.sort()>>> list1[3 , 5 , 7 ]
子类中定义的方法会覆盖父类定义的方法, 包括__init__(self)方法
所以子类的__init__(self)需要先调用父类的__init__(self)方法
调用未绑定的父类方法
super().__init__()
Python支持多继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import random as rclass Fish : def __init__ (self ): self .x = r.randint(0 , 10 ) self .y = r.randint(0 , 10 ) def move (self ): self .x -= 1 print ('我的位置是:' , self .x, self .y) class Shark (Fish ): def __init__ (self ): super ().__init__() self .hungry = True
类组合(用于横向关系的类, 类之间没有继承关系或者其他关联)
把要组合的类的实例化写入新类的__init__函数中, 例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Turtle : def __init__ (self, x ): self .num = x class Fish : def __init__ (self, x ): self .num = x class Pool : def __init__ (self, x, y ): self .turtle = Turtle(x) self .fish = Fish(y) def print_num (self ): print ("水池里总共有乌龟 %d 只和小鱼 %d 条!" % (self .turtle.num, self .fish.num)) pool = Pool(2 , 11 ) pool.print_num()
类、类对象、实例对象
类属性(静态属性/成员), 所有实例对象共用
实例属性(实例属性/成员), 与类属性同名的实例属性会覆盖类属性
属性名与方法名相同, 属性会覆盖方法(导致方法无法调用)
类的方法需要绑定self , 是为了实例对象调用该方法
Python魔法方法 解构与析构
在定义类时, 第一个调用的方法是__new__方法, 一般采用Python自带即可, 不需要重写, 当继承一个不可变的类时才可能需要重写. 例如:
1 2 3 4 5 6 7 8 class CapitalStr (str ): def __new__ (cls, string ): string = string.upper() return str .__new__(cls, string) >>> s = CapitalStr('Good morning, everyone!' )>>> s'GOOD MORNING, EVERYONE!'
定义类时, 还有一个隐式的__del__方法, 当对象不再被其它变量引用时会被Python垃圾回收机制回收, 触发__del__方法
__str__与__repr__
str()函数得到的字符串可读性好, 所以被print调用, 对应__str__函数返回值
repr()函数得到字符串通常可以用来重新获得该对象, obj==eval(repr(obj). 对应__repr__函数返回值
str()则不同,它生成一个对象的可读性好的字符串表示,结果通常无法用eval()求值,但适合print输出。
str()出来的值是给人看的。repr()出来的值是给python看的,可以通过eval()重新变回一个Python对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> class A :... def __str__ (self ):... return 'a__str__' ... def __repr__ (self ):... return 'a__repr__' ... >>> a = A()>>> aa__repr__ >>> print (a)a__str__ >>> '%s' % a'a__str__' >>> '%r' % a'a__repr__'
定制定时器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import time as tclass MyTimer (): def __init__ (self ): self .unit = ['年' , '月' , '日' , '时' , '分' , '秒' ] self .prompt = '未开始计时!' self .lasted = [] self .begin = 0 self .end = 0 def __str__ (self ): return self .prompt __repr__ = __str__ def __add__ (self, other ): prompt = '总共运行了' result = [] for index in range (6 ): result.append(self .lasted[index] + other.lasted[index]) if result[index]: prompt += (str (result[index]) + self .unit[index]) return prompt def start (self ): self .begin = t.localtime() self .prompt = '提示: 请先调研stop()停止计时!' print ('计时开始...' ) def stop (self ): if not self .begin: print ('提示: 请先调用start()进行计时!' ) else : self .end = t.localtime() self ._calc() print ('计时结束!' ) def _calc (self ): self .lasted = [] self .prompt = '总共运行了' for index in range (6 ): self .lasted.append(self .end[index] - self .begin[index]) if self .lasted[index]: self .prompt += (str (self .lasted[index]) + self .unit[index]) self .begin = 0 self .end = 0
__add__与__sub__内置加法与内置减法, 当两个对象相加或相减是触发
属性访问(定制)
__getattr__(self, name) –> 定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self, name) –> 定义当该类的属性被访问时的行为
__setattr__(self, name, value) –> 定义当一个属性被设置时的行为
__delattr__(self, name) –> 定义当一个属性被删除时的行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Rectangle : def __init__ (self, width=0 , height=0 ): self .width = width self .height = height def __setattr__ (self, name, value ): if name == 'square' : self .width = value self .height = value else : self .__dict__[name] = value def getArea (self ): return self .width * self .height r = Rectangle(4 , 5 ) print (r.getArea()) r.square = 10 print (r.getArea())
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Celsius : def __init__ (self, value=26 ): self .value = float (value) def __get__ (self, instance, owner ): return self .value def __set__ (self, instance, value ): self .value = float (value) class Fahrenheit : def __get__ (self, instance, owner ): return instance.cel * 1.8 + 32 def __set__ (self, instance, value ): instance.cel = float (value) - 32 / 1.8 class Temperature : def __init__ (self, value=26 ): self .value = float (value) cel = Celsius() fah = Fahrenheit() temp = Temperature() print (temp.value) print (temp.cel) temp.cel = 30 print (temp.fah) temp.fah = 88 print (temp.cel)
定制序列(容器)
__len__(self)
__getitem__(self, key)
__setitem__(self, key, value)
__delitem__(self, key)
定义元组或者字符串等不可变容器, 只需定义前两个方法即可 如果定义可变容器, 以上四个方法都需要定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class CountList : def __init__ (self, *args ): self .values = [x for x in args] self .count = dict .fromkeys(range (len (self .values)), 0 ) def __len__ (self ): return len (self .values) def __getitem__ (self, key ): self .count[key] += 1 return self .values[key] list1 = CountList(1 , 3 , 5 , 7 , 9 ) list2 = CountList(2 , 4 , 6 , 8 , 10 ) print (list1[1 ]) print (list2[1 ]) print (list1[1 ] + list2[2 ]) list1.count print (list1.count) print (list2.count)
定制迭代器
iter() –> 返回可迭代对象的迭代器
next() –> 得到迭代器的下一个迭代值, 如果没有下一个迭代值, 报StopIteration异常
1 2 3 4 5 6 7 8 9 10 11 >>> it = iter ('abc' )>>> next (it)'a' >>> next (it)'b' >>> next (it)'c' >>> next (it)Traceback (most recent call last): File "<console>" , line 1 , in <module> StopIteration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Fibs : def __init__ (self, n=10 ): self .a = 0 self .b = 1 self .n = n def __iter__ (self ): return self def __next__ (self ): self .a, self .b = self .b, self .a + self .b if self .a > self .n: raise StopIteration return self .a fibs = Fibs(100 ) for each in fibs: print (each, end=' ' )
以上代码, Fibs被定义为一个可迭代的斐波那契类容器, 迭代结果如下:
1 1 1 2 3 5 8 13 21 34 55 89
生成器函数
关键词yield, 相当于return, 函数运行到此处会暂停或挂起, 并在需要的时候(next())从程序离开的地方继续或者重新开始
生成器推导式
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> d = (i for i in range (10 ))>>> d<generator object <genexpr> at 0x10b9588e0 > >>> next (d)0 >>> next (d)1 >>> next (d)2 for each in d: print (each, end=' ' ) 3 4 5 6 7 8 9
1 2 3 4 >>> sum ((i for i in range (100 ) if i % 2 ))2500 >>> sum (i for i in range (100 ) if i % 2 )2500
列表推导式 1 2 3 >>> a = [i for i in range (100 ) if i % 2 and not (i % 3 )]>>> a [3 , 9 , 15 , 21 , 27 , 33 , 39 , 45 , 51 , 57 , 63 , 69 , 75 , 81 , 87 , 93 , 99 ]
字典推导式 1 2 3 >>> b = {i: i % 2 == 0 for i in range (10 )}>>> b {0 : True , 1 : False , 2 : True , 3 : False , 4 : True , 5 : False , 6 : True , 7 : False , 8 : True , 9 : False }
集合推导式 1 2 3 >>> c = {i for i in [23 , 4 , 5 , 9 , 6 , 3 , 1 , 4 , 5 , 6 , 7 ]}>>> c {1 , 3 , 4 , 5 , 6 , 7 , 9 , 23 }