python学习笔记 :小甲鱼python全套视频 + python基础教程 第2版修订版(书附10个大型案例)
python学习环境 :python3, win10下python3.5.4的IDLE + ubuntu下python3辅助
python分享范围 :适合有C/C++/JAVA任意语言之一为基础,不适合纯新手入门
python语言优势 :至今还没有一门编程语言,开发速度比Python快,运行速度比C快
python常用工具手册:
http://bbs.fishc.com/forum.php?mod=collection&action=view&ctid=198
00. python背景与特点 Python语言起源 在1989年末,Guido van Rossum为了打发圣诞节的无聊,创造了python(大蟒蛇)。 1991年,第一个 Python 版本诞生。最新版本是Python3 3.6.2 。Guido van Rossum 是蒙提·派森的飞行马戏团(Monty Python‘s Flying Circus)的爱好者。logo是由两只蟒蛇的图形组成。
官网下载地址:https://www.python.org/downloads/
Python 3 与 Python 2 不完全兼容 官方表示对 Python2 支持到2020年, Python2 2.7.13。Python 2 的生态库远远大于 Python 3。
简单: 学习曲线平滑, 45分钟学会基本使用,使用简单。 跨平台: 一次编写、到处运行。 Windows, Linux, Mac, Android 功能强大: 动态类型、自动内存管理 非常实用的内置对象类型 强大的内置工具和标准库 易于扩展,很多成熟易用第三方库 大型程序支持 应用广泛: 数据库、网络、图形图像、科学计算、机器学习、web开发、操作系统扩展等 缺点: 运行速度不够快(硬件的发展可以为此弥补不足) 开发速度与运行速度之间的矛盾: 至今还没有一门编程语言,开发速度比Python快,运行速度比C快 知名软件包:Django/Numpy/Pandas/Matplotlib/PIL (Pillow)/PyQt5/Tensorflow/Scipy/Theano/NLTK 知名项目:(网站)豆瓣/知乎/美团/Gmail/Youtube/Instagram/Calibre/……
01. 第一次亲密接触 first love (1) win下的python IDLE集成开发环境自动缩进,table键补齐变量名 (2) linux下使用vi编辑.py的python文件,需要声明 #!/usr/bin/python3 (3) python使用等量(1个tab)的缩进来严格对齐表示作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 print (" -游戏开始 -- - " ) temp = input ("输入一个我现在想的数字:" ) guess = int (temp)if guess == 8 :print ("猜对了!!!" )else :print ("哈哈,猜错了。。" )print ("游戏结束喽~" ) BIF == Built-in functions(内置函数)>>> dir (__builtins__) ..., 'input' , ...>>> help (input )
02. 变量 variable (1) python没有”变量”只有”名字” (2) 变量使用之前,需要对其先赋值 (3) 变量名命名同C的规则,不能以数字开头,保证可读性命名即可 (4) 大小写敏感,区分 (5) =左右依次为左值和右值 (6) 十六进制,以0x 或 0X 开头 ,数字由”0”到”9” 或者 “a”到”f” 或者 “A”到”F”组成 八进制,0o或0O 开头,数字由”0” 到 “7”组成 二进制,0b或0B 开头表示,数字由”0” 或者”1”组成 十进制由数字”0”到”9”组成,并且不能以0开头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> teacher = 'jiangyuan' >>> print (teacher) jiangyuan>>> teacher = 'somebody' >>> print (teacher) somebody>>> first = 3 >>> second = 8 >>> third = first + second>>> print (third)11 >>> myteacher = 'jiangyuan' >>> yourteacher = 'somebody' >>> ourteacher = myteacher + yourteacher>>> print (ourteacher) jiangyuansomebody
03. 运算符及优先级 precedence of operator #符合数学运算优先原则,括号最优先,最安全。 lambda lambda表达式 or 布尔或 and 布尔与 not 布尔非 in 和 not in 成员是否属于测试 is 和 is not 对象是否是同一个
= < <= == != 比较操作符 | 按位或 ^ 按位异或 & 按位与 << 和 >> 移位
和 / 和 % 乘法、除法、取余 +x 和 -x 正负号 ~x 按位翻转 ** 指数(幂运算) // 地板除法,舍弃小数部分 – -python运算符优先级(图)– -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 >>> a = b = c = d = 10 >>> print (a, b, c, d)10 10 10 10 >>> a += 1 >>> b -= 1 >>> c *= 10 >>> d /= 8 >>> print (a, b, c, d)11 9 100 1.25 >>> d = 10 >>> d // 3 3 >>> 3 < 4 < 5 True >>> 3 < 4 and 4 < 5 True
04. 类型 type 数值类型:整型(int)、浮点型(float)、布尔类型(bool)、e记法(科学计数法,属于float) (1) 整型与浮点型的区别就是是否含有小数点’.’ (2) bool类型的值是以大写开头的两个单词: True / False (3) 纯数字的字符串可以使用int转为数字,进而参与计算,相当于C的atoi,非纯数字的不能使用int转换为数字 (4) float类型转换为int类型时,会丢弃小数部分 (5) str类型均可被其他类型转换,即变成字符串无障碍 (6) type (value) 返回变量类型,isinstance(value, type)类型判断返回bool值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 >>> a = 5.99 >>> b = int (a)>>> print (b)5 >>> 0.00000000000000111 1.11e-15 >>> 150000000000 150000000000 >>> 15e10 150000000000.0 >>> isinstance ('hello' , str )True >>> isinstance (520 , str )False >>> isinstance (520 , int )True
05. 条件分支与循环 condition and loop 条件bool值: True False False 的值: False None 0 “” () [] {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 if -else if condition:else :if -elif -else if condition:elif condition:else : x if condition else y 举例:>>> x, y = 4 , 5 >>> small = x if x < y else y>>> print (small)4
assert 断言 当assert关键字后面的条件为假的时候,程序自动崩溃并抛出AssertionError异常。
1 2 3 4 5 6 >>> assert 3 > 4 Traceback (most recent call last): File "<pyshell#160>" , line 1 , in <module> assert 3 > 4 AssertionError>>> assert 3 < 4
while 循环 while condition:
for 循环 for target in expression: 循环体 示例:
1 2 3 4 >>> favourite = 'string' >>> for i in favourite:print (i, end=' ' ) s t r i n g
range()函数 range ([start], [stop], [step]) #step默认每次递增1,且range的取值范围到stop-1 常与for循环一起使用。 示例:
1 2 3 4 5 6 >>> for i in range (2 , 5 ):print (i, end=' ' )2 3 4 >>> for i in range (1 , 10 , 2 ):print (i, end=' ' )1 3 5 7 9
break 和 continue 同C语言的break和continue,依次为跳出循环和跳过当前循环。
pass 和 del 和 exec pass 什么也不敢,暂时预留 del 删除不再使用的对象 exec 执行python语句 exal 计算python表达式,并返回结果值
06. 列表 list 普通列表:member = [‘name’, ‘id’, ‘age’, ‘weight’] 混合列表:mix = [1, ‘name’, 3.14, [1, 2, 3]] 空列表:empty = [] 列表常用方法: len()/max()/min()/append()/extend()/insert()/remove()/pop()/count()/index()/reverse()/sort()
len() 功能:列表长度(元素个数) len(listname)
append() 功能:向列表添加单个元素 listname.append(element)
1 2 3 >>> member.append('class' )>>> member ['name' , 'id' , 'age' , 'weight' , 'class' ]
extend() 功能:使用子列表扩展列表 listname.extend([element1, element2, …])
1 2 3 >>> member.extend (['str1' , 'str2' ])>>> member ['name' , 'id' , 'age' , 'weight' , 'class' , 'str1' , 'str2' ]
insert() 功能:向列表指定位置插入元素 listname.insert(position, element)
1 2 3 4 >>> member.insert (1 , 'new_elem' )>>> member ['name' , 'new_elem' , 'id' , 'age' , 'weight' , 'class' , 'str1' , 'str2' ]
列表元素访问 listname[index]
列表元素删除 listname.remove(element) #删除元素element
1 2 3 del listname[index] listname.pop() listname.pop(index)
列表元素分片 listname[start_index:stop_index] (1) 分片不会修改原列表的值,输出的是一份拷贝 (2) 分片输出的是从 start_index 到 stop_index-1 位置的值 (3) 分片的start和stop位置均可省略,start省略表示从头取值,stop省略表示取值到结尾,都省略表示取列表所有的值 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> member = ['name' , 'id' , 'age' , 'weight' , 'class' , 'str1' , 'str2' , 'str3' ] 0 1 2 3 4 5 6 7 >>> member[1 :3 ] ['id' , 'age' ]>>> member[1 :] ['id' , 'age' , 'weight' , 'class' , 'str1' , 'str2' , 'str3' ]>>> member[:3 ] ['name' , 'id' , 'age' ]>>> member[:] ['name' , 'id' , 'age' , 'weight' , 'class' , 'str1' , 'str2' , 'str3' ]>>> member[5 :len (member)] ['str1' , 'str2' , 'str3' ]>>> member[0 :len (member):2 ] ['name' , 'age' , 'class' , 'str2' ]
列表常用操作符 (1) list元素的判断只会判断第一个元素,然后理解返回bool结果 (2) list支持比较、逻辑、连接(+)、重复(* )、成员关系(in)操作符 (3) list赋值list时需要注意加上[:],左值会表现为一份拷贝 示例: list2 = list1[:]#list2是list1的一份拷贝 list3 = list1 #list3是list1的一个引用(list1被修改,list3也会跟着被修改) (4) dir(list) 查看list支持的所有方法: listname.count(element)#element元素出现的次数 listname.index(element, [range_s], [rang_t])#查找元素在起止范围里第一次出现的下标位置 listname.reverse()#将list中的元素原地翻转 listname.sort()#将list中的元素进行排序,默认从小到大(修改原list内容) listname.sort(reverse=True)#排序元素,实现从大到小(修改原list内容)
07. 元组 tuple 元组和列表使用上相似: (1) 最大区别:列表可以任意修改和插入等操作,元组是不可改变的 (2) 创建:列表使用[],元组使用() 元组只有1个元素时使用(element,)注意逗号 ()可以省略,但是,逗号不能省略 (3) 访问:都使用name[index]来访问 (4) 元组在映射中当做键使用,而列表不行 示例:
1 2 3 4 5 6 7 8 9 10 11 12 >>> temp = 1 ,>>> type (temp) <class 'tuple' >>>> 8 * (8 )64 >>> 8 * (8 ,) (8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ) >>> temp = ('name1' ,'name2' ,'name3' ,'name4' )>>> temp = temp[:2 ] + ('new_name' ,) + temp[2 :]>>> temp ('name1' , 'name2' , 'new_name' , 'name3' , 'name4' )
08. 字符串 string (1) 可以进行符号转义 (2) 单引号等同于双引号 (3) 定义字符串时使用r写在右值前面声明为原始字符串 (4) 使用三引号(‘’’或”””)可以指定多行字符串。并且字符串里可以包含单引号和双引号’’’ (5) +号运算符可以连接字符串为1个字符串 (6) * 号运算符可以复制多个相同字符串 列表和元组应用于字符串,所有标准的序列操作均适用于字符串。
1 2 3 4 >>> str1 = 'hello, python!' >>> str1 = str1[:5 ] + ';' + str1[5 :]>>> str1'hello;, python!'
字符串常用方法: find()/join()/lower()/replace()/split()/strip()/translate()/
1 2 >>> dir (str ) ...'capitalize' , 'casefold' , 'center' , 'count' , 'encode' , 'endswith' , 'expandtabs' , 'find' , 'format' , 'format_map' , 'index' , 'isalnum' , 'isalpha' , 'isdecimal' , 'isdigit' , 'isidentifier' , 'islower' , 'isnumeric' , 'isprintable' , 'isspace' , 'istitle' , 'isupper' , 'join' , 'ljust' , 'lower' , 'lstrip' , 'maketrans' , 'partition' , 'replace' , 'rfind' , 'rindex' , 'rjust' , 'rpartition' , 'rsplit' , 'rstrip' , 'split' , 'splitlines' , 'startswith' , 'strip' , 'swapcase' , 'title' , 'translate' , 'upper' , 'zfill' ...
【F1】可以从python的帮助文档中【索引】查找操作方法的介绍内容及举例。
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 capitalize() 返回新字符串,把字符串的第一个字符改为大写 casefold() 返回新字符串,把整个字符串的所有字符改为小写 center(width) 将字符串居中,并使用空格填充至长度 width 的新字符串 count(sub[, start[, end]]) 返回 sub 在字符串里边出现的次数,start 和 end 参数表示范围,可选。 encode(encoding='utf-8' , errors='strict' ) 以 encoding 指定的编码格式对字符串进行编码。 endswith(sub[, start[, end]]) 检查字符串是否以 sub 子字符串结束,如果是返回 True ,否则返回 False 。start 和 end 参数表示范围,可选。 expandtabs([tabsize=8 ]) 把字符串中的 tab 符号(t)转换为空格,如不指定参数,默认的空格数是 tabsize=8 。 find(sub[, start[, end]]) 检测 sub 是否包含在字符串中,如果有则返回索引值,否则返回 -1 ,start 和 end 参数表示范围,可选。 index(sub[, start[, end]]) 跟 find 方法一样,不过如果 sub 不在 string 中会产生一个异常。 isalnum() 如果字符串至少有一个字符并且所有字符都是字母或数字则返回 True ,否则返回 False 。 isalpha() 如果字符串至少有一个字符并且所有字符都是字母则返回 True ,否则返回 False 。 isdecimal() 如果字符串只包含十进制数字则返回 True ,否则返回 False 。 isdigit() 如果字符串只包含数字则返回 True ,否则返回 False 。 islower() 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是小写,则返回 True ,否则返回 False 。 isnumeric() 如果字符串中只包含数字字符,则返回 True ,否则返回 False 。 isspace() 如果字符串中只包含空格,则返回 True ,否则返回 False 。 istitle() 如果字符串是标题化(所有的单词都是以大写开始,其余字母均小写),则返回 True ,否则返回 False 。 isupper() 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是大写,则返回 True ,否则返回 False 。 join(sub) 以字符串作为分隔符,插入到 sub 中所有的字符之间。 ljust(width) 返回一个左对齐的字符串,并使用空格填充至长度为 width 的新字符串。 lower() 转换字符串中所有大写字符为小写。 lstrip() 去掉字符串左边的所有空格 partition(sub) 找到子字符串 sub,把字符串分成一个 3 元组 (pre_sub, sub, fol_sub),如果字符串中不包含 sub 则返回 ('原字符串' , '' , '' ) replace(old, new[, count]) 把字符串中的 old 子字符串替换成 new 子字符串,如果 count 指定,则替换不超过 count 次。 rfind(sub[, start[, end]]) 类似于 find() 方法,不过是从右边开始查找。 rindex(sub[, start[, end]]) 类似于 index() 方法,不过是从右边开始。 rjust(width) 返回一个右对齐的字符串,并使用空格填充至长度为 width 的新字符串。 rpartition(sub) 类似于 partition() 方法,不过是从右边开始查找。 rstrip() 删除字符串末尾的空格。 split(sep=None , maxsplit=-1 ) 不带参数默认是以空格为分隔符切片字符串,如果 maxsplit 参数有设置,则仅分隔 maxsplit 个子字符串,返回切片后的子字符串拼接的列表。 splitlines(([keepends])) 按照 'n' 分隔,返回一个包含各行作为元素的列表,如果 keepends 参数指定,则返回前 keepends 行。 startswith(prefix[, start[, end]]) 检查字符串是否以 prefix 开头,是则返回 True ,否则返回 False 。start 和 end 参数可以指定范围检查,可选。 strip([chars]) 删除字符串前边和后边所有的空格,chars 参数可以定制删除的字符,可选。 swapcase() 翻转字符串中的大小写。 title() 返回标题化(所有的单词都是以大写开始,其余字母均小写)的字符串。 translate(table) 根据 table 的规则(可以由 str .maketrans('a' , 'b' ) 定制)转换字符串中的字符。 upper() 转换字符串中的所有小写字符为大写。 zfill(width) 返回长度为 width 的字符串,原字符串右对齐,前边用 0 填充。
字符串操作:格式化 (1) 通过format方法将位置参数传递给对应字段 (2) : 冒号表示格式化符号的开始
位置参数:{0~n}
1 2 >>> "{0} love {1},{2}." .format ("I" , "you" , "too" )'I love you,too.'
关键字参数:{自定义}
1 2 3 >>> "{a} love {b}, {c}." .format (a="I" , b="you" , c="too" )'I love you, too.' 注意:位置参数和关键字参数可以同时使用,但位置参数必须在关键字参数的前面。
字符串格式化符号含义 %c 格式化字符及其 ASCII 码 %s 格式化字符串 %d 格式化整数 %o 格式化无符号八进制数 %x 格式化无符号十六进制数 %X 格式化无符号十六进制数(大写) %f 格式化浮点数字,可指定小数点后的精度,默认精确到小数点后6位 %e 用科学计数法格式化浮点数 %E 作用同 %e,用科学计数法格式化浮点数 %g 根据值的大小决定使用 %f 或 %e %G 作用同 %g,根据值的大小决定使用 %f 或者 %E 举例:
1 2 3 4 >>> '%c' % 97 'a' >>> '%c %c %c' % (97 , 98 , 99 ) 'a b c'
格式化操作符辅助命令 m.n m 是显示的最小总宽度,n 是小数点后的位数
在正数前面显示加号(+)在八进制数前面显示 ‘0o’,在十六进制数前面显示 ‘0x’ 或 ‘0X’ 0 显示的数字前面填充 ‘0’ 取代空格 举例:
1 2 3 4 5 6 7 8 >>> '%5.1f' % 27.658 ' 27.7' >>> '%-10d' % 5 '5 ' >>> '%#x' % 160 '0xa0' >>> '%010d' % 5 '0000000005'
Python 的转义字符及其含义 ‘ 单引号 “ 双引号 a 发出系统响铃声 b 退格符 n 换行符 t 横向制表符(TAB) v 纵向制表符 r 回车符 f 换页符 o 八进制数代表的字符 x 十六进制数代表的字符 0 表示一个空字符 反斜杠
09. 序列方法 sequence method 列表、元组、字符串的共同点: (1) 都可以通过索引得到每一个元素 (2) 默认索引值总是从0开始 (3) 可以通过分片的方法得到一个范围内的元素的集合 (4) 有很多共同的操作符(重复*、拼接+、成员关系in/not in等) (5) 统称为序列,以下(成员函数)为序列方法
list() list(iterable) 把一个可迭代对象转换为列表 举例:
1 2 3 4 >>> b = 'I love you.' >>> b = list (b)>>> b ['I' , ' ' , 'l' , 'o' , 'v' , 'e' , ' ' , 'y' , 'o' , 'u' , '.' ]
tuple() tuple(iterable) 把一个可迭代对象转换为元组 举例:
1 2 3 4 >>> b = 'I love you.' >>> b = tuple (b)>>> b ('I' , ' ' , 'l' , 'o' , 'v' , 'e' , ' ' , 'y' , 'o' , 'u' , '.' )
max(…) 返回集合或者序列中的最大值(要求类型一致) min(…) 返回集合或者序列中的最小值(要求类型一致)
1 2 >>> max (iterable, * [, default=obj, key=func]) -> value>>> max (arg1, arg2, * args, * [, key=func]) -> value
举例:
1 2 3 4 5 >>> numbers = [1 , 18 , 13 , 0 , -98 , 34 , 53 , 76 , 32 ]>>> max (numbers)76 >>> min (numbers) -98
sum(…) 返回序列iterable和可选参数的总和(要求类型一致)
1 >>> sum (iterable, start=0 , /)
举例:
1 2 3 4 5 >>> tuple1 = (3.1 , 2.3 , 3.4 )>>> sum (tuple1)8.8 >>> sum (tuple1, 0.2 ) 9.0
sorted(…) 返回序列的排序结果
1 >>> sorted (iterable, /, * , key=None , reverse=False )
举例:
1 2 3 >>> tuple1 = (3.1 , 2.3 , 3.4 )>>> sorted (tuple1) [2.3 , 3.1 , 3.4 ]
reversed(…) 翻转一个序列的内容
举例:
1 2 3 4 5 >>> numbers = [1 , 24 , 5 , -98 , 54 , 32 ]>>> reversed (numbers) <list_reverseiterator object at 0x000002C3EE5046A0 >>>> list (reversed (numbers)) [32 , 54 , -98 , 5 , 24 , 1 ]
enumerate(…) 生成由序列组成的元组
1 >>> enumerate (iterable[, start])
举例:
1 2 3 >>> numbers = [1 , 24 , 5 , -98 , 54 , 32 ]>>> list (enumerate (numbers)) [(0 , 1 ), (1 , 24 ), (2 , 5 ), (3 , -98 ), (4 , 54 ), (5 , 32 )]
zip(…) 返回由各个参数的序列组成的元组
1 >>> zip (iter1 [,iter2 [...]])
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> a = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]>>> b = [4 , 5 , 6 , 7 , 8 ]>>> zip (a, b) <zip object at 0x000002C3EE562948 >>>> list (zip (a, b)) [(1 , 4 ), (2 , 5 ), (3 , 6 ), (4 , 7 ), (5 , 8 )]>>> for i,j in zip (a, b): print (str (i) + ' is ' + str (j))1 is 4 2 is 5 3 is 6 4 is 7 5 is 8
10. 函数 function (1) python只有函数(return)没有过程(no return) (2) 函数返回多个值的时候,使用list列表或tuple元组进行返回 (3) 局部变量和全局变量的规则同C语言 (4) 在函数内部使用 global 修饰变量,使函数可以修改同名的全局变量 (5) 函数嵌套时,内部函数的作用域都在外部函数之内,出了外部函数就不能被调用
函数定义和调用
1 2 3 def function_name (): function_name()
函数返回值
1 2 3 4 def function_name ():return valueprint (function_name())
函数参数
1 2 3 def function_name (param ): function_name(parameter)
函数文档 举例:
1 2 3 4 5 6 7 8 9 10 11 >>> def my_sec_func (name ):'function document.' print (name)>>> my_sec_func('myname' ) myname>>> my_sec_func.__doc__ 'function document.' >>> help (my_sec_func) Help on function my_sec_func in module __main__: my_sec_func(name) function document.
关键字参数与默认参数 举例:
1 2 3 4 5 6 7 8 9 >>> def say_some (name, words ):print (name + ' -> ' + words)>>> say_some('Jan' , 'learning python.' ) Jan -> learning python.>>> say_some(words='learning python.' , name='Jan' ) Jan -> learning python.
*params
搜集其余的位置参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> def test (*params ): print ('len = ' , len (params))print ('second params = ' , params[1 ])>>> test(1 , 'Jan' , 3.14 )len = 3 second params = Jan>>> def test (*params, tmp ):print ('len = ' , len (params))print ('second params = ' , params[1 ])print ('tmp = ' , tmp)>>> test(1 , 'Jan' , 3.14 , tmp = 520 ) len = 3 second params = Jan tmp = 520
global 关键字 举例:
1 2 3 4 5 6 7 8 9 >>> cnt = 5 >>> def my_func ():global cnt cnt= 10 print (cnt)>>> my_func()10 >>> print (cnt)10
函数嵌套 举例:
1 2 3 4 5 6 7 8 >>> def func1 ():print ('func1 called...' )def func2 ():print ('func2 called...' ) func2()>>> func1() func1 called... func2 called...
闭包closure 举例1:
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 >>> def funX (x ):def funY (y ):return x * yreturn funY>>> i = funX(8 )>>> i <function funX.<locals >.funY at 0x000001EFE75E87B8 >>>> type (i) <class 'function' >>>> i(5 )40 >>> funX(8 )(5 )40 >>> funY(5 ) 举例2 - list :>>> def fun1 (): x = [5 ] def fun2 (): x[0 ] *= x[0 ]return x[0 ]return fun2()>>> fun1()25 举例2 - nonlocal :>>> def fun1 (): x = 5 def fun2 ():nonlocal x x *= xreturn xreturn fun2()>>> fun1()25
lambda 表达式(匿名函数) (1) 不需要考虑函数名的命名问题 (2) 极大简化函数编写的步骤 举例:
1 2 3 4 5 6 7 8 9 10 11 12 >>> def ds (x ):return 2 *x + 1 >>> ds(5 )11 >>> lambda x : 2 *x + 1 <function <lambda > at 0x000002170B3D87B8 > >>> g = lambda x : 2 *x + 1 >>> g(5 )11 >>> g = lambda x, y : x+y >>> g(1 , 3 )4
两个牛逼的BIF:filter和map (1) filter 过滤:返回其函数为真的元素的列表
1 >>> filter (function or None , iterable)
举例:
1 2 3 4 5 6 7 8 9 10 11 12 >>> filter (None , [1 , 0 , False , True ]) <filter object at 0x000001CE5BCB0710 >>>> 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 ]
(2) map 映射:对序列中每个元素都应用函数
1 2 >>> list (map (lambda x : x + 2 , range (10 ))) [2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ]
-2017.08.28 --
11. 递归 recursion 1 2 3 4 5 6 7 8 9 10 11 12 def factorial (n ): if n == 1 : return 1 else : return n * factorial(n-1 ) number = int (input ("请输入一个正整数:" )) result = factorial(number)print ("%d 的阶乘为:%d" % (number, result)) 请输入一个正整数:10 10 的阶乘为:3628800
斐波那契数列(递归)
1 2 3 4 5 6 7 8 9 10 11 def fab (n ): if n < 1 : print ("input error!" ) return -1 if n == 1 or n == 2 : return 1 else : return fab(n-1 ) + fab(n-2 ) num = int (input ("请输入一个数字:" )) result = fab(num)print ("斐波那契数列结果为:%d" % result)
汉诺塔游戏(递归)
1 2 3 4 5 6 7 8 9 10 11 def hanoi (n, x, y, z ): if n == 1 : print (x, '-- >' , z) else : hanoi(n-1 , x, y, z) print (x, '-- >' , z) hanoi(n-1 , y, x, z) n = int (input ('请输入汉诺塔的层数:' )) hanoi(n, 'x' , 'y' , 'z' )
-2017.08.29 --
12. 字典 dict (1) 字典是一种映射类型(key:value 键值映射项),类型名为 dict (2) 字典的表示使用{}大括号,元素映射之间使用:冒号,使用dictname[]访问字典映射的值 (3) 新建字典有两种方法:三层小括号,一层小括号中key=value (4) 字典中的键值映射项是无序的,popitem时是随机弹出 (5) 字典基本操作: len(d) 返回d中项的数量 d[k] 返回映射到键k上的值 d[k]=v 将值v映射到键k上 del d[k] 删除键为k的项 k in d 检查d中是否含有键为k的项 (6) 字典常用方法: clear()/copy()/fromkeys()/get()/has_key()/items()/iteritems()/keys()/iterkeys()/pop()/popitem()/setdefault()/update()/values()/itervalues()
映射关系示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 >>> brand = ['李宁' , '耐克' , '阿迪达斯' , 'xx工作室' ]>>> slogan = ['一切皆有可能' , 'Just do it' , 'Impossible is nothing' , '让编程改变世界' ]>>> print ('鱼c工作室的口号是: ' , slogan[brand.index('xx工作室' )]) xx工作室的口号是: 让编程改变世界>>> dict1 = {'李宁' :'一切皆有可能' , '耐克' :'Just do it' , '阿迪达斯' :'Impossible is nothing' , 'xx工作室' :'让编程改变世界' }>>> print ('xx工作室的口号是: ' , dict1['xx工作室' ]) xx工作室的口号是: 让编程改变世界>>> dictname = dict ((('y' , 1 ), ('u' , 2 ), ('a' , 3 ), ('n' , 4 )))>>> dictname {'u' : 2 , 'a' : 3 , 'y' : 1 , 'n' : 4 }>>> dictname = dict (苍井空='让AV改变宅男' , 工作室='让编程改变世界' )>>> dictname {'工作室' : '让编程改变世界' , '苍井空' : '让AV改变宅男' }>>> dictname['苍井空' ]'让AV改变宅男' >>> dictname['爱迪生' ] = '天才是99%的汗水+1%的灵感,但这1%的灵感比99%的汗水更重要。' >>> dictname {'工作室' : '让编程改变世界' , '爱迪生' : '天才是99%的汗水+1%的灵感,但这1%的灵感比99%的汗水更重要。' , '苍井空' : '让AV改变宅男' }
字典中键、值、键值映射项的访问
1 2 3 4 5 6 7 8 9 10 11 12 >>> dict1 = dict1.fromkeys(range (10 ), '赞' )>>> dict1 {0 : '赞' , 1 : '赞' , 2 : '赞' , 3 : '赞' , 4 : '赞' , 5 : '赞' , 6 : '赞' , 7 : '赞' , 8 : '赞' , 9 : '赞' }>>> for eachKey in dict1.keys():print (eachKey, end=' ' )0 1 2 3 4 5 6 7 8 9 >>> for eachValue in dict1.values():print (eachValue, end=' ' ) 赞 赞 赞 赞 赞 赞 赞 赞 赞>>> for eachItems in dict1.items():print (eachItems, end=' ' ) (0 , '赞' ) (1 , '赞' ) (2 , '赞' ) (3 , '赞' ) (4 , '赞' ) (5 , '赞' ) (6 , '赞' ) (7 , '赞' ) (8 , '赞' ) (9 , '赞' )
fromkeys(…) 创建并返回一个新的字典 dictname.fromkeys(S[, V]) @S key;@V value 可选参数 举例:
1 2 3 4 5 6 7 8 9 >>> dict1 = {}>>> dict1.fromkeys((1 , 2 , 3 )) {1 : None , 2 : None , 3 : None }>>> dict1.fromkeys((1 , 2 , 3 ), 'number' ) {1 : 'number' , 2 : 'number' , 3 : 'number' }>>> dict1.fromkeys((1 , 2 , 3 ), ('one' , 'two' , 'three' )) {1 : ('one' , 'two' , 'three' ), 2 : ('one' , 'two' , 'three' ), 3 : ('one' , 'two' , 'three' )}>>> dict1.fromkeys((1 , 3 ), 'num' ) {1 : 'num' , 3 : 'num' }
get(…) 从字典中找到key的映射值value 举例:
1 2 3 4 5 6 7 8 9 10 >>> dict1 = dict .fromkeys(range (10 ), 'Yes!' )>>> dict1 {0 : 'Yes!' , 1 : 'Yes!' , 2 : 'Yes!' , 3 : 'Yes!' , 4 : 'Yes!' , 5 : 'Yes!' , 6 : 'Yes!' , 7 : 'Yes!' , 8 : 'Yes!' , 9 : 'Yes!' }>>> dict1.get(10 )>>> print (dict1.get(10 ))None >>> dict1.get(10 , '木有' )'木有' >>> dict1.get(9 , '木有' )'Yes!'
setdefault(…) 类似于get但在字典里如果找不到的话会将映射项添加到字典中 dictname.setdefault(key, value) 举例:
1 2 3 4 5 6 >>> a {3 : 'three' , 4 : 'four' }>>> a.setdefault(5 , '小白' )'小白' >>> a {3 : 'three' , 4 : 'four' , 5 : '小白' }
clear() 清空一个字典(包括使用当前字典赋值的其他字典) 举例:
1 2 3 >>> dict1.clear()>>> dict1 {}
copy() 拷贝一个字典(浅拷贝,不受字典修改影响)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> a = {1 :'one' , 2 :'two' , 3 :'three' }>>> b = a.copy()>>> c = a >>> a {1 : 'one' , 2 : 'two' , 3 : 'three' }>>> b {1 : 'one' , 2 : 'two' , 3 : 'three' }>>> c {1 : 'one' , 2 : 'two' , 3 : 'three' }>>> print (id (a), id (b), id (c))2334673012680 2334672609672 2334673012680 >>> c[4 ] = 'four' >>> c {1 : 'one' , 2 : 'two' , 3 : 'three' , 4 : 'four' }>>> a {1 : 'one' , 2 : 'two' , 3 : 'three' , 4 : 'four' }>>> b {1 : 'one' , 2 : 'two' , 3 : 'three' }
pop(…) 给定一个键弹出一个值 popitem() 随机弹出一个项(映射关系的键和值) 举例:
1 2 3 4 5 6 7 8 9 10 >>> a {1 : 'one' , 2 : 'two' , 3 : 'three' , 4 : 'four' }>>> a.pop(2 )'two' >>> a {1 : 'one' , 3 : 'three' , 4 : 'four' }>>> a.popitem() (1 , 'one' )>>> a {3 : 'three' , 4 : 'four' }
update(…) 使用一个子字典去更新原字典 dictname1.update(dictname2) 举例:
1 2 3 4 5 6 >>> a {3 : 'three' , 4 : 'four' , 5 : '小白' }>>> b = {'小白' :'狗' }>>> a.update(b)>>> a {'小白' : '狗' , 3 : 'three' , 4 : 'four' , 5 : '小白' }
13. 集合 set (1) 使用{}创建的没有映射关系的字典,成为集合类型,如num = {1, 2, 3, 4, 5} (2) 集合中元素唯一,重复的数据会被自动清理掉 (3) 集合中元素无序,不能索引取到其元素的值 (4) 集合使用关键字 set([]) 来创建 (5) 集合支持 in 和 not in 来判断是否属于集合
举例:
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 >>> num = {}>>> type (num) <class 'dict' >>>> num1 = {1 , 2 , 3 , 4 , 5 }>>> type (num1) <class 'set' >>>> num2 = {1 , 2 , 3 , 4 , 2 , 3 , 5 , 1 , 5 , 5 }>>> num2 {1 , 2 , 3 , 4 , 5 }>>> num2[2 ] TypeError: 'set' object does not support indexing>>> set1 = set ([1 , 2 , 3 , 4 , 5 , 5 , 5 , 3 , 1 ])>>> set1 {1 , 2 , 3 , 4 , 5 }>>> num1 = [1 , 2 , 3 , 4 , 5 , 5 , 3 , 1 , 0 ]>>> temp = []>>> for each in num1:if each not in temp: temp.append(each)>>> temp [1 , 2 , 3 , 4 , 5 , 0 ]>>> num1 [1 , 2 , 3 , 4 , 5 , 5 , 3 , 1 , 0 ]>>> num1 = list (set (num1))>>> num1 [0 , 1 , 2 , 3 , 4 , 5 ]
add(…) 往集合中加入元素 remove(…) 从集合中删除指定元素 举例:
1 2 3 4 5 6 7 8 >>> num2 {1 , 2 , 3 , 4 , 5 }>>> num2.add(6 )>>> num2 {1 , 2 , 3 , 4 , 5 , 6 }>>> num2.remove(4 )>>> num2 {1 , 2 , 3 , 5 , 6 }
frozenset(…) 将集合设置为不可变集合,frozen:冰冻的,冻结的 举例:
1 2 3 4 5 >>> num3 = frozenset ([1 , 2 , 3 , 4 , 5 ])>>> num3frozenset ({1 , 2 , 3 , 4 , 5 })>>> num3.add(6 ) AttributeError: 'frozenset' object has no attribute 'add'
集合内建方法(整理出来):http://bbs.fishc.com/forum.php?mod=viewthread&tid=45276&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
14. 文件操作 file operation open(…) 打开一个文件返回一个流对象 open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) #除了file参数,其他参数均有默认值 ‘r’ 只读模式 ‘w’ 写入(会覆盖已存在的文件)模式 ‘x’ 文件存在,报异常的模式 ‘a’ 写入(文件存在则追加)模式 ‘b’ 二进制模式 ‘t’ 文本模式 ‘+’ 可读写模式(可添加到其他模式) ‘U’ 通用换行符支持
举例:
1 2 3 4 >>> f = open ('C:UsersJanDesktopIP.txt' )>>> f <_io.TextIOWrapper name='C:UsersJanDesktopIP.txt' mode='r' encoding='cp936' >
文件对象方法 (整理)http://bbs.fishc.com/forum.php?mod=viewthread&tid=45279&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403 (1) 文件对象支持直接使用list转换读出 (2) 文件对象支持 for…in 的迭代方式读取
举例:
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 >>> f = open ('C:UsersJanDesktopIP.txt' ) >>> f.read()'【本机】nIP:192.168.31.217n[ Ctrl + r ]ncmdnping 192.168.31.207nmstscnnn【虚拟机】 - 虚拟网络编辑器(自动) - 桥接模式nIP:192.168.31.207nlinux账户:jiangyuannlinux密码:123456n' >>> f.read()'' >>> f.close()>>> f = open ('C:UsersJanDesktopIP.txt' )>>> f.read(5 )'【本机】n' >>> f.tell()10 >>> f.seek(45 , 0 ) 45 >>> f.readline()'mdn' >>> list (f) ['ping 192.168.31.207n' , 'mstscn' , 'n' , 'n' , '【虚拟机】 - 虚拟网络编辑器(自动) - 桥接模式n' , 'IP:192.168.31.207n' , 'linux账户:jiangyuann' , 'linux密码:123456n' ]>>> for each_line in f:print (each_line) 【本机】 IP:192.168 .31 .217 [ Ctrl + r ] cmd ping 192.168 .31 .207 mstsc ...>>> f = open ('C:UsersJanDesktoptest.txt' , 'w' )>>> f.write('some lines' )10 >>> f.close()
任务:将文件record.txt中的数据进行分割并且按照规律保存起来。
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 def save_file (boy, girl, count ): file_name_boy = 'boy_' + str (count) + '.txt' file_name_girl = 'girl_' + str (count) + '.txt' boy_f = open (file_name_boy, 'w' ) girl_f = open (file_name_girl, 'w' ) boy_f.writelines(boy) girl_f.writelines(girl) boy_f.close() girl_f.close()def split_file (filename ): f = open (filename) boy = [] girl = [] count = 1 for each_line in f: if each_line[:6 ] != '======' : (role, line_spoken) = each_line.split(':' , 1 ) if role == '小甲鱼' : boy.append(line_spoken) if role == '小客服' : girl.append(line_spoken) else : save_file(boy, girl, count) boy = [] girl = [] count += 1 save_file(boy, girl, count) f.close() split_file('C:UsersJanDesktoppython_studyrecord.txt' )
文件操作练习题及答案(伪代码可以保存一下):http://blog.csdn.net/junwei0206/article/details/44988195
-2017.08.30 --
15. 模块 modules (1) 模块是.py的python文件 (2) 使用模块是需要进行导入,使用关键字 import
举例:
1 2 3 4 >>> import random>>> secret = random.randint(1 , 10 )>>> secret3
os 模块(系统模块)
os模块方法表格:http://bbs.fishc.com/thread-45512-1-2.html
举例:
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 >>> import os>>> os.getcwd() 'C:UsersJanAppDataLocalProgramsPythonPython35' >>> os.chdir('E:' ) >>> os.getcwd()'E:' >>> os.listdir('E:' ) ['$RECYCLE.BIN' , '.cache' , '360Downloads' , 'Jan_mi' , 'Jan个人总资料' , 'Qiyi' , 'QQMusicCache' , 'qycache' , 'System Volume Information' , 'Youku Files' , 'Youxun' , '博客' ] >>> os.mkdir('E:A' ) >>> os.mkdir('E:AB' )>>> os.mkdir('E:CD' ) FileNotFoundError: [WinError 3 ] 系统找不到指定的路径。: 'E:CD' >>> os.remove('E:ABtest.txt' ) >>> os.rmdir('E:AB' ) >>> os.system('cmd' ) -1073741510 >>> os.system('calc' ) 0 >>> os.curdir '.' >>> os.listdir(os.curdir) ['$RECYCLE.BIN' , '.cache' , '360Downloads' , 'A' , 'Jan_mi' , 'Jan个人总资料' , 'Qiyi' , 'QQMusicCache' , 'qycache' , 'System Volume Information' , 'Youku Files' , 'Youxun' , '博客' ]>>> os.sep '' >>> os.linesep 'rn' >>> os.name 'nt'
os.path 模块(系统路径模块属于os的子模块)
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 >>> os.path.basename('E:ABCsexy.avi' ) 'sexy.avi' >>> os.path.dirname('E:ABCsexy.avi' ) 'E:ABC' >>> os.path.join('A' , 'B' , 'C' ) 'ABC' >>> os.path.join('D:' , 'A' , 'B' , 'C' )'D:ABC' >>> os.path.join('D:' , 'A' , 'B' , 'C' ) 'D:ABC' >>> os.path.split('E:ASEXY.AVI' ) ('E:A' , 'SEXY.AVI' )>>> os.path.split('E:ABC' ) ('E:AB' , 'C' )>>> os.path.splitext('E:ASEXY.AVI' ) ('E:ASEXY' , '.AVI' )>>> os.path.getatime('E:Atest.txt' ) 1504103243.229383 >>> import time>>> time.gmtime(os.path.getatime('E:Atest.txt' )) time.struct_time(tm_year=2017 , tm_mon=8 , tm_mday=30 , tm_hour=14 , tm_min=27 , tm_sec=23 , tm_wday=2 , tm_yday=242 , tm_isdst=0 )>>> time.localtime(os.path.getatime('E:Atest.txt' )) time.struct_time(tm_year=2017 , tm_mon=8 , tm_mday=30 , tm_hour=22 , tm_min=27 , tm_sec=23 , tm_wday=2 , tm_yday=242 , tm_isdst=0 )>>> time.localtime(os.path.getmtime('E:Atest.txt' )) time.struct_time(tm_year=2017 , tm_mon=8 , tm_mday=30 , tm_hour=22 , tm_min=30 , tm_sec=1 , tm_wday=2 , tm_yday=242 , tm_isdst=0 )>>> time.localtime(os.path.getctime('E:Atest.txt' )) time.struct_time(tm_year=2017 , tm_mon=8 , tm_mday=30 , tm_hour=22 , tm_min=27 , tm_sec=23 , tm_wday=2 , tm_yday=242 , tm_isdst=0 )>>> os.path.ismount('E:' ) True >>> os.path.ismount('E:A' )False
pickle 模块(泡菜模块) 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >>> import pickle>>> my_list = [123 , 3.14 , '名字' , ['another list' ]]>>> pickle_f = open ('E:Amy_list.pkl' , 'wb' )>>> pickle.dump(my_list, pickle_f) >>> pickle_f.close()>>> pickle_f = open ('E:Amy_list.pkl' , 'rb' )>>> my_list2 = pickle.load(pickle_f) >>> print (my_list2) [123 , 3.14 , '名字' , ['another list' ]]>>> city = {'城市1' :'000001' , '城市2' :'000002' , '城市n' :'999999' } >>> import pickle>>> pickle_f = open ('E:Acity.pkl' , 'wb' ) >>> pickle.dump(city, pickle_f)>>> pickle_f.close()>>> pickle_file = open ('E:Acity.pkl' , 'rb' ) >>> city = pickle.load(pickle_file)>>> print (city) {'城市2' : '000002' , '城市n' : '999999' , '城市1' : '000001' }
-2017.08.31 --
16. 异常 exception 异常汇总
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 AssertionError 断言语句(assert )失败<eg1> AttributeError 尝试访问未知的对象属性<eg2> EOFError 用户输入文件末尾标志EOF(Ctrl+d) FloatingPointError 浮点计算错误 GeneratorExit generator.close()方法被调用的时候 ImportError 导入模块失败的时候 IndexError 索引超出序列的范围<eg3> KeyError 字典中查找一个不存在的关键字<eg4> KeyboardInterrupt 用户输入中断键(Ctrl+c) MemoryError 内存溢出(可通过删除对象释放内存) NameError 尝试访问一个不存在的变量 NotImplementedError 尚未实现的方法 OSError 操作系统产生的异常(例如打开一个不存在的文件) OverflowError 数值运算超出最大限制 ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 RuntimeError 一般的运行时错误 StopIteration 迭代器没有更多的值 SyntaxError Python的语法错误 IndentationError 缩进错误 TabError Tab和空格混合使用 SystemError Python编译器系统错误 SystemExit Python编译器进程被关闭 TypeError 不同类型间的无效操作 UnboundLocalError 访问一个未初始化的本地变量(NameError的子类) UnicodeError Unicode相关的错误(ValueError的子类) UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类) UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类) UnicodeTranslateError Unicode转换时的错误(UnicodeError的子类) ValueError 传入无效的参数 ZeroDivisionError 除数为零
部分举例:
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 >>> my_list = ['我是帅哥' , '你是美女' ]>>> assert len (my_list) > 0 >>> my_list.pop()'你是美女' >>> my_list.pop()'我是帅哥' >>> assert len (my_list) > 0 Traceback (most recent call last): File "<pyshell#856>" , line 1 , in <module> assert len (my_list) > 0 AssertionError >>> my_list.abcd Traceback (most recent call last): File "<pyshell#857>" , line 1 , in <module> my_list.abcd AttributeError: 'list' object has no attribute 'abcd' >>> my_list = [1 , 2 , 3 ]>>> my_list[3 ] Traceback (most recent call last): File "<pyshell#859>" , line 1 , in <module> my_list[3 ] IndexError: list index out of range >>> my_list[2 ]3 >>> my_dict = {'one' :1 , 'two' :2 , 'three' :3 }>>> my_dict['one' ]1 >>> my_dict['four' ] Traceback (most recent call last): File "<pyshell#863>" , line 1 , in <module> my_dict['four' ] KeyError: 'four' >>> my_dict.get('four' )>>>
异常检测与处理 (1) try语句一旦检测出现异常,则剩下的其他代码则不会执行 (2) raise Exception_name 主动引发一个自定义异常名字的异常,可定义异常描述
try:
1 2 3 4 5 except Exception[as reason]:finally :
举例:
1 2 3 4 5 6 7 8 try : f = open ('我为什么是一个文件.txt' ) print (f.read()) f.close()except OSError: print ('文件出错啦T_T' ) 运行: 文件出错啦T_T
1 2 3 4 5 6 7 8 9 try : f = open ('我为什么是一个文件.txt' ) print (f.read()) f.close()except OSError as reason: print ('文件出错啦T_Tn错误的原因是:' + str (reason)) 运行: 文件出错啦T_T 错误的原因是:[Errno 2 ] No such file or directory: '我为什么是一个文件.txt'
1 2 3 4 5 6 7 8 try : sum = 1 + '1' f = open ('我为什么是一个文件.txt' ) print (f.read()) f.close()except (OSError, TypeError): print ('出错啦T_T' ) 运行:出错啦T_T
1 2 3 4 5 6 7 8 9 10 11 12 try : f = open ('我为什么是一个文件.txt' , 'w' ) print (f.write('我存在了!' )) sum = 1 + '1' f.close()except (OSError, TypeError): print ('出错啦T_T' )finally : f.close() 运行:5 出错啦T_T
1 2 3 4 5 >>> raise ZeroDivisionError('除数为0的异常' ) Traceback (most recent call last): File "<pyshell#872>" , line 1 , in <module> raise ZeroDivisionError('除数为0的异常' ) ZeroDivisionError: 除数为0 的异常
17. 丰富的esle-简洁的with else
举例:while-else / for-else
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def showMaxFactor (num ): count = num // 2 while count > 1 : if num % count == 0 : print ('%d最大的约数是%d' % (num, count)) break count -= 1 else : print ('%d是素数!' % num) num = int (input ('请输入一个数:' )) showMaxFactor(num)
举例:try-else
1 2 3 4 5 6 7 8 9 try : print (int ('123' ))except ValueError as reason: print ('出错啦:' + str (reason))else : print ('Good!没有任何异常。' ) 运行:123 Good!没有任何异常。
with as
举例:
1 2 3 4 5 6 7 8 try : with open ('data.txt' , 'w' ) as f: for each_line in f: print (each_line)except OSError as reason: print ('出错啦:' + str (reason))
18. 图形用户界面 EasyGui EasyGui官网:http://easygui.sourceforge.net 中文的教学文档:http://bbs.fishc.com/thread-46069-1-1.html (要看完并实操) 模块库:easygui-0.96.zip
安装方法: (1) 使用命令窗口切换到easygui-docs-0.96的目录下 (2) 【Windows下】执行C:Python33python.exe setup.py install
1 2 3 4 5 6 7 8 > cd Desktop > cd puthon_studyeasygui-0.96 > "C:Program Files (x86)pythonpython.exe" setup.py install > "C:Program Files (x86)pythonpython.exe" easygui.py PS: 【Linux或Mac下】sudo /Library/Framworks/Python.framework/Versions/3.3 /bin /python3.3 setup.py install
使用方法: 【遇到难题】import easygui 出错~!!! 【解决办法】 (1) 重装python IDLE勾选添加python路径,选择目录安装到C:python文件夹,如重装则忽略(2),如此一来win-cmd下的python中sys.path和IDLE中的sys.path则一致了。 (2) 对比windows命令窗口中启动python与IDLE中python的系统路径,添加到IDLE即可。
windows中系统路径: C:UsersJan> “C:Program Files (x86)pythonpython.exe”
1 2 3 4 5 6 7 8 >>> import sys>>> sys.path ['' , 'C:Program Files (x86)pythonpython35.zip' , 'C:Program Files (x86)pythonDLLs' , 'C:Program Files (x86)pythonlib' , 'C:Program Files (x86)python' , 'C:Program Files (x86)pythonlibsite-packages' ]
IDLE中系统路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 >>> import easygui as g Traceback (most recent call last): File "<pyshell#0>" , line 1 , in <module> import easygui as g ImportError: No module named 'easygui' >>> import sys>>> sys.path ['' , 'C:UsersJanAppDataLocalProgramsPythonPython35Libidlelib' , 'C:UsersJanAppDataLocalProgramsPythonPython35python35.zip' , 'C:UsersJanAppDataLocalProgramsPythonPython35DLLs' , 'C:UsersJanAppDataLocalProgramsPythonPython35lib' , 'C:UsersJanAppDataLocalProgramsPythonPython35' , 'C:UsersJanAppDataLocalProgramsPythonPython35libsite-packages' ]>>> sys.path.append('C:Program Files (x86)pythonpython35.zip' )>>> sys.path.append('C:Program Files (x86)pythonDLLs' )>>> sys.path.append('C:Program Files (x86)pythonlib' )>>> sys.path.append('C:Program Files (x86)python' )>>> sys.path.append('C:Program Files (x86)pythonlibsite-packages' )>>> import easygui as g >>> g.msgbox('嗨,python!' )'OK' >>>
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 import easygui as gimport syswhile 1 : g.msgbox("嗨,欢迎进入第一个界面小游戏^_^" ) msg ="请问你希望在鱼C工作室学习到什么知识呢?" title = "小游戏互动" choices = ["谈恋爱" , "编程" , "OOXX" , "琴棋书画" ] choice = g.choicebox(msg, title, choices) g.msgbox("你的选择是: " + str (choice), "结果" ) msg = "你希望重新开始小游戏吗?" title = "请选择" if g.ccbox(msg, title): pass else : sys.exit(0 )
-2017.09.01 --
19. 类和对象 class and object 面向对象(Object Oriented) (1) python约定类名以大写字母开头 (2) 面向对象特征:封装(信息隐蔽)、继承(子类共享父类公共内容)、多态(不同对象对同一方法响应不同的行动)
类的示例:
1 2 3 4 5 6 7 class Turtle : color = 'green' weight = 60 legs = 2 shell = True age = 26
1 2 3 4 5 def climb (self ):print ('我正在学习...' )def run (self ):print ('我正在奔跑...' )
运行:
1 2 3 4 5 6 7 8 9 10 11 >>> tt = Turtle() >>> Turtle <class '__main__.Turtle' >>>> type (Turtle) <class 'type' >>>> type ('abc' ) <class 'str' >>>> tt.climb() 我正在学习...>>> tt.run() 我正在奔跑...
1 2 3 4 5 6 7 8 >>> list1 = [2 , 1 , 7 , 5 , 3 ]>>> list1.sort() >>> list1 [1 , 2 , 3 , 5 , 7 ]>>> list1.append(9 ) >>> list1 [1 , 2 , 3 , 5 , 7 , 9 ]
1 2 3 4 5 6 7 8 9 10 11 12 >>> class Mylist (list ):pass >>> list2 = Mylist()>>> list2.append(5 ) >>> list2.append(3 )>>> list2.append(7 )>>> list2 [5 , 3 , 7 ]>>> list2.sort()>>> list2 [3 , 5 , 7 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> class A :def fun (self ):print ('我是小A' )>>> class B :def fun (self ):print ('我是小B' )>>> a = A()>>> b = B()>>> a.fun() 我是小A>>> b.fun() 我是小B
self 相当于C++的this指针(指向当前对象本身的地址),表明类自身 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> class Ball :def setName (self, name ): self.name = namedef kick (self ): print ('我叫%s, 该死的谁踢我...' % self.name)>>> a = Ball()>>> a.setName('球A' )>>> b = Ball()>>> b.setName('球B' )>>> c = Ball()>>> c.setName('土豆' )>>> a.kick() 我叫球A, 该死的谁踢我...>>> c.kick() 我叫土豆, 该死的谁踢我...
魔法方法:init (self)init (self, parma1, parma2, …) 举例:
1 2 3 4 5 6 7 8 9 10 >>> class Ball :def __init__ (self, name ): self.name = namedef kick (self ):print ('我叫%s,该死的,谁踢我!!' % self.name)>>> b = Ball('土豆' )>>> b.kick() 我叫土豆,该死的,谁踢我!!>>> a = Ball() TypeError: __init__() missing 1 required positional argument: 'name'
公有和私有 name mangling 名字改变/名字重造 公有成员:默认创建的成员均为公有。 私有成员: (1) 在变量或函数名前加上 “_
“ 两个下划线即可。 (2) python中类的私有均属于伪私有,通过”对象._类_变量
“的形式可以访问私有成员 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> class Person : __name = 'yuan.jiang' >>> p = Person()>>> p.name AttributeError: 'Person' object has no attribute 'name' >>> p.__name AttributeError: 'Person' object has no attribute '__name' >>> class Person : __name = 'yuan.jiang' def getName (self ):return self.__name>>> p = Person()>>> p.getName()'yuan.jiang' >>> p._Person__name 'yuan.jiang'
继承 inherit class DerivedClassName(BaseClassName): … (1) 如果子类中定义于父类同名的成员时,则会自动覆盖父类对应的方法或属性 (2) 解决子类中__init()
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 >>> class Parent :def hello (self ):print ('正在调用父类的方法...' )>>> class Child (Parent ):pass >>> p = Parent()>>> p.hello() 正在调用父类的方法...>>> c = Child()>>> c.hello() 正在调用父类的方法...>>> class Child (Parent ):def hello (self ):print ('正在调用子类的方法...' )>>> c = Child()>>> c.hello() 正在调用子类的方法...>>> p.hello() 正在调用父类的方法...
举例:
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 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 Goldfish (Fish ): pass class Carpfish (Fish ): pass class Salmonfish (Fish ): pass class Sharkfish (Fish ): def __init__ (self ): self.hungry = True def eat (self ): if self.hungry: print ('吃货的梦想就是天天有的吃^_^' ) self.hungry = False else : print ('太撑了,吃不下了!' ) 运行:>>> fish = Fish()>>> fish.move() 我的位置是: 3 0 >>> fish.move() 我的位置是: 2 0 >>> goldfish = Goldfish()>>> goldfish.move() 我的位置是: 4 9 >>> goldfish.move() 我的位置是: 3 9 >>> shark = Sharkfish()>>> shark.eat() 吃货的梦想就是天天有的吃^_^>>> shark.eat() 太撑了,吃不下了!>>> shark.move() AttributeError: 'Sharkfish' object has no attribute 'x'
2017.09.02
覆盖属性或方法问题优化 问题:针对子类属性或方法覆盖父类属性或方法的情况,导致子类无法访问父类中被覆盖的属性 (1) 调用未绑定的父类的方法 (2) 使用super方法(推荐) 举例: def init (self): Fish.init (self) #调用未绑定的父类的方法,相当于
1 2 3 4 5 6 7 8 >>>Fish.__init__(Sharkfish) self.hungry = True 运行:>>> shark = Sharkfish()>>> shark.move() 我的位置是: -1 2 >>> shark.move() 我的位置是: -2 2
举例: def init (self): super().init () #使用super方法解决 self.hungry = True 运行:
1 2 3 4 5 >>> shark = Sharkfish()>>> shark.move() 我的位置是: 8 3 >>> shark.move() 我的位置是: 7 3
多重继承 class DerivedClassName(Base1, Base2, Base3, …): …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> class Base1 :def fool (self ):print ('我是fool,我为Base1代言...' )>>> class Base2 :def fool2 (self ):print ('我是fool2,我为Base2代言...' )>>> class C (Base1, Base2):pass >>> c = C()>>> c.fool() 我是fool,我为Base1代言...>>> c.fool2() 我是fool2,我为Base2代言...
组合
1 2 3 4 5 6 7 8 9 10 11 12 class Turtle : def __init__ (self, x ): self.num = xclass Fish : def __init__ (self, x ): self.num = xclass 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))
运行:
1 2 3 >>> pool = Pool(1 , 10 )>>> pool.print_num() 水池里总共有乌龟 1 只,小鱼 10 条!
类、类对象、示例对象 类定义 C 类对象 C 实例对象 a b c 举例:
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 >>> class C : count = 0 >>> a = C() >>> b = C() >>> c = C() >>> a.count0 >>> b.count0 >>> c.count0 >>> c.count += 10 >>> c.count10 >>> a.count0 >>> b.count0 >>> C.count 0 >>> C.count += 100 >>> a.count100 >>> b.count100 >>> c.count10
(1) 当属性名与方法名冲突,会导致方法不能正常调用。 (2) 一般遵循规则:属性名用英文名词,方法名用英文动词。 (3) python严格要求方法需要有实例才能被调用,即绑定的概念。
举例:
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 55 56 57 58 >>> class C :def x (self ):print ('X-man!' )>>> c = C()>>> c.x() X-man!>>> c.x = 1 >>> c.x1 >>> c.x() TypeError: 'int' object is not callable >>> class BB :def printBB ():print ('no zuo no die.' )>>> BB.printBB() no zuo no die.>>> >>> bb = BB()>>> bb.printBB() Traceback (most recent call last): File "<pyshell#187>" , line 1 , in <module> bb.printBB() TypeError: printBB() takes 0 positional arguments but 1 was given>>> class CC :def setXY (self, x, y ): self.x = x; self.y = y>>> class CC :def setXY (self, x, y ): self.x = x self.y = ydef printXY (self ):print (self.x, self.y)>>> dd = CC()>>> dd.__dict__ {} >>> CC.__dict__ mappingproxy({'printXY' : <function CC.printXY at 0x0000020483176EA0 >, '__doc__' : None , '__dict__' : <attribute '__dict__' of 'CC' objects>, 'setXY' : <function CC.setXY at 0x0000020483176E18 >, '__module__' : '__main__' , '__weakref__' : <attribute '__weakref__' of 'CC' objects>}) >>> dd.setXY(4 , 5 )>>> dd.__dict__ {'y' : 5 , 'x' : 4 } >>> >>> del CC>>> ee = CC() NameError: name 'CC' is not defined>>> dd.printXY()4 5
类与对象的内置函数 issubclass 功能:测试一个类是否是另外一个类的子类 issubclass(class, classinfo) (1) 一个类被认为是其自身的子类 (2) classinfo可以是类对象的元组,只要class属于其中任何一个候选类的子类,则返回True 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> class A :pass >>> class B (A ):pass >>> issubclass (B, A)True >>> issubclass (B, B)True >>> issubclass (B, object ) True >>> class C :pass >>> issubclass (B, C)
isinstance 功能:测试一个对象是否是一个类的实例对象 isinstance(object, classinfo) (1) object为类的实例对象,如果不是类的实例对象,永远返回False (2) 如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> class A :pass >>> class B (A ):pass >>> class C :pass >>> b1 = B()>>> isinstance (b1, B)True >>> isinstance (b1, A)True >>> isinstance (b1, C)False >>> isinstance (b1, (A, B, C)) True
hasattr 功能:测试一个对象里面是否有指定的属性 hasattr(object, name) (1) object 对象名, name 是属性名(需要用引号引起来,否则报错)
getattr 功能:返回对象指定的属性值 getattr(object, name[, default]) (1) 如果属性值不存在打印default,没有default则抛出异常
setattr 功能:设置对象中指定属性的值,如果属性不存在则创建并赋值 setattr(object, name, value)
delattr 功能:删除对象中指定的属性,如果属性不存在则抛出异常 delattr(object, name)
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 >>> class C :def __init__ (self, x=0 ): self.x = x>>> c1 = C()>>> hasattr (c1, 'x' ) True >>> hasattr (c1, x) NameError: name 'x' is not defined>>> getattr (c1, 'x' ) 0 >>> getattr (c1, 'y' ) AttributeError: 'C' object has no attribute 'y' >>> getattr (c1, 'y' , '您所访问的属性不存在!' ) '您所访问的属性不存在!' >>> setattr (c1, 'y' , 100 ) >>> getattr (c1, 'y' )100 >>> delattr (c1, 'y' ) >>> delattr (c1, 'y' ) Traceback (most recent call last): File "<pyshell#264>" , line 1 , in <module> delattr (c1, 'y' ) AttributeError: y
property 功能:设置一个定义好的属性,通过对象属性来设置对象属性 property(fget=None, fset=None, fdel=None, doc=None) (1) fget获取属性的方法, fset设置属性的方法, fdel删除属性的方法 举例:
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 >>> class C :def __init__ (self, size=10 ): self.size = sizedef getSize (self ):return self.sizedef setSize (self, value ): self.size = valuedef delSize (self ):del self.size x = property (getSize, setSize, delSize)>>> c1 = C()>>> c1.getSize()10 >>> c1.x10 >>> c1.x = 18 >>> c1.x18 >>> c1.getSize()18 >>> c1.size18 >>> del c1.x>>> c1.size AttributeError: 'C' object has no attribute 'size'
20. 魔法方法 magic methods (1) 魔法方法总是被双下划綫包围,如 __init__
(2) 魔法方法是面向对象的python的一切 (3) 魔法方法的魔力体现在能够在适当的时候被调用
魔法方法汇总:http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
__init__
(self[, …]) 功能:初始化类对象(根据需求决定是否增加属性参数) 返回值: None 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> class Rectangle : def __init__ (self, x, y ): self.x = x self.y = ydef getPeri (self ): return (self.x + self.y) * 2 def getArea (self ): return self.x * self.y>>> rect = Rectangle(3 , 4 )>>> rect.getPeri()14 >>> rect.getArea()12
__new__
(class[, …]) 功能:创建一个类对象 返回值:返回一个对象 (1) 在__init__方法之前被调用,属于类创建时第一个被调用的方法 举例:
1 2 3 4 5 6 7 >>> class CapStr (str ): def __new__ (cls, string ): string = string.upper()return str .__new__(cls, string) >>> a = CapStr("I love M." )>>> a'I LOVE M.'
__del__
(self) 功能:对象将要被销毁的时候,自动调用,属于自动垃圾回收方法 注意:del x != x.__del__()
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> class C :def __init__ (self ):print ('我是init方法,我被调用了!' )def __del__ (self ):print ('我是del方法,我被调用了!' )>>> c1 = C() 我是init方法,我被调用了!>>> c2 = c1 >>> c3 = c2>>> del c3>>> del c2>>> del c1 我是del 方法,我被调用了!
算术运算魔法方法
1 2 3 4 5 6 7 8 9 10 11 12 13 __add__(self, other) 加法:+ __sub__(self, other) 减法:- __mul__(self, other) 乘法:* __truediv__(self, other) 真除法:/ __floordiv__(self, other) 整数除法:// __mod__(self, other) 取模算法:% __divmod__(self, other) divmod ()调用时的行为 __pow__(self, other[, modulo]) power()调用或 ** 运算时的行为 __lshift__(self, other) 按位左移:<< __rshift__(self, other) 按位右移:>> __and__(self, other) 按位与:& __xor__(self, other) 按位异或:^ __or__(self, other) 按位或:|
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >>> class New_int (int ):def __add__ (self, other ):return int .__sub__(self, other)def __sub__ (self, other ):return int .__add__(self, other)>>> a = New_int(3 )>>> b = New_int(5 )>>> a + b -2 >>> a - b8 >>> class Try_int (int ):def __add__ (self, other ):return int (self) + int (other)def __sub__ (self, other ):return int (self) - int (other)>>> a = Try_int(3 )>>> b = Try_int(5 )>>> a + b8
类定制的计时器 (1) 定制一个计时器的类 (2) start和stop方法代表启动计时和停止计时 (3) 假设计时器对象t1,print(t1)和直接调用t1均显示结果 (4) 当计时器未启动或已经停止计时,调用stop方法会给与温馨的提示 (5) 两个计时器对象可以进行相加:t1 + t2 需要的资源: (1) 使用time模块的localtime方法获取时间 (2) __str__
方法 __repr__
方法可用来打印文字
time 模块 详解链接:http://bbs.fishc.com/forum.php?mod=viewthread&tid=51326&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
struct_time元组 time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=12, tm_min=18, tm_sec=55, tm_wday=5, tm_yday=245, tm_isdst=0)
类定制计时器代码:http://blog.csdn.net/sinat_36184075/article/details/77806778
属性访问
1 2 3 4 __getattribute__(self, name) __getattr__(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 23 >>> class C :def __getattribute__ (self, name ):print ('getattribute' )return super ().__getattribute__(name)def __getattr__ (self, name ):print ('getattr' )def __setattr__ (self, name, value ):print ('setattr' )super ().__setattr__(name, value)def __delattr__ (self, name ):print ('delattr' )super ().__delattr__(name)>>> c = C()>>> c.x getattributegetattr >>> c.x = 1 setattr >>> c.x getattribute1 >>> del c.xdelattr
举例:属性访问时的严重问题,无限递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 : super ().__setattr__(name, value) def getArea (self ): return self.width * self.height
运行:
1 2 3 4 5 6 7 8 9 10 11 12 >>> r1 = Rectangle(4 , 5 )>>> r1.getArea()20 >>> r1.square = 10 >>> r1.width10 >>> r1.height10 >>> r1.getArea()100 >>> r1.__dict__ {'width' : 10 , 'height' : 10 }
2017.09.03
描述符 decriptor
1 2 3 4 5 6 7 8 描述符就是将某种特殊类型的类的实例指派给另一个类的属性。 __get__(self, instance, owner) __set__(self, instance, value) __delete__(self, instance) @self, 描述符类本身的类实例 @instance, 拥有者的类实例 @owner, 拥有者类本身 @value, 所赋的值
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 >>> class MyDecriptor :def __get__ (self, instance, owner ):print ('getting: ' , self, instance, owner)def __set__ (self, instance, value ):print ('setting: ' , self, instance, value)def __delete__ (self, instance ):print ('deleting: ' , self, instance)>>> class Test : x = MyDecriptor()>>> >>> test = Test() >>> test.x getting: <__main__.MyDecriptor object at 0x000002164DC31FD0 > <__main__.Test object at 0x000002164DBB6F28 > <class '__main__.Test' >>>> test <__main__.Test object at 0x000002164DBB6F28 >>>> test.x = 'X-man' setting: <__main__.MyDecriptor object at 0x000002164DC31FD0 > <__main__.Test object at 0x000002164DBB6F28 > X-man>>> del test.x deleting: <__main__.MyDecriptor object at 0x000002164DC31FD0 > <__main__.Test object at 0x000002164DBB6F28 >
自定义的描述符
1 2 3 4 5 6 7 8 9 10 11 >>> class MyProperty :def __init__ (self, fget=None , fset=None , fdel=None ): self.fget = fget self.fset = fset self.fdel = fdeldef __get__ (self, instance, owner ):return self.fget(instance) def __set__ (self, instance, value ): self.fset(instance, value)def __delete__ (self, instance ): self.fdel(instance)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >>> class C :def __init__ (self ): self._x = None def getX (self ):return self._xdef setX (self, value ): self._x = valuedef delX (self ):del self._x x = MyProperty(getX, setX, delX)>>> c = C()>>> c.x = 'X-man' >>> c.x'X-man' >>> c._x'X-man' >>> del c.x
练习:温度转换 定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性。 要求两个属性会自动进行转换,也就是说可以给摄氏度这个属性赋值,打印华氏度是自动转换后的结果。 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Celsius : def __init__ (self, value = 26.0 ): 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 = round ((float (value) - 32 ) / 1.8 , 1 )
class Temperature: cel = Celsius() #摄氏度 fah = Fahrenheit() #华氏度, fah在实例对象中被赋值时调用对应类的__set__ 运行:
1 2 3 4 5 6 7 8 9 >>> temp = Temperature()>>> temp.cel26.0 >>> temp.cel = 30 >>> temp.fah86.0 >>> temp.fah = 100 >>> temp.cel37.8
定制序列(容器) (1) 如果希望定制的容器不可变,只需要定义魔法方法__len__()和__getitem__() (2) 如果希望定制的容器可变,需要定义__len__()和__getitem__()和__setitem__()和__delitem__()
魔法方法详解:http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
练习: 编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数。
1 2 3 4 5 6 7 8 9 10 11 12 13 class CountList : def __init__ (self, *args ): self.values = [x for x in args] self.count = {}.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]
运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> c1 = CountList(1 , 3 , 5 , 7 , 9 )>>> c2 = CountList(2 , 4 , 6 , 7 , 10 )>>> c1[1 ] 3 >>> c2[1 ]4 >>> c1[1 ] + c2[1 ] 7 >>> c1.count {0 : 0 , 1 : 2 , 2 : 0 , 3 : 0 , 4 : 0 }>>> c1[1 ] 3 >>> c1.count {0 : 0 , 1 : 3 , 2 : 0 , 3 : 0 , 4 : 0 }
迭代器 iter-next iter iter() 内置方法, 功能:返回一个迭代器对象__iter__
() 魔法方法
next next() 内置方法__next__
() 魔法方法
for循环迭代器:
1 2 3 4 5 6 7 8 9 10 >>> links = {'百度' :'http://www.baidu.com' , '谷歌' :'http://www.google.com' , '搜狗' :'http://www.sougou.com' , '腾讯' :'http://www.qq.com' }>>> for each in links:print ("%s -> %s" % (each, links[each])) 谷歌 -> http://www.google.com 搜狗 -> http://www.sougou.com 腾讯 -> http://www.qq.com 百度 -> http://www.baidu.com
iter迭代器:
1 2 3 4 5 6 7 8 9 10 >>> string = 'yuan.jiang' >>> it = iter (string)>>> while True :try : each = next (it)except StopIteration:break ;print (each, end=' ' ) 运行: y u a n . j i a n g
斐波那契数列迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >>> class Fibs : def __init__ (self, n=10 ): self.a = 0 self.b = 1 self.n = ndef __iter__ (self ):return self def __next__ (self ): self.a, self.b = self.b, self.a+self.bif self.a > self.n:raise StopIterationreturn self.a>>> fibs = Fibs()>>> for each in fibs:print (each, end=' ' )1 1 2 3 5 8 >>> fibs = Fibs(100 )>>> for each in fibs:print (each, end=' ' )1 1 2 3 5 8 13 21 34 55 89
生成器 yield (1) 生成器是一种特殊的迭代器,兼容next()内置方法 (2) 生成器模仿了协同程序 协同程序:可以运行的对立函数调用,函数可以暂停或挂起,并再需要的时候从程序离开的地方继续活着重新开始。 举例:
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 >>> def MyGen ():print ('生成器被执行!' )yield 1 yield 2 >>> myg = MyGen()>>> next (myg) 生成器被执行!1 >>> next (myg)2 >>> next (myg) StopIteration>>> for i in MyGen(): print (i) 生成器被执行!1 2 >>> def fibs (): a = 0 b = 1 while True : a, b = b, a+byield a>>> for each in fibs():if each > 100 :break print (each, end=' ' )1 1 2 3 5 8 13 21 34 55 89
列表推导式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 >>> a = [i for i in range (100 ) if not (i % 2 ) and (i % 3 )] >>> a [2 , 4 , 8 , 10 , 14 , 16 , 20 , 22 , 26 , 28 , 32 , 34 , 38 , 40 , 44 , 46 , 50 , 52 , 56 , 58 , 62 , 64 , 68 , 70 , 74 , 76 , 80 , 82 , 86 , 88 , 92 , 94 , 98 ]>>> 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 }>>> c = {i for i in [1 , 1 , 2 , 3 , 4 , 5 , 5 , 6 , 7 , 8 , 3 , 2 , 1 ]} >>> c {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }>>> e = (i for i in range (10 )) >>> e <generator object <genexpr> at 0x00000261E200A7D8 >>>> next (e)0 >>> next (e)1 >>> for each in e:print (each, end=' ' )2 3 4 5 6 7 8 9 >>> sum (i for i in range (100 ) if i % 2 )2500
生成器扩展阅读:http://bbs.fishc.com/forum.php?mod=viewthread&tid=56023&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
21. 模块 module 容器 -> 数据的封装 函数 -> 语句的封装 类 -> 方法和属性的封装 模块 -> 程序的封装,其实就是.py的python程序 (1) import导入的.py模块文件必须放在与python.exe同一目录下,即可正确导入。 (2) 导入方法有三种: ① import 模块名 ② from 模块名 import 函数名1, 函数名2, … #不建议这样用,可能会覆盖系统函数 ③ import 模块名 as 新名字 举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 在python下新建test_module文件夹:C:pythontest_module C:pythontest_moduleTempeatureConversion.py C:pythontest_modulecalc.pydef c2f (cel ): fah = cel * 1.8 + 32 def f2c (fah ): cel = round ((fah - 32 ) / 1.8 , 1 ) return celimport TemperatureConversion as tcprint ('32摄氏度 = %.1f华氏度' % tc.c2f(32 ))print ('99华氏度 = %.1f摄氏度' % tc.f2c(99 ))
运行calc.py:
1 2 3 4 =================== RESTART: C:pythontest_modulecalc.py ===================32 摄氏度 = 89.6 华氏度99 华氏度 = 37.2 摄氏度>>>
__name__
说明if __name__ = '__main__'
: #决定是.py文件中的代码是当前程序运行,还是导入到其他程序中作为模块使用而运行 作用:限制为自身.py程序运行才执行的代码区域
搜索路径 path (1) 最佳存放模块的目录:C:pythonlibsite-packages
1 2 3 4 5 6 7 8 9 >>> import sys>>> sys.path ['' , 'C:pythonLibidlelib' , 'C:pythonpython35.zip' , 'C:pythonDLLs' , 'C:pythonlib' , 'C:python' , 'C:pythonlibsite-packages' ]>>> sys.path.append('C:pythontest_module' ) >>> sys.path ['' , 'C:pythonLibidlelib' , 'C:pythonpython35.zip' , 'C:pythonDLLs' , 'C:pythonlib' , 'C:python' , 'C:pythonlibsite-packages' , 'C:pythontest_module' ]>>> import TemperatureConversion as temp>>> temp.c2f(32 )89.6
包 package (1) python目录下创建一个文件夹,用于存放相关的模块,文件夹的名字即包(package)的名字 (2) 在文件夹中创建一个 init .py 的模块文件,内容可以为空 举例:
1 2 3 4 5 6 7 C:pythontest_modulecalc.py C:pythontest_moduleM1TemperatureConversion.py C:pythontest_moduleM1__init__.py import M1.TemperatureConversion as tcprint ('32摄氏度 = %.1f华氏度' % tc.c2f(32 ))print ('99华氏度 = %.1f摄氏度' % tc.f2c(99 ))
自带电池:python标准库 (1) 电池:python-IDLE 帮助文档 F1 (2) 来自全球开发者贡献的python模块:https://pypi.python.org/pypi #也可以自己写模块发布上去。 (3) PEP:python增强建议书,规范与定义python各种加强和延伸功能的技术规格,即参考标准 (4) PEP规范内容历史:http://www.python.org/dev/peps (5) IDLE中模块信息查看:
1 2 3 4 5 6 >>> import timeit>>> print (timeit.__doc__) >>> dir (timeit) >>> timeit.__all__ >>> timeit.__file__ >>> help (timeit)
timeit 模块详解 地址:http://bbs.fishc.com/thread-55593-1-1.html
22. python实例:网络爬虫 python访问网络: urllib (是个包模块) URL一般格式: protocol://hostname[:port]/path/[;parameters][?query]#fragment URL三部分组成: (1) 协议:http, https, ftp, file, ed2k… (2) 域名/IP地址:如http默认端口号80 (3) 资源具体地址:如目录或文件名
查看帮助文档后发现urllib包有4个模块: urllib.request #for opening and reading URLs urllib.error #containing the exceptions raised by urllib.request urllib.parse #for parsing URLs urllib.robotparser #for parsing robots.txt files 尝鲜:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 >>> import urllib.request>>> response = urllib.request.urlopen('http://www.fishc.com' )>>> html = response.read()>>> print (html)b'xef...rn</html>rn' >>> html = html.decode('utf-8' ) >>> print (html)""" <!DOCTYPE html> <html lang="en"> <head> ... </head> <body> </body> </html> """
访问网页内容存储本地 举例:
1 2 3 4 5 6 7 8 9 import urllib.request as url_req response = url_req.urlopen('http://placekitten.com/g/1920/1080' ) cat_img = response.read()with open ('cat_1920_1080.jpg' , 'wb' ) as f: f.write(cat_img)
运行: 会生成这个文件:C:UsersJanDesktoppython_studycat_1920_1080.jpg
实现POST请求 - 自动翻译机
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 import urllib.request as url_reqimport urllib.parse as url_prsimport json #json, 轻量级的数据交换格式while True: content = input('请输入需要翻译的内容<.q退出>:' ) if content == '.q' : break else : #注意url地址<有道翻译>,按小甲鱼视频中的可能不对,需到网上查别人的 url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com/' data = {} #字典类型 data ['type' ] = 'AUTO' data ['i' ] = content data ['doctype' ] = 'json' data ['xmlVersion' ] = '1.8' data ['keyfrom' ] = 'fanyi.web' data ['ue' ] = 'UTF-8' data ['action' ] = 'FY_BY_CLICKBUTTON' data ['typoResult' ] = 'true' data = url_prs.urlencode(data ).encode('utf-8' ) response = url_req.urlopen(url, data ) html = response.read().decode('utf-8' ) target = json.loads(html) print('翻译结果:%s' % (target['translateResult' ][0 ][0 ]['tgt' ])) #缺陷:能够被识别为代码访问,而非浏览器,即非人类访问
运行:
1 2 3 4 5 6 7 ========= RESTART: C:UsersJanDesktoppython_studytranslation.py ========= 请输入需要翻译的内容<.q退出>:生存,还是毁灭,这是一个问题 翻译结果:To survive, or not to be, this is a problem 请输入需要翻译的内容<.q退出>:To be or not to be, it's a question. 翻译结果:生存还是毁灭,这是一个问题。 请输入需要翻译的内容<.q退出>:.q >>>
修改header (1) 通过Request的headers参数修改,字典形式 (2) 通过Request.add_header()方法修改 追加header模拟浏览器访问:
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 import urllib.request as url_reqimport urllib.parse as url_prsimport json while True : content = input ('请输入需要翻译的内容<.q退出>:' ) if content == '.q' : break else : url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com/' ''' head = {} #模拟浏览器访问 Request Headers head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' ''' data = {} data['type' ] = 'AUTO' data['i' ] = content data['doctype' ] = 'json' data['xmlVersion' ] = '1.8' data['keyfrom' ] = 'fanyi.web' data['ue' ] = 'UTF-8' data['action' ] = 'FY_BY_CLICKBUTTON' data['typoResult' ] = 'true' data = url_prs.urlencode(data).encode('utf-8' ) '''req = url_req.Request(url, data, head) #调用请求的方法:data, head ''' req = url_req.Request(url, data) req.add_header('User-Agent' , 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' ) response = url_req.urlopen(req) html = response.read().decode('utf-8' ) target = json.loads(html) print ('翻译结果:%s' % (target['translateResult' ][0 ][0 ]['tgt' ]))
运行:
1 2 3 4 5 6 7 ========= RESTART: C:UsersJanDesktoppython_studytranslation.py ========= 请输入需要翻译的内容<.q退出>:生存,还是毁灭,这是一个问题 翻译结果:To survive, or not to be, this is a problem 请输入需要翻译的内容<.q退出>:To be or not to be, it's a question. 翻译结果:生存还是毁灭,这是一个问题。 请输入需要翻译的内容<.q退出>:.q >>>
代理 作用:让爬虫伪装浏览器请求,让http服务器不会认为是非人类访问。 步骤:
1 2 3 4 5 6 7 8 9 (1 ) 参数是一个字典{'类型' :'代理ip:端口号' } proxy_support = urllib.request.ProxyHandler({}) (2 ) 定制、创建一个opener opener = urllib.request.build_opener(proxy_support) (3 ) 安装opener urllib.request.install_opener(opener) (4 ) 调用opener opener.open (url)
代码:
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 import urllib.request as url_reqimport random url = 'http://www.whatismyip.com.tw' iplist = ['115.197.136.78:8118' , '118.250.50.69:80' , '183.133.81.57:8118' , '113.77.240.236:9797' , '139.129.166.68:3128' ] proxy_support = url_req.ProxyHandler({'http' :random.choice(iplist)}) opener = url_req.build_opener(proxy_support) opener.addheaders = [('User-Agent' , 'Chrome/55.0.2883.87' )] url_req.install_opener(opener) response = url_req.urlopen(url) html = response.read().decode('utf-8' )print (html)
补充: Beautiful Soup 是用Python写的一个HTML/XML的解析器,使用安装python-IDLE时附带的pip命令,直接在windows下执行:
1 2 3 4 C:python> pip install bs4>>> from bs4 import BeautifulSoup>>>
采集代理ip
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 55 56 57 58 import urllib.request as url_reqfrom bs4 import BeautifulSoup import randomimport pprint as ppr display_ip_url = 'http://www.whatismyip.com.tw' proxy_ip_url = 'http://www.xicidaili.com/wt/' header = {} header['User-Agent' ] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' def getProxyIp (): proxyip_list = [] for i in range (1 , 2 ): try : url = proxy_ip_url + str (i) req = url_req.Request(url, headers=header) res = url_req.urlopen(req).read() soup = BeautifulSoup(res, "html.parser" ) ips = soup.findAll('tr' ) for x in range (1 , len (ips)): ip = ips[x] tds = ip.findAll('td' ) ip_tmp = tds[1 ].contents[0 ] + ':' + tds[2 ].contents[0 ] proxyip_list.append(ip_tmp) except : continue return proxyip_list iplist = getProxyIp() ppr.pprint(iplist) ip_port = random.choice(iplist) proxy_support = url_req.ProxyHandler({'http' :ip_port}) print ('ip:port ' + ip_port) opener = url_req.build_opener(proxy_support) opener.addheaders = [('User-Agent' , 'Chrome/55.0.2883.87' )] url_req.install_opener(opener) response = opener.open (display_ip_url) html = response.read().decode('utf-8' )print (html)
运行: ======== RESTART: C:UsersJanDesktoppython_studyproxy_support.py ========
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!DOCTYPE HTML > <html > <head > ... </head > <body > <h1 > IP位址</h1 > <span data-ip ='183.56.177.130' > <b style ='font-size: 1.5em;' > 183.56.177.130</b > </span > <span data-ip-country ='CN' > <i > CN</i > </span > <h1 > 真實IP</h1 > <span data-ip-real ='113.110.143.94' > <b style ='font-size: 1.5em;' > 113.110.143.94</b > </span > <span data-ip-real-country ='CN' > <i > CN</i > </span > <script type ="application/json" id ="ip-json" > { "ip" : "183.56.177.130" ,"ip-country" : "CN" ,"ip-real" : "113.110.143.94" ,"ip-real-country" : "CN" } </script > ... </body > </html >
2017.09.04
urllib.request 返回响应后的内置方法 import urllib.request as url_req req = url_req.Request(‘http://url' ) res = url_req.urlopen(req) #打开一个链接,参数可以是一个字符串或者Request对象 res.geturl() #返回链接的字符串,即urlopen的字符串参数 res.info() #返回http响应数据包的头headers, 输出:print(res.info()) res.getcode() #返回http响应的状态码
举例: =============== RESTART: C:/Users/Jan/Desktop/download_cat.py ===============
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 >>> res.geturl()'http://placekitten.com/g/500/600' >>> res.info() <http.client.HTTPMessage object at 0x0000022E09C006D8 >>>> res.headers <http.client.HTTPMessage object at 0x0000022E09C006D8 >>>> print (res.info()) Date: Mon, 04 Sep 2017 13 :11 :21 GMT Content-Type : image/jpeg Content-Length: 26590 Connection: closeSet -Cookie: __cfduid=d8354310653b8846db674de048175187b1504530681; expires=Tue, 04-Sep-18 13 :11 :21 GMT; path=/; domain=.placekitten.com; HttpOnly Accept-Ranges: bytes X-Powered-By: PleskLin Access-Control-Allow-Origin: * Cache-Control: public Expires: Thu, 31 Dec 2020 20 :00 :00 GMT Server: cloudflare-nginx CF-RAY: 399131b5435b6d4e-SJC>>> res.getcode()200
python爬虫下载妹子图 代码:
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 import urllib.requestimport osimport randomimport pprint as pprfrom bs4 import BeautifulSoup header = {} header_key = 'User-Agent' header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' header[header_key] = header_valuedef get_proxy_ip (): proxyip_list = [] proxy_ip_url = 'http://www.xicidaili.com/wt/' for i in range (1 , 2 ): try : url = proxy_ip_url + str (i) req = urllib.request.Request(url, headers=header) res = urllib.request.urlopen(req).read() soup = BeautifulSoup(res, "html.parser" ) ips = soup.findAll('tr' ) for x in range (1 , len (ips)): ip = ips[x] tds = ip.findAll('td' ) ip_tmp = tds[1 ].contents[0 ] + ':' + tds[2 ].contents[0 ] proxyip_list.append(ip_tmp) except : continue return proxyip_listdef url_open (url ): req = urllib.request.Request(url) req.add_header(header_key, header_value) ''' #使用代理模拟真人访问而不是代码访问 iplist = get_proxy_ip() #ppr.pprint(iplist) #for test ip_port = random.choice(iplist) proxy_support = urllib.request.ProxyHandler({'http':ip_port}) print('ip:port ' + ip_port) #for test opener = urllib.request.build_opener(proxy_support) opener.addheaders = [('User-Agent', 'Chrome/55.0.2883.87')] urllib.request.install_opener(opener) ''' res = urllib.request.urlopen(url) html = res.read() print (url) return htmldef get_page (url ): html = url_open(url).decode('utf-8' ) a = html.find('current-comment-page' ) + 23 b = html.find(']' , a) print (html[a:b]) return html[a:b]def find_imgs (url ): html = url_open(url).decode('utf-8' ) img_addrs = [] a = html.find('img src=' ) while a != -1 : b = html.find('.jpg' , a, a+255 ) if b != -1 : img_addrs.append('http:' + html[a+9 :b+4 ]) else : b = a + 9 a = html.find('img src=' , b) return img_addrsdef save_imgs (folder, img_addrs ): for each in img_addrs: filename = each.split('/' )[-1 ] with open (filename, 'wb' ) as f: img = url_open(each) f.write(img)def download_mm (folder='mm_dir' , pages=25 ): if os.path.exists(folder): os.chdir(folder) else : os.mkdir(folder) os.chdir(folder) url = 'http://jandan.net/ooxx/' page_num = int (get_page(url)) for i in range (pages): page_num -= i page_url = url + 'page-' + str (page_num) + '#comments' img_addrs = find_imgs(page_url) save_imgs(folder, img_addrs)if __name__ == '__main__' : download_mm()
2017.09.05
正则表达式 “我知道,可以使用正则表达式解决现在遇到的难题。”于是,现在他就有两个问题了。
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 >>> import re>>> re.search(r'Hello' , 'I love you, Hello!~' ) <_sre.SRE_Match object ; span=(12 , 17 ), match='Hello' > >>> re.search(r'lo' , 'hello' ) <_sre.SRE_Match object ; span=(3 , 5 ), match='lo' >>>> 'hello' .find('lo' )3 >>> re.search(r'.' , 'I love you, baidu.com!~' ) <_sre.SRE_Match object ; span=(0 , 1 ), match='I' >>>> re.search(r'.' , 'I love you, baidu.com!~' ) <_sre.SRE_Match object ; span=(17 , 18 ), match='.' >>>> re.search(r'd' , 'I love 123, baidu.com!~' ) <_sre.SRE_Match object ; span=(7 , 8 ), match='1' >>>> re.search(r'ddd' , 'I love 123, baidu.com!~' ) <_sre.SRE_Match object ; span=(7 , 10 ), match='123' >>>> re.search(r'ddd.ddd.ddd.ddd' , '192.168.111.123:8080' ) <_sre.SRE_Match object ; span=(0 , 15 ), match='192.168.111.123' >>>> re.search(r'ddd.ddd.ddd.ddd' , '192.168.1.1' ) >>> re.search(r'[aeiou]' , 'I love you, baidu.com!~' ) <_sre.SRE_Match object ; span=(3 , 4 ), match='o' >>>> re.search(r'[aeiouAEIOU]' , 'I love you, baidu.com!~' ) <_sre.SRE_Match object ; span=(0 , 1 ), match='I' >>>> re.search(r'[a-z]' , 'I love you, baidu.com!~' ) <_sre.SRE_Match object ; span=(2 , 3 ), match='l' >>>> re.search(r'[0-9]' , 'I love 123, baidu.com!~' ) <_sre.SRE_Match object ; span=(7 , 8 ), match='1' >>>> re.search(r'ab{3}c' , 'zabbbcz' ) <_sre.SRE_Match object ; span=(1 , 6 ), match='abbbc' >>>> re.search(r'ab{3, 10}c' , 'zabbbbbcz' )>>> re.search(r'ab{3,10}c' , 'zabbbbbcz' ) <_sre.SRE_Match object ; span=(1 , 8 ), match='abbbbbc' >>>> re.search(r'[0-2][0-5][0-5]' , '188' ) >>> re.search(r'[0-255]' , '188' ) <_sre.SRE_Match object ; span=(0 , 1 ), match='1' >>>> re.search(r'[01]dd|2[0-4]d|25[0-5]' , '188' ) <_sre.SRE_Match object ; span=(0 , 3 ), match='188' >>>> re.search(r'(([01]{0,1}d{0,1}d|2[0-4]d|25[0-5]).){3}([01]{0,1}d{0,1}d|2[0-4]d|25[0-5])' , '192.168.1.1' ) <_sre.SRE_Match object ; span=(0 , 11 ), match='192.168.1.1' >>>> re.search(r'(([01]{0,1}d{0,1}d|2[0-4]d|25[0-5]).){3}([01]{0,1}d{0,1}d|2[0-4]d|25[0-5])' , '255.255.255.0' ) <_sre.SRE_Match object ; span=(0 , 13 ), match='255.255.255.0' >>>> re.search(r'(([01]{0,1}d{0,1}d|2[0-4]d|25[0-5]).){3}([01]{0,1}d{0,1}d|2[0-4]d|25[0-5])' , '11192.168.41.8888' ) <_sre.SRE_Match object ; span=(2 , 15 ), match='192.168.41.88' >import re ptnIP = re.compile (r'(?<![d.])' r'(?:(?:' r'[01]?d?d' r'|2[0-4]d' r'|25[0-5])' r'.){3}' r'(?:' r'[01]?d?d' r'|2[0-4]d' r'|25[0-5])' r'(?![d.])' ) test_IP = ( '0.0.0.0' ';1.22.333.444' ';2.0.0.256' ';3.22.33.23333333' ';4.2.3.4.5' ';5.111.222.99' ';6.0.0.0' ';7.234.234.234' ';255.255.255.255' ';234.234.234.234' ';1192.168.41.888' ) match = ptnIP.findall(test_IP)print (match)
运行: ========== RESTART: C:UsersJanDesktoppython_studyip_regular.py ==========
1 ['0.0.0.0' , '5.111.222.99' , '6.0.0.0' , '7.234.234.234' , '255.255.255.255' , '234.234.234.234' ]
2017.09.07
Python3 正则表达式特殊符号及用法(详细列表)http://blog.csdn.net/riba2534/article/details/54288552
正则表达式举例:
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 import urllib.requestimport re header = {} header_key = 'User-Agent' header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' header[header_key] = header_valuedef open_url (url ): req = urllib.request.Request(url) req.add_header(header_key, header_value) page = urllib.request.urlopen(req) html = page.read().decode('utf-8' ) return htmldef get_img (html ): p = r'<img class="BDE_Image" src="([^"]+.jpg)' imglist = re.findall(p, html) for each in imglist: print (each) for each in imglist: filename = each.split("/" )[-1 ] urllib.request.urlretrieve(each, filename, None )if __name__ == '__main__' : url = 'https://tieba.baidu.com/p/5310571187' get_img(open_url(url))
运行:https://imgsa.baidu.com/forum/w%3D580/sign=0b340d2849a7d933bfa8e47b9d4ad194/f1f8e3dde71190ef7241a5e3c51b9d16fcfa60a4.jpg https://imgsa.baidu.com/forum/w%3D580/sign=6ff2514ff0f2b211e42e8546fa816511/fe4fbf014a90f6030c47ab7b3212b31bb151ed60.jpg https://imgsa.baidu.com/forum/w%3D580/sign=7f8aadd5f9d3572c66e29cd4ba136352/b9dc748b4710b912bda70cc2c8fdfc03934522f1.jpg
优化采集代理ip:
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 import urllib.requestimport re header = {} header_key = 'User-Agent' header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' header[header_key] = header_valuedef open_url (url ): req = urllib.request.Request(url) req.add_header(header_key, header_value) page = urllib.request.urlopen(req) html = page.read().decode('utf-8' ) return htmldef get_ip (html ): ptnIP = (r'(?<![d.])' r'(?:(?:' r'[01]?d?d' r'|2[0-4]d' r'|25[0-5])' r'.){3}' r'(?:' r'[01]?d?d' r'|2[0-4]d' r'|25[0-5])' r'(?![d.])' ) iplist = re.findall(ptnIP, html) for each in iplist: print (each) if __name__ == '__main__' : url = 'http://www.xicidaili.com/wt/' get_ip(open_url(url))
异常处理 URLError 举例:
1 2 3 4 5 6 7 8 >>> import urllib.request>>> import urllib.error>>> req = urllib.request.Request('http://www.ooxx-hello.com' ) >>> try : urllib.request.urlopen(req)except urllib.error.URLError as e:print (e.reason) [Errno 11001 ] getaddrinfo failed
HTTPError 举例:
1 2 3 4 5 6 7 8 >>> import urllib.request>>> import urllib.error>>> req = urllib.request.Request('http://www.fishC.com/ooxx.html' )>>> try : urllib.request.urlopen(req)except urllib.error.HTTPError as e:print (e.code)print (e.read())
1 2 404 b'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" > n<html > <head > n<title > 404 Not Found</title > n</head > <body > n<h1 > Not Found</h1 > n<p > The requested URL /ooxx.html was not found on this server.</p > n<hr > n<address > Apache Server at www.fishc.com Port 80</address > n</body > </html > n'
处理异常的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from urllib.request import Request, urlopenfrom urllib.error import URLError req = Request('http://someurl/' )try : response = urlopen(req)except URLError as e:if hasattr (e, 'reason' ):print ('We failed to reach a server.' )print ('Reason: ' , e.reason)elif hasattr (e, 'code' ):print ('The server couldn' t fulfill the request.') print(' Error code: ', e.code) else: #everything is fine.
2017.09.08
Scrapy爬虫框架 ① Scrapy的安装与环境搭建 Scrapy对应python2.7的版本。(安装过程中如遇任何问题均可百度搜索一下,这是程序员必须学会的快速解决问题的办法)
安装python2.7(32位版本)
1 2 3 4 5 6 安装包:python-2.7 .6 -win32.msi 设置环境变量:win-运行-cmd > C:Python27python.exe C:Python27toolsScriptswin_add2path.py 重启windows系统,验证安装是否成功: > python -- version
安装pywin32(32位版本)
1 安装包:pywin32-215. win32-py2.7 .exe
安装python2.7的pip程序
1 2 3 4 5 6 安装程序:get-pip.py 安装方法:win-cmd> python C:pythonScrapyget-pip.py 先把pip的路径添加到windows的环境变量中。 重启windows系统,验证安装是否成功: > pip -- version
安装lxml
1 2 3 4 安装环境包:VCForPython27.msi > pip2 install lxml 安装包:lxml-3.2 .3 .win32-py2.7 .exe
安装OpenSSL
1 2 3 > pip2 install pyOpenSSL 安装包:egenix-pyopenssl-0.13 .7 .win32-py2.7 .msi
安装Scrapy
1 2 3 4 5 6 > pip2 install service_identity > pip2 install Scrapy 验证是否安装成功: > Scrapy 安装完Twisted后再次尝试验证即可。
② Scrapy框架爬虫程序初探 一个为了爬取网站数据,提取结构性数据而编写的应用框架。最初是为了页面抓取所设计的,也可以应用在获取API所访问的数据上,或者说通用的网络爬虫上。 使用Scrapy抓取一个网站一共需要四个步骤:
创建一个Scrapy项目;
定义Item容器;
编写爬虫;
存储内容。
– -Scrapy框架(官网)图示– -
实验网站对象:www.dmoz.org
创建一个Scrapy项目:crawler
1 2 3 C:UsersJanDesktoppython_study>Scrapy startproject crawler 在python_studycrawler文件夹中即是我们的爬虫框架。
Item是保存爬取到的数据的容器,其使用方法和python字典类似,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。
定义Item容器:
1 2 3 4 5 6 7 8 import scrapyclass CrawlerItem (scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field()
编写爬虫: 编写爬虫类Spider,Spider是用户编写用于从网站上爬取数据的类。其包含了一个用于下载的初始化URL,然后是如何跟进网页中的链接以及如何分析页面中的内容,还有提取生成item的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import scrapyclass CrawlerSpider (scrapy.Spider): name = 'csdn' allowed_domains = ['csdn.net' ] start_urls = ['http://geek.csdn.net/AI' ] def parse (self, response ): filename = response.url.split('/' )[-2 ] with open (filename, 'wb' ) as f: f.write(response.body)
3.1 爬
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 win-cmd: C:UsersJanDesktoppython_study>cd crawler C:UsersJanDesktoppython_studycrawler>scrapy crawl csdn 2017 -09-08 21 :56 :28 [scrapy.utils.log] INFO: Scrapy 1.4 .0 started (bot: crawler) ...2017 -09-08 21 :56 :30 [scrapy.core.engine] INFO: Spider opened2017 -09-08 21 :56 :30 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min ), scraped 0 items (at 0 items/min )2017 -09-08 21 :56 :30 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0 .0 .1 :6023 2017 -09-08 21 :56 :30 [scrapy.core.engine] DEBUG: Crawled (200 ) <GET http://geek.csdn.net/robots.txt> (referer: None ) 2017 -09-08 21 :56 :30 [scrapy.core.engine] DEBUG: Crawled (200 ) <GET http://geek.csdn.net/AI> (referer: None ) 2017 -09-08 21 :56 :31 [scrapy.core.engine] INFO: Closing spider (finished) ...2017 -09-08 21 :56 :31 [scrapy.core.engine] INFO: Spider closed (finished) C:UsersJanDesktoppython_studycrawler 目录下 geek.csdn.net 的NET文件。
3.2 取 在Scrapy中使用的是一种基于XPath和CSS的表达式机制:Scrapy Selectors(选择器) Selector是一个选择器,有4个基本方法: xpath() 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表。 css() 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表。 extract() 序列化该节点为unicode字符串并返回list。 re() 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。
1 2 3 4 5 6 7 8 9 10 11 12 win-cmd进入项目根目录后执行:scrapy shell "http://target_url/" C:UsersJanDesktoppython_studycrawler>scrapy shell "http://geek.csdn.net/AI" 2017 -09-08 22 :05:48 [scrapy.utils.log] INFO: Scrapy 1.4 .0 started (bot: crawler) ...2017 -09-08 22 :05:50 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0 .0 .1 :6023 2017 -09-08 22 :05:50 [scrapy.core.engine] INFO: Spider opened2017 -09-08 22 :05:50 [scrapy.core.engine] DEBUG: Crawled (200 ) <GET http://geek.csdn.net/robots.txt> (referer: None )2017 -09-08 22 :05:50 [scrapy.core.engine] DEBUG: Crawled (200 ) <GET http://geek.csdn.net/AI> (referer: None ) ...>>> response.body >>> response.headers {'Date' : ['Fri, 08 Sep 2017 14:06:31 GMT' ], 'Content-Type' : ['text/html; charset=utf-8' ], 'Server' : ['openresty' ], 'Vary' : ['Accept-Encoding' , 'Accept-Encoding' ]}
XPath是一门在网页中查找特定信息的语言,所以用XPath来筛选数据,要比使用正则表达式容易些。
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 /html/head/title 选择HTML文档中<head>标签内的<title>元素 /html/head/title/text() 选择上面提到的<title>元素的文字 //td 选择所有的<td>元素 //div[@class ="mine" ] 选择所有具有 class ="mine" 属性的div元素 response.xpath() = response.selector.xpath() >>> response.xpath('//title' ) [<Selector xpath='//title' data=u'<title>CSDNu6781u5ba2u5934u6761-u63a8u8350u6bcfu65e5u6700u65b0u6700u70edITu8d44u8baf</title>' >] >>> response.xpath('//title/text()' ).extract() [u'CSDNu6781u5ba2u5934u6761-u63a8u8350u6bcfu65e5u6700u65b0u6700u70edITu8d44u8baf' ]>>> sel.xpath('//span/a' ) 2017 -09-08 22 :36 :08 [py.warnings] WARNING: <string>:1 : ScrapyDeprecationWarning: "sel" shortcut is deprecated. Use "response.xpath()" , "response.css()" or "response.selector" instead>>> sel.xpath('//span/a/text()' ).extract() >>> sel.xpath('//span/a/@href' ).extract() >>> sites = sel.xpath('//div/div/div/dl/dd/span/a/text()' ).extract() >>> for title in sites: ... print (title) 自己动手做聊天机器人 四十二-(重量级长文)从理论到实践开发自己的聊天机器人 微软携手 Facebook 推出开源项目 打造共享神经网络模型 Taylor Swift vs 人工智能:作词谁更强? 推荐13 个机器学习框架 ...>>> sites = sel.xpath('//div/div/div[@class="directory-url"]/dl/dd/span/a/text()' ).extract()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import scrapyclass CrawlerSpider (scrapy.Spider): name = 'csdn' allowed_domains = ['csdn.net' ] start_urls = ['http://geek.csdn.net/AI' ] def parse (self, response ): sel = scrapy.selector.Selector(response) sites = sel.xpath('//div/div/div/dl/dd/span' ) for site in sites: title = site.xpath('a/text()' ).extract() link = site.xpath('a/@href' ).extract() desc = site.xpath('text()' ).extract() print (title, link, desc) win-cmd: C:UsersJanDesktoppython_studycrawler>scrapy crawl csdn
存储内容 最常见的导出为json格式。 中文乱码问题:http://bbs.fishc.com/thread-85672-1-1.html
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 import scrapyfrom crawler.items import CrawlerItemclass CrawlerSpider (scrapy.Spider): name = 'csdn' allowed_domains = ['csdn.net' ] start_urls = ['http://geek.csdn.net/AI' ] def parse (self, response ): sel = scrapy.selector.Selector(response) items = [] sites = sel.xpath('//div/div/div/dl/dd/span' ) for site in sites: item = CrawlerItem() item['title' ] = site.xpath('a/text()' ).extract() item['link' ] = site.xpath('a/@href' ).extract() item['desc' ] = site.xpath('text()' ).extract() print (item['title' ], item['link' ], item['desc' ]) items.append(item) return items
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import jsonimport codecs store_filename = 'items.json' class CrawlerPipeline (object ): def __init__ (self ): self.file = codecs.open (store_filename, 'wb' , encoding='utf-8' ) def process_item (self, item, spider ): line = json.dumps(dict (item), ensure_ascii=False ) + 'n' self.file.write(line) return item
1 2 3 4 ITEM_PIPELINES = { 'crawler.pipelines.CrawlerPipeline' : 300 , }
win-cmd运行scrapy,即可自动在crawler目录下生成items.json文件,并且中文显示正常:
1 2 3 4 5 6 C:UsersJanDesktoppython_studycrawler>scrapy crawl csdn C:UsersJanDesktoppython_studycrawleritems.json {"title" : ["自己动手做聊天机器人 四十二-(重量级长文)从理论到实践开发自己的聊天机器人" ], "link" : ["http://www.shareditor.com/blogshow?blogId=136&hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io" ], "desc" : ["n " , "n " ]} {"title" : ["微软携手 Facebook 推出开源项目 打造共享神经网络模型" ], "link" : ["http://tech.163.com/17/0908/08/CTQ1403R00097U80.html" ], "desc" : ["n " , "n " ]} {"title" : ["Taylor Swift vs 人工智能:作词谁更强?" ], "link" : ["http://dataquestion.com/taylor-vs-ai" ], "desc" : ["n " , "n " ]} ...
2017.09.09
23. GUI界面的终极选择 Tkinter Tkinter是python的默认GUI模块库。 示例1:主窗口及标题
1 2 3 4 5 6 7 8 9 10 11 12 import tkinter as tk app = tk.Tk() app.title('Tkinter root window' ) theLabel = tk.Label(app, text='我的第2个窗口程序!' ) theLabel.pack() app.mainloop()
示例2:按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import tkinter as tkclass APP : def __init__ (self, master ): frame = tk.Frame(master) frame.pack(side=tk.LEFT, padx=10 , pady=10 ) self.hi_there = tk.Button(frame, text='打招呼' , bg='black' , fg='white' , command=self.say_hi) self.hi_there.pack() def say_hi (self ): print ('卧槽,居然打了个招呼!~' ) root = tk.Tk() app = APP(root) root.mainloop()
示例3:图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from tkinter import * root = Tk() textLabel = Label(root, text='请重试!n您的操作不被允许!' , justify=LEFT, padx=10 , pady=10 ) textLabel.pack(side=LEFT) photo = PhotoImage(file='tk_image.png' ) imageLabel = Label(root, image=photo) imageLabel.pack(side=RIGHT) mainloop()
示例4:背景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from tkinter import * root = Tk() photo = PhotoImage(file='tk4_bg.png' ) theLabel = Label(root, text='生存还是毁灭n这是一个问题' , justify=LEFT, image=photo, compound=CENTER, font=('华文隶书' , 20 ), fg='blue' ) theLabel.pack() mainloop()
示例5:按钮交互
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 from tkinter import *def callback (): var.set ('吹吧你,我才不信呢!' ) root = Tk() frame1 = Frame(root) frame2 = Frame(root) var = StringVar() var.set ('请重试!n您的操作不被允许!' ) textLabel = Label(frame1, textvariable=var, justify=LEFT) textLabel.pack(side=LEFT) photo = PhotoImage(file='tk_image.png' ) imageLabel = Label(root, image=photo) imageLabel.pack(side=RIGHT) theButton = Button(frame2, text='我是超级管理员' , command=callback) theButton.pack() frame1.pack(padx=10 , pady=10 ) frame2.pack(padx=10 , pady=10 ) mainloop()
示例6:选项按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from tkinter import * root = Tk() v = IntVar() c = Checkbutton(root, text='测试一下' , variable=v) c.pack() l = Label(root, textvariable=v) l.pack() mainloop()
示例7:多个方框选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from tkinter import * root = Tk() GIRLS = ['西施' , '貂蝉' , '王昭君' , '杨玉环' ] v = []for girl in GIRLS: v.append(IntVar()) b = Checkbutton(root, text=girl, variable=v[-1 ]) b.pack(anchor=W) mainloop()
示例8:多个圆点选项 Radiobutton
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from tkinter import * root = Tk() v = IntVar() Radiobutton(root, text='one' , variable=v, value=1 ).pack(anchor=W) Radiobutton(root, text='two' , variable=v, value=2 ).pack(anchor=W) Radiobutton(root, text='three' , variable=v, value=3 ).pack(anchor=W) Radiobutton(root, text='four' , variable=v, value=4 ).pack(anchor=W) mainloop()
示例9:内陷填充按钮选项 Radiobutton indicatoron
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from tkinter import * root = Tk() LANGS = [ ('C' , 1 ), ('C++' , 2 ), ('shell' , 3 ), ('python' , 4 )] v = IntVar() v.set (1 )for lang, num in LANGS: b = Radiobutton(root, text=lang, variable=v, value=num, indicatoron=False ) b.pack(fill=X) mainloop()
示例10:附带标题的圆点选项 LabelFrame
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 from tkinter import * root = Tk() group = LabelFrame(root, text='最好的开发语言是?' , padx=5 , pady=5 ) group.pack(padx=10 , pady=10 ) LANGS = [ ('C' , 1 ), ('C++' , 2 ), ('shell' , 3 ), ('python' , 4 )] v = IntVar() v.set (1 )for lang, num in LANGS: b = Radiobutton(group, text=lang, variable=v, value=num) b.pack(anchor=W) mainloop()
示例11:输入框 Entry
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from tkinter import * root = Tk() e = Entry(root) e.pack(padx=20 , pady=20 ) e.delete(0 , END) e.insert(0 , '默认文本...' ) mainloop()
示例12:按钮和输入框交互
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 from tkinter import * root = Tk() root.title('输入框与按钮程序' ) Label(root, text='作品:' ).grid(row=0 , column=0 ) Label(root, text='作者:' ).grid(row=1 , column=0 ) e1 = Entry(root) e2 = Entry(root) e1.grid(row=0 , column=1 , padx=10 , pady=5 ) e2.grid(row=1 , column=1 , padx=10 , pady=5 )def show (): print ('作品:《%s》' % e1.get()) print ('作者:《%s》' % e2.get()) Button(root, text='获取信息' , width=10 , command=show) .grid(row=3 , column=0 , sticky=W, padx=10 , pady=5 ) Button(root, text='点击退出' , width=10 , command=root.quit) .grid(row=3 , column=1 , sticky=E, padx=10 , pady=5 ) mainloop()
示例12:登陆框程序
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 from tkinter import * root = Tk() root.title('登陆程序' ) Label(root, text='账号:' ).grid(row=0 , column=0 ) Label(root, text='密码:' ).grid(row=1 , column=0 ) v1 = StringVar() v2 = StringVar() e1 = Entry(root, textvariable=v1) e2 = Entry(root, textvariable=v2, show='*' ) e1.grid(row=0 , column=1 , padx=10 , pady=5 ) e2.grid(row=1 , column=1 , padx=10 , pady=5 )def show (): print ('账号:%s' % e1.get()) print ('密码:%s' % e2.get()) Button(root, text='芝麻开门' , width=10 , command=show) .grid(row=3 , column=0 , sticky=W, padx=10 , pady=5 ) Button(root, text='点击退出' , width=10 , command=root.quit) .grid(row=3 , column=1 , sticky=E, padx=10 , pady=5 ) mainloop()
示例13:输入对错验证程序
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 from tkinter import * root = Tk() root.title('输入对错验证' )def test (): if e1.get() == '张三' : print ('正确!' ) return True else : print ('错误!' ) e1.delete(0 , END) return False v = StringVar() e1 = Entry(root, textvariable=v, validate='focusout' , validatecommand=test) e2 = Entry(root) e1.pack(padx=10 , pady=10 ) e2.pack(padx=10 , pady=10 ) mainloop()
示例13:简单计算器程序
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 from tkinter import * root = Tk() root.title('计算器程序' ) frame = Frame(root) frame.pack(padx=10 , pady=10 ) v1 = StringVar() v2 = StringVar() v3 = StringVar()def test (content ): return content.isdigit() testCMD = frame.register(test) e1 = Entry(frame, width=10 , textvariable=v1, validate='key' , validatecommand=(testCMD, '%P' )).grid(row=0 , column=0 ) Label(frame, text='+' ).grid(row=0 , column=1 ) e2 = Entry(frame, width=10 , textvariable=v2, validate='key' , validatecommand=(testCMD, '%P' )).grid(row=0 , column=2 ) Label(frame, text='=' ).grid(row=0 , column=3 ) e3 = Entry(frame, width=10 , textvariable=v3, state='readonly' ).grid(row=0 , column=4 )def calc (): result = int (v1.get()) + int (v2.get()) v3.set (str (result)) Button(frame, text='计算结果' , command=calc).grid(row=1 , column=2 , pady=5 ) mainloop()
示例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 from tkinter import * master= Tk() theLB = Listbox(master, selectmode=SINGLE, height=15 ) theLB.pack()for item in ['笔' , '墨' , '纸' , '砚' ]: theLB.insert(END, item) for item in range (11 ): theLB.insert(END, item) theButton = Button(master, text='删除' , command=lambda x=theLB:x.delete(ACTIVE) ) theButton.pack() mainloop()
示例15:为列表组件添加滚动条 安装垂直滚动条步骤:
设置该组件的yscrollbarcommand选项为Scrollbar组件的set方法;
设置Scrollbar组件的command选项为该组件的yview()方法。
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 from tkinter import * root = Tk() root.title('滚动条程序' ) sb = Scrollbar(root) sb.pack(side=RIGHT, fill=Y) lb = Listbox(root, yscrollcommand=sb.set )for i in range (1000 ): lb.insert(END, i) lb.pack(side=LEFT, fill=BOTH) sb.config(command=lb.yview) mainloop() 示例16 :滑块滚动条 Scalefrom tkinter import * root = Tk() root.title('滑块程序' ) s1 = Scale(root, from_=0 , to=100 , tickinterval=5 , resolution=5 , length=200 ) s1.pack() s2 = Scale(root, from_=0 , to=100 , tickinterval=5 , orient=HORIZONTAL, length=400 ) s2.pack()def show (): print (s1.get(), s2.get()) Button(root, text='音量:' , command=show).pack() mainloop()
示例17:文本组件 Text (插入按钮)
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 from tkinter import * root = Tk() root.title('Text' ) text = Text(root, width=30 , height=20 ) text.pack() text.insert(INSERT, '这里是显示的文本信息内容。n' ) text.insert(END, '对比一下效果。' )def show (): print ('提交中...' ) b1 = Button(text, text='提交' , command=show) text.window_create(INSERT, window=b1) mainloop()
示例18:文本组件 Text (插入图片)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from tkinter import * root = Tk() root.title('Text' ) text = Text(root, width=100 , height=30 ) text.pack() photo = PhotoImage(file="tk_image.png" )def show_img (): text.image_create(END, image=photo) b1 = Button(text, text='插入图片' , command=show_img) text.window_create(INSERT, window=b1) mainloop()
示例19:文本组件 Text (Indexes:索引定位)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from tkinter import * root = Tk() root.title('Text' ) text = Text(root, width=30 , height=10 ) text.pack() text.insert(INSERT, 'I love baidu.com!' ) text.tag_add('tag1' , '1.7' , '1.12' , '1.14' ) text.tag_add('tag2' , '1.7' , '1.12' , '1.14' ) text.tag_config('tag1' , background='blue' , foreground='yellow' ) text.tag_config('tag2' , foreground='red' ) mainloop()
示例20:文本组件中可点击连接
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 from tkinter import *import webbrowser as wb root = Tk() root.title('GUI link show' ) text = Text(root, width=30 , height=5 ) text.pack() text.insert(INSERT, 'I love baidu.com!' ) text.tag_add('link' , '1.7' , '1.16' ) text.tag_config('link' , foreground='blue' , underline=True )def show_arrow_cursor (event ): text.config(cursor='arrow' )def show_xterm_cursor (event ): text.config(cursor='xterm' )def click (event ): wb.open ('http://www.baidu.com' ) text.tag_bind('link' , '<Enter>' , show_arrow_cursor) text.tag_bind('link' , '<Leave>' , show_xterm_cursor) text.tag_bind('link' , '<Button-1>' , click) mainloop()
示例21:文本组件之MD5
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 from tkinter import *import hashlib root = Tk() root.title('link click' ) text = Text(root, width=50 , height=10 ) text.pack() text.insert(INSERT, 'I love www.baidu.com' ) contents = text.get('1.0' , END)def getSig (contents ): m = hashlib.md5(contents.encode()) return m.digest() sig = getSig(contents)def check (): contents = text.get('1.0' , END) if sig != getSig(contents): print ('内容有修改,是否保存?' ) else : print ('无任何修改!' ) Button(root, text='检查' , command=check).pack() mainloop()
示例22:文本组件之全文搜索
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 from tkinter import * root = Tk() root.title('link click' ) text = Text(root, width=50 , height=10 ) text.pack() text.insert(INSERT, 'I love www.baidu.com' )def getIndex (text, index ): return tuple (map (int , str .split(text.index(index), '.' ))) start = '1.0' while True : pos = text.search('o' , start, stopindex=END) if not pos: break print ('找到啦,位置是:' , getIndex(text, pos)) start = pos + '+1c' mainloop()
示例23:文本组件之撤销操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from tkinter import * root = Tk() root.title('link click' ) text = Text(root, width=50 , height=10 , undo=True ) text.pack() text.insert(INSERT, 'I love www.baidu.com' )def show (): text.edit_undo() Button(root, text='撤销' , command=show).pack() mainloop()
示例24:绘制组件 Canvas
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from tkinter import * root = Tk() root.title('Canvas' ) w = Canvas(root, width=500 , height=300 ) w.pack() w.create_rectangle(50 , 50 , 450 , 250 , fill='yellow' ) w.create_line(0 , 300 //2 , 500 , 300 //2 , fill='red' ) w.create_line(500 //2 , 0 , 500 //2 , 300 , fill='blue' , dash=(4 , 4 )) mainloop()
示例25:绘制组件 Canvas (修改和删除图形)
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 from tkinter import * root = Tk() root.title('Canvas' ) w = Canvas(root, width=500 , height=300 ) w.pack() rect1 = w.create_rectangle(50 , 50 , 450 , 250 , fill='yellow' ) line1 = w.create_line(0 , 300 //2 , 500 , 300 //2 , fill='red' ) line2 = w.create_line(500 //2 , 0 , 500 //2 , 300 , fill='blue' , dash=(4 , 4 )) w.coords(line1, 0 , 25 , 500 , 25 ) w.itemconfig(rect1, fill='red' ) w.delete(line2) Button(root, text='删除全部' , command=(lambda x=ALL:w.delete(x))).pack() mainloop()
示例26:绘制组件 Canvas (图形正中心)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from tkinter import * root = Tk() root.title('Canvas' ) w = Canvas(root, width=600 , height=300 ) w.pack() line1 = w.create_line(0 , 0 , 600 , 300 , fill='green' , width=3 ) line1 = w.create_line(600 , 0 , 0 , 300 , fill='green' , width=3 ) rect1 = w.create_rectangle(60 , 30 , 540 , 270 , fill='green' ) rect2 = w.create_rectangle(120 , 60 , 480 , 240 , fill='yellow' ) w.create_text(300 , 150 , text='Hello, python!' ) mainloop()
示例27:绘制组件 Canvas (椭圆和圆形)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from tkinter import * root = Tk() root.title('Canvas' ) w = Canvas(root, width=600 , height=300 ) w.pack() w.create_rectangle(60 , 30 , 540 , 270 , dash=(4 , 4 )) w.create_oval(60 , 30 , 540 , 270 , fill='pink' ) w.create_text(300 , 150 , text='wow~' ) mainloop()
示例28:绘制组件 Canvas (五角星)
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 from tkinter import *import math as m root = Tk() root.title('Canvas' ) w = Canvas(root, width=600 , height=300 , background='red' ) w.pack() center_x = 300 center_y = 150 r = 150 points = [ center_x - int (r * m.sin(2 * m.pi / 5 )), center_y - int (r * m.cos(2 * m.pi / 5 )), center_x + int (r * m.sin(2 * m.pi / 5 )), center_y - int (r * m.cos(2 * m.pi / 5 )), center_x - int (r * m.sin(m.pi / 5 )), center_y + int (r * m.cos(m.pi / 5 )), center_x, center_y - r, center_x + int (r * m.sin(m.pi / 5 )), center_y + int (r * m.cos(m.pi / 5 )), ] w.create_polygon(points, outline='yellow' , fill='yellow' ) mainloop()
示例29:绘制组件 Canvas (自定义画板)
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 from tkinter import * root = Tk() root.title('Canvas draw tool' ) w = Canvas(root, width=400 , height=200 , background='white' ) w.pack()def paint (event ): x1, y1 = (event.x - 1 ), (event.y - 1 ) x2, y2 = (event.x + 1 ), (event.y + 1 ) w.create_oval(x1, y1, x2, y2, fill='red' ) w.bind('<B1-Motion>' , paint) Label(root, text='按住鼠标左键并移动,开始绘制吧!~~' ).pack(side=BOTTOM) mainloop()
示例30:菜单组件 Menu (主菜单/下拉菜单/右键菜单/单多选菜单/按钮菜单/选项菜单(列表))
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 from tkinter import * root = Tk() root.title('Main Menu Show' )def callback (): print ('你好~' ) menubar = Menu(root) filemenu = Menu(menubar, tearoff=False ) filemenu.add_command(label='新建' , command=callback) filemenu.add_command(label='打开...' , command=callback) filemenu.add_separator() filemenu.add_command(label='保存' , command=callback) filemenu.add_separator() filemenu.add_command(label='退出' , command=root.quit) menubar.add_cascade(label='文件(W)' , menu=filemenu) editmenu = Menu(menubar, tearoff=False ) editmenu.add_command(label='撤销' , command=callback) editmenu.add_command(label='重做' , command=callback) editmenu.add_separator() editmenu.add_command(label='剪切' , command=callback) editmenu.add_command(label='复制' , command=callback) editmenu.add_command(label='粘贴' , command=callback) editmenu.add_separator() editmenu.add_command(label='全选' , command=callback) editmenu.add_separator() editmenu.add_command(label='查找...' , command=callback) menubar.add_cascade(label='编辑(B)' , menu=editmenu) openVar = IntVar() saveVar = IntVar() quitVar = IntVar() optionmenu = Menu(menubar, tearoff=False ) optionmenu.add_checkbutton(label='多选项1' , command=callback, variable=openVar) optionmenu.add_checkbutton(label='多选项2' , command=callback, variable=saveVar) optionmenu.add_checkbutton(label='多选项3' , command=callback, variable=quitVar) menubar.add_cascade(label='选项(C)' , menu=optionmenu) otherVar = IntVar() othermenu = Menu(menubar, tearoff=False ) othermenu.add_radiobutton(label='单选项1' , command=callback, variable=otherVar, value=1 ) othermenu.add_radiobutton(label='单选项2' , command=callback, variable=otherVar, value=2 ) othermenu.add_radiobutton(label='单选项3' , command=callback, variable=otherVar, value=3 ) menubar.add_cascade(label='其他(C)' , menu=othermenu) mb = Menubutton(root, text='按钮菜单...' , relief=RAISED) mb.pack() openVar = IntVar() saveVar = IntVar() quitVar = IntVar() optionmenu = Menu(mb, tearoff=False ) optionmenu.add_checkbutton(label='test' , command=callback, variable=openVar) optionmenu.add_checkbutton(label='test' , command=callback, variable=saveVar) optionmenu.add_checkbutton(label='test' , command=callback, variable=quitVar) mb.config(menu=optionmenu) variable = StringVar() variable.set ('one' ) w = OptionMenu(root, variable, 'one' , 'two' , 'three' ) w.pack() OPTIONS = [ '表项1' , '对比2' , '选项3' , '其他4' , '退出5' ] var = StringVar() var.set (OPTIONS[0 ]) o = OptionMenu(root, var, *OPTIONS) o.pack() helpmenu = Menu(menubar, tearoff=False ) helpmenu.add_separator() helpmenu.add_command(label='关于...' , command=callback) helpmenu.add_separator() menubar.add_cascade(label='帮助(F1)' , menu=helpmenu) frame = Frame(root, width=512 , height=512 ) frame.pack()def popup (event ): editmenu.post(event.x_root, event.y_root) frame.bind('<Button-3>' , popup) root.config(menu=menubar) mainloop()
示例31:事件绑定 bind (鼠标/按键/按键组合)
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 from tkinter import * root = Tk() root.title('Event bind' ) frame = Frame(root, width=200 , height=200 )def callback1 (event ): print ('点击位置:' , event.x, event.y) frame.bind('<Button-1>' , callback1) frame.pack()def callback2 (event ): print (event.keysym) frame.bind('<Key>' , callback2) frame.focus_set() frame.pack()def callback3 (event ): print ('点击位置:' , event.x, event.y) frame.bind('<Motion>' , callback3) frame.pack() mainloop()
示例32:消息组件 Message | 输入组件 Spinbox
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from tkinter import * root = Tk() root.title('Module' ) m1 = Message(root, text='这是一个消息:' , width=100 ) m1.pack() m2 = Message(root, text='这是一n则骇人听闻的长长长长长长长消息!' , width=100 ) m2.pack() s1 = Spinbox(root, from_=0 , to=5 ) s1.pack() s2 = Spinbox(root, values=('zero' , 'one' , 'two' , 'three' , 'four' , 'five' )) s2.pack() mainloop()
示例33:窗口布局管理器 PanedWindow
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 from tkinter import * root = Tk() root.title('Module' )''' p = PanedWindow(orient=VERTICAL) p.pack(fill=BOTH, expand=1) top = Label(p, text='top pane') p.add(top) bottom = Label(p, text='bottom pane') p.add(bottom) ''' p = PanedWindow(showhandle=True , sashrelief=SUNKEN) p.pack(fill=BOTH, expand=1 ) left = Label(p, text='left pane' ) p.add(left) q = PanedWindow(orient=VERTICAL, showhandle=True , sashrelief=SUNKEN) p.add(q) top = Label(q, text='top pane' ) q.add(top) bottom = Label(q, text='bottom pane' ) q.add(bottom) mainloop()
示例34:容器组件 Toplevel (创建顶级窗口,即弹出窗口)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from tkinter import * root = Tk() root.title('Toplevel' )def create (): top = Toplevel() top.title('Toplevel demo...' ) msg = Message(top, text='I love python...' ) msg.pack() Button(root, text='创建顶级窗口' , command=create).pack() mainloop()
示例35:几何管理类,包pack(),网格grid(),位置place()
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 from tkinter import * root = Tk() root.title('pack' ) listbox = Listbox(root) listbox.pack(fill=BOTH, expand=True ) for i in range (10 ): listbox.insert(END, str (i)) Label(root, text='red' , bg='red' , fg='white' ).pack(fill=X) Label(root, text='green' , bg='green' , fg='black' ).pack(fill=X) Label(root, text='blue' , bg='blue' , fg='white' ).pack(fill=X) Label(root, text='red' , bg='red' , fg='white' ).pack(side=LEFT) Label(root, text='green' , bg='green' , fg='black' ).pack(side=LEFT) Label(root, text='blue' , bg='blue' , fg='white' ).pack(side=LEFT) mainloop()
grid() 注意pack和grid不要混合使用
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 from tkinter import * root = Tk() root.title('grid' ) Label(root, text='用户名' ).grid(row=0 , sticky=W) Label(root, text='密码' ).grid(row=1 , sticky=W) photo = PhotoImage(file='tk_image.png' ) Label(root, image=photo).grid(row=0 , column=2 , rowspan=2 , padx=5 , pady=5 ) Entry(root).grid(row=0 , column=1 ) Entry(root, show='*' ).grid(row=1 , column=1 )def callback (): print ('登陆中...' ) Button(text='提交' , width=10 , command=callback).grid(row=2 , columnspan=3 , pady=5 ) mainloop()
place() 可以实现一些pack和grid实现不了的布局
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 from tkinter import * root = Tk() root.title('place' )''' photo = PhotoImage(file='tk_image.png') Label(root, image=photo).pack() #按钮就会出现在图片的组件上,实现组件叠加显示 def callback(): print('正中靶心!!!') #relx,rely相对父组件root的位置,0.5正中间,1最右边,0最左边,anchor=CENTER居中显示 Button(root, text='射击', command=callback).place(relx=0.5, rely=0.5, anchor=CENTER) ''' Label(root, bg='red' ).place(relx=0.5 , rely=0.5 , relheight=0.75 , relwidth=0.75 , anchor=CENTER) Label(root, bg='yellow' ).place(relx=0.5 , rely=0.5 , relheight=0.5 , relwidth=0.5 , anchor=CENTER) Label(root, bg='blue' ).place(relx=0.5 , rely=0.5 , relheight=0.25 , relwidth=0.25 , anchor=CENTER) mainloop()
示例35:对话框 (警告 showinfo | 消息 messagebox | 文件 filedialog | 颜色 colorchooser)
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 from tkinter import *from tkinter import messagebox from tkinter import filedialog from tkinter import colorchooser from tkinter.messagebox import * showinfo(title='test' , message='警告' ) result = messagebox.askokcancel('demo' , '发射核弹?' ) print (result) root = Tk()def callback1 (): filename = filedialog.askopenfilename(defaultextension='.py' ) print (filename) Button(root, text='打开文件' , command=callback1).pack()def callback2 (): color_data = colorchooser.askcolor() print (color_data) Button(root, text='选择颜色' , command=callback2).pack() mainloop()