300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 【python教程】-- 入门 | 小甲鱼《零基础入门学Python》教程笔记(知识点详细 源

【python教程】-- 入门 | 小甲鱼《零基础入门学Python》教程笔记(知识点详细 源

时间:2019-11-12 09:48:25

相关推荐

【python教程】-- 入门 | 小甲鱼《零基础入门学Python》教程笔记(知识点详细 源

(考研成功的第一个暑假,-6-1开始学习python,之前了解的很少,只知道其与网络爬虫、视频图像识别、树莓派系统有关)

说明:

首先,这是个小甲鱼python入门教程的笔记。笔记前面部分是根据版教程(【Python教程】《零基础入门学习Python》最新版)记的,章节标题中带有“(NEW:P1~P34 )”字样;后面部分是根据版教程(【Python教程】《零基础入门学习Python》)记的,为什么是版?看看鱼C论坛就知道了(/thread-36000-1-1.html),其章节标题中带有“(OLD:P18~P97 )”字样。新版本与老版本有多大差别?不大,至少新版本的P1~P34我都看过,与老版本相比,更新了一些内容,去掉/新增了一些知识点,但知识点改变的部分几乎可以忽略,因为重要知识点一点儿也没变!

另外,本人已有部分C语言基础,过于基本的东西没有记录,但讲到的95%的知识点都有,而且有大量例程源码,因此具有较大参考价值(不大?难道打代码不费时间吗!);虽然教程中推荐IDLE进行编程,但我后来使用的是pycharm,因为这样效率高,能节省很多时间,但这就导致前面的示例代码一般是解释性的,而后面的示例代码是直接可以运行的。

注意,从“🔰类和对象(OLD:P37~P41)”开始,笔记中的例程源码是基于pycharm的,相对小甲鱼老师的在IDE中运行的稍作了修改,包括:

增加主程序入口ifname== ‘main’:,以快速在pycharm中运行程序将t1 修改为 print('t1 = ', t1) IDLE运行的教程原程序已在下方注释内容中存放

知识点内容增加了其他参考,做了完善。

适用人群:学习小甲鱼python基础课程的同学

笔记整理发布不易,如果对你有帮助,请多多点赞支持啊!

python语言介绍、和学习准备(NEW:P1~P3)

P1 序章

python的应用

人工智能、数据分析、科学计算、网络爬虫、自动化开发、自动化部署

python优点

强大、快速、兼容性强、入门轻松、开源

python的后台——pypl

第三方模块

课程参考书籍

零基础入门学习Python(第2版)

P2 环境搭建和课程介绍

python相关官网

python官网鱼C工作室官网

编辑器

IDLE 推荐使用,新手从基础学起交互模式 + 编辑器模式

Hello Word

print(“Hello Word”)

P3 (IDLE的使用)用python设计第一个游戏

IDLE的两种模式:交互模式、编辑器模式

示例

""" 用python设计第一个游戏 """temp = input("猜一个数字:")guess = int(temp)if guess == 8:print("^_^")print("@_@")else:print("*_*")print("结束,不玩了")

设置IDLE字体

设置 -> Options -> Configure IDLE -> (推荐使用)Consolas

新手注意点:

英文标点正确的缩进 Python3代码样式指导手册(PEP8) 函数的拼写(BIF内置函数,通过dir(builtins))

🔰变量、字串符、运算符(NEW:P4-P6)

P4 变量和字串符(上)

注意

变量名不能以数字开头中文字符可以作为变量名

字符串

单引号双引号

P5 变量和字串符(下)

转义字符 +符号 (可用于显示引号中的引号) 反斜杠不能放在字符串末尾,使用 r 可以定义为原始字符 如print(r"D:\three\two\one")

三单引号、三双引号 -> 此用法无需每行结尾输入\n\ 后才换行

字符串的加减

相加 -> 拼接相乘 -> 复制

P6 (比较运算符)是时候讲代码了

转换

guess = int(temp)

比较运算符

💻实践-随机数模块(NEW:P7-P8)

P7-P8改进我们的小游戏

判断

if x<y:print("")else:print("")

循环

while x<y:print("")

ctrl + c 强制停止运行

跳出

break跳出一层循环

随机数模块

BIF速查宝典

import randomanswer = random.ranint(1 , 10)

操作随机数 random使用当前操作系统的时间作为种子获取种子:random.getstate()使用方法: x = random.getstate()… #调用随机数random.getstate(x)

导入模块

import

BIF

BIF 就是 Built-in Functions,内置函数。Python 提供了非常丰富的内置函数,不用导入直接调用即可,如print() 、input()dir(__builtins__)查看所有BIFhelp(input)BIF的功能描述。

示例源码

import random # 导入随机数模块counts = 3answer = random.randint(1, 10) # 随机生成1~10的数while counts > 0:temp = input("请输入:")guess = int(temp)if guess == answer:print("^_^")print("@_@")else:if guess > answer:print("大了~~")else:print("小了!!")counts = counts - 1print("游戏结束,不玩啦~~")

🔰数据类型(NEW:P9-P12)

P9-P10 数字类型

整数

有无限大的长度(无限大的精度)

浮点数

存储有误差精确存储浮点数 ↓

import decimala = decimal.Decimal('0.2')

复数

x = 1 + 2j //形式x.real //获取实部x.imag//获取虚部

运算

P11 布尔类型

False是假

空字符串""是假

值等于零是假

false =0 ;true=1

逻辑运算符:

P12 短路逻辑和运算符优先级

短路逻辑

从左往右,只有当第一个操作数的值无法确定逻辑运算结果时,才对第二个操作数进行求值。(谁影响结果,就把谁扔出来 )

运算符优先级

🔰流程图思维

P13-P14 谋定而后动,知止而有得

(-6-7)

流程图+思维导图

思维导图怎么画

方法: 顶层设计,逐层往下分析。按功能分析按元素分析 比如一个小游戏包含哪些元素,这些元素要干什么,怎么样才能实现指定的功能

其他

Scratch Desktop(图像化编程软件)《零基础入门学习Scratch》(少儿编程)零基础入门学习web开发

🔰if 和while(NEW:P15~P19)

P15~P19 了不起的分支和循环

分支

'''条件语句1'''if con:print()'''条件语句12'''if a>b:print()elif b>c:print()else:print()print()/* 另一种条件表达式 */print(“条件成立”) if ?>? else print("条件不成立")small = a if a<b else bprintf(small)/* 条件表达式用法 */score = 66level = ("D" if 0 < score < 60 else'C' if 60 <= score <80 else'B' if 80 <= score < 90 else'A' if 90 <= score < 100 else'S' if score == 100 else"请输入 0~100 之间的数值^o^")printf(level)//利用括号,是程序可以写在多行,比反斜杠更好用/* 条件嵌套 */if ?<?:print("")else:if isMale:print("")else:print("")

循环

while cndition:statement(s)break 用于退出死循环 ,永久退出continue 用于结束单次循环,回到开头/*while else用法*/while ?<?print("")if ?<?breakaaaelse:print("程序正常循环结束,未break") //不使用标志位去检测循环的退出情况for循环for 变量 in 可迭代对象:ststement(s) range()//可生成数字序列range(stop) range(start,stop)range(start,stop,step)

素数检测for n in range(2, 15):for x in range(2,n):if n%x == 0:print(n, "=", x, "*", n//x)breakelse:print(n, "是一个素数")

🔰列表、元组、字符串、序列(NEW:P20-P26)

.06.24

P20-P26 列表

列表创建

[1, 2, 3, "一", "二", "三"]//不限制类型rhyme = [1, 2, 3, "一", "二", "三"]print(rhyme)

列表引用与遍历

print(rhyme)for each in rhyme:print(each)

列表索引

//方式一rhyme[0]rhyme[1]rhyme[2]...rhyme[5]//方式二rhyme[-6]rhyme[-5]rhyme[-4]...rhyme[-1]//方式三length = len(rhyme)rhyme[length - 1]

列表切片(一次性获取多个元素)

rhyme[0:3] 或 rhyme[:3]rhyme[3:6] 或 rhyme[3:] //注意,要写到最后一个元素+1 :[3:6]rhyme[:] //取出全部元素rhyme[::2] //取出全部步进元素rhyme[::-2] //取出全部倒序步进元素

[增]添加列表元素

rhyme1 = [1, 2, 3, 4, 5, 6]//添加一个rhyme1.append(7)//添加多个 rhyme1.extend([8, 9, 10]) //extend()方法的参数必须是一个可迭代对象,新内容追加在原列表最后面//从中间插入添加rhyme1.insert(位置 , 元素)//如:rhyme1.insert(1 , "一")

用法扩展

切片+添加列表元素s = [1, 2, 3, 4, 5]s[len(s):] = [6] //相当于s.append()s[len(s):] = [7, 8, 9] // 相当于s.extend()

[删]删除列表元素

rhyme2 = [1, 2, 3, 4, 5, 6]//删除指定元素rhyme2.remove(6)//如果列表中有多个匹配元素,那么只删除第一个;如果指定元素不存在,则会报错//删除指定位置的元素rhyme2.pop(5)//清空rhyme2.clear()

[改]替换列表元素

rhyme3 = [1, 2, 3, 4, 5, 6]//替换指定位置元素rhyme3[2] = "三" //替换连续几个位置元素rhyme3[2:3] = ["三", "四"]

[改]列表排序

rhyme4 = [1, 2, 3, 4, 5, 6]//从小到大rhyme4.sort()//从大到小rhyme4.sort() rhyme4.reverse()或者 rhyme4.sort(reverse=True)

[查]列表查找

rhyme5 = [1, 2, 3, 6, 6, 6,6]//查找某个元素出现的次数rhyme5.count(6)//查找某个元素的索引值rhyme5.index(6)rhyme5.index(6,4,6) //最后两个元素是开始、结束位置

列表拷贝

.copy()

= rhyme5[ : ]

列表运算

s = [1, 2, 3]

t = [4, 5, 6]

加:s + t

乘:s *3

多维列表(嵌套列表)

应用:matrix = [[ ],[ ],[ ]]访问:

for i in matrix:for each in i:print(each,end=' ')print()

索引访问 matrix[][] 创建并初始化

A =[0]*3for i in range(3):A[i] = [0]*5

浅拷贝与深拷贝

浅拷贝 = .copy 只拷贝外层对象,内层还是引用(引用:y = x)=copy.copy(变量) 深拷贝 =copy.deepcopy(变量)

列表推导式

[expressfor target in iterable][expressfor target in iterableif condition]

P27 元组

什么是元组(tuple)? 和列表形似,可使用切片,但: 用的是圆括号,且圆括号可省略,且最好不要省略内容不可修改只支持查:count 、 index支持嵌套支持迭代支持 + 和 *支持列表推导式 打包、解包 打包:t = (123, ‘aaasss’, 3.14)解包:x, y, z = t

P28~P33 字符串

处理方法1

.capitalize - 将字符串首字母编程大写.casefold - 将所有字符变成小写.title - 每个单词首字母大写.swapcase - 大小写反转upper - 所有变大写.lower - 所有变小写

处理方法2 - 左中右对齐

center(width,fillchar=’’) 左右填充后居中ljust(width,fillchar=’’) 填充后左对齐rjust(width,fillchar=’’) 填充后右对齐zfil(width) 用0填充

处理方法3 - 查找

count(sub[,start[,end]]) 在指定位置查找sub指定的子字符串出现次数find(sub[,start[,end]]) 在指定位置从左往右查下标索引rfind(sub[,start[,end]]) 在指定位置从右往左查下表索引index(sub[,start[,end]])** **在指定位置…同find,但若查不到会抛出异常rindex(sub[,start[,end]])** **在指定位置…同rfind,但若查不到会抛出异常

处理方法4 - 替换

expandtabs([tabsize=9]) 如: = code.expendtabs(4) replace(old,new,count=-1) 将old字符串替换为new字符串 translate(tabe) 按照table中的方法转换如:‘I I ivcc’.translate(str.maketrans(“HIJK”, “1234”))

处理方法5 - 判断

startswith(prefix[, start[, end]]) 判断指定参数的子字符串是否出现在字符串开始位置

endswith(suffix[, start, end]]) 判断指定参数的子字符串是否出现在字符串结束位置

isupper() 判断字符串中所有字母为大写

islower() 判断字符串中所有字母为小写

istitle() 判断字符串中所有单词开头字母为大写,其余为小写

isalpha() 判断字符串中有没有非字母,没有非字母-返回true

isascii()

isspace() 判断是空格字符串,包括tab \n

isprintable() 判断字符是否全部可打印,比如 \n 不可打印,返回false

isdecimal() 判断是数字 123-true

isdigit() 判断是数字 123-true 22-true

isnumeric() 判断是数字 123-true 22-true Ⅰ Ⅱ Ⅲ-true 一二三-true

isalnum() isalpha()、isdecimal()、isdigit()、isnumeric()任何一个是true,他就是true

isidentifier() 判断是合法标识符

判断一个字符串是否是python保留标识符:

import keyword

keyword.iskeyword(" ")

处理方法6 - 截取 如:比如" 左侧不要留白".lstrip()

.strip(char-None) 去除左右空白,传入字符串可以以单个字符作为匹配,去去除.lstrip(char-None) 去除左侧空白.rstrip(char-None) 去除右侧空白.removeprefix(prefix) 去除前缀.removesuffix(suffix) 去除后缀

处理方法7 - 拆分&拼接

.partition(sep) 以从左到右指定的字符串为分割位置分割,返回三元组.rpartition(sep) 以从右到左指定的字符串为分割位置分割,返回三元组.split(sep=None,maxsplit=-1) 以指定字符串为分隔符分割,maxsplit为分割次数.rsplit(sep=None,maxsplit=-1).splitlines(keepends=False) 按行(换行符)分割,以列表形式返回 ;keepends=False不包含换行符.join(iterable)"连接符".join((元组或列表))使用连接符拼接列表或元组中的元素

格式化字符串

location = "北京";year = "{0} 奥运会举办于 {1} 年,是{1}年".format(location, year)位置索引 :"{0} 奥运会举办于 {1} 年,是{1}年".format(location, year)关键字索引"{location} 奥运会举办于 {year} 年,是{year}年".format(location = "北京", ``year = )位置索引+关键字索引"{location} 奥运会举办于 {year} 年,是{0}年".format(year, location = "北京", ``year = )语法: 参数[align ] < : 强制左对齐"{:<}".format(520)

: 强制右对齐

= : 强制将填充放在符号之后数字之前^ : 强制居中 参数[width] 指定字符宽度"{:<10}".format(520)索引参数 位置索引"{2:<10}{1:<10}{0:>10}".format(520, 111, 222)参数[0] 使用“0”作为填充 参数[fill] 填充元素"{:0<10}".format(520)参数[sign] + : 根据正负数动态添加 + - :"{:+}{:-}".format(520, -250)- : 只在负数前添加 - :空格 : 正数前添加空格,负数前添加 - : 参数[groouping_option] 千分位分隔符 ,:"{:,}".format(1234)_ :"{:_}".format(1234)参数[.precision] 精度"{:.2f}".format(3.1415)"{:.2g}".format(3.1415)"{:.3}".format("i love ivcc")参数[type] 如:"{:b}".format(80)参数[#] 如果以二、八、十六进制输出,自动加前缀0b 0o 0x 高级玩法 将参数以关键字表示和引用"{:{fill}{align}{width}.{prec}{type}}".format(3.1415, fill="+", align="^", width=10, prec=3, type="g")

f-字符串

f-string,在字符串前加f,可让程序更简介方便"{0} 奥运会举办于 {1} 年,是{1}年".format(location, year)** ->**f"{location} 奥运会举办于 {year} 年,是{year}年"格式化字符串,可以将format()中的数值放在冒号前面。 如"{:.2f}".format(3.1415)->f"{3.1415:.2f}"

P34 序列

列表、元组、字符串都是序列,列表是可变序列,元组和字符串是不可变序列

加法乘法 + 拼接* 重复 可变对象的+*后的id值不变,不变对象+*运算后的id值改变检测id值——同一性运算符 is :如x is yis not 判断元素是否包含在某个序列 in :如"i" in "ivcc"not in del 用于删除一个或多个指定语句、对象 如:x = “ivcc”; del x, y 用于删除可变序列中的指定元素 如:x = [1, 2, 3, 4, 5] del x[1:4] ->相当于切片中的 x[1:4] = [] 列表、元组、字符串相互转换 list() 转换为列表tuple() 转换为元组str() 转换为字符串 函数 对比传入参数返回最值 min() 返回列表中最小元素、字符串中字母编码值max()min(s, defaule="空的序列"),若序列可能为空,用这种方法 ** len() 计算长度sum() 计算求和 start参数 指定求和起始值,从起始值开始加sum(s, start=100)** sorted() 从小到大排序,返回全新列表 (注意:.sort()方法会改变原列表)sorted(t,reverse=true)sorted(t, key=len)key可以干预配许算法 len 比较每个元素长度 reversed() 翻转

-7-22, 最新教程已经更新至34,但停更很久了,也不想等更新,太慢

就先看老教程吧

老教程包含了变量和字符串、数据类型、分支循环、列表、元组、字符串、序列,到此接着学

🔰函数、递归(OLD:P18-P25)

P18~P25 函数

参数

多个参数逗号隔开:def 函数(参数1,参数2):print(参数1, 参数2)return(true)形参实参 形参:定义函数时设置的参数实参:调用函数时传入的参数 关键字参数 在实参前面加上关键字索引,如:函数(参数2 = "我是参数2", 参数1 = "我是参数1")功能:防止参数顺序混乱⭐ 默认参数 在形参后面加上参数,如:def 函数(参数1 = "默认值1",参数2 = "默认值2"):虽然有默认值,但仍然可以在函数调用时给它(形参)重新赋值功能:防止参数漏掉赋值导致错误⭐ 收集参数 把参数前面加上*,如def 函数(*参数参数,参数1):print(len(参数参数)) # 可以识别形参的个数print(参数[索引]) # 以元组形式调用形参中的参数调用↓函数(1, 2, 3, "ivcc", 参数1 = "love")功能:拓展功能

函数文档

语法:在函数内部用单引号引注的部分查看:有两种方法函数.__doc__,不方便查看,因为换行符直接打印出来了help(函数),更方便查看,对换行符进行了转意

返回值

python函数的返回值可以是多个 或 多种类型,如:def back():return [1, "二", 3.14]使用方法类似将一组返回值打包成列表 或 元组

局部变量全局变量

局部变量local variable ;全局变量global variable全局变量使用要小心 如果在函数内部修改全局变量的值,python将会在函数内部建立一个与全局变量一样的局部变量,修改值不影响全局变量如果要在函数内部修改全局变量,可使用global关键字,如:数字1 = 5def 函数():global 数字1数字1 = 10

内嵌函数

内嵌函数只能在它的父级函数内被调用

闭包

closure如果一个内部函数对父级函数内的变量进行引用,内部函数就被认为是闭包内部函数要改变父级函数中的变量值的话,可以使用列表形式,如x[0]作为变量,因为列表是直接存放在堆里面,不存放在栈里面;也可以使用nonlocal关键字,如:nonlocal x用法和global相似

lambda表达式

语法:lambda x : 2 * x + 1lambda x, y : 2 * x + y调用g = lambda x : 2 * x + 1特点: 将函数形式转化为表达式, 省下了定义函数的过程,使代码更加简洁不需要考虑命名的问题增加了可读性,不用跑去看函数使怎么定义的不占用内存资源 注:如果使用函数,则可能(猜想)会一直占用内存资源

BIF

filter过滤器 语法:filter[function or none, iterable]将iterable(可迭代对象,如列表),中的元素带入function中计算,并返回值为真的元素。如果function为none,则返回iterable中的值为真的元素 筛选出值为真的元素如:list(filter(lambda x : x % 2, range(10)))map 语法: 将序列每个元素作为函数的参数进行加工,直到序列的每个元素都加工完毕,返回新序列 如:list(map(lambda x : x % 2, range(10)))

递归

啥是递归 相当于函数调用自身对栈操作频繁,很消耗时间、空间注意: 很危险:如果忘记返回,将会报错 怎么调用自身,且有正确返回?

def factorial(n)if n == 1:return 1else:return n * factorial(n - 1)以上是一个计算阶乘的例子

P24~25 递归

分治思想

能将递归算法直接的用代码表示出来

如:斐波那契数列

def fab(n):if n < 1:print("输入有误!")return -1if n ==1 or n == 2:return 1else:return fab(n--1) + fab(n-2)result = fab(12)if result != -1:print(result)

如:汉诺塔解法

def hanoi(n, x, y, z)if n == 1:print(x, '-->', z)else:hanoi(n-1, x, z, y)# 将n-1个盘子从x移动到y上print(x, '-->', z)# 将最底下的最后一个盘子从x移动到z上hanoi(n-1, y, x, z)# 将y上的n-1个盘子移动到z上n = int(input("请输入汉诺塔层数:"))hanoi(n, 'X', 'Y', 'Z')

<br />

🔰字典、集合(OLD:P26-P28)

P26~27 字典:当索引不好用时

说明字典相当于一个一对一映射类型包含两种元素:键(key)、值(value)

创建

dict = {'键1':'值1', '键2':'值2', '键3':'值3'}键可以是一个整型、字符型、字符串、变量一对键、值称为“项”调用:dict['键3']创建空的字典:dict = {}

修改

dict['键3'] = ['值6']dict['键4'] = ['值4']– 若键为新的,则在原字典中添加新的项

字典工厂函数

dict(map) map参数:映射类型

内建函数

formkeys() 使用方法:dict.fomkeys(s[,v])创建并返回一个新的字典,如:dict.fokeys((1,2), '新值')

访问

keys() 返回字典的键用法:for eachkey in dict1.keys()print(eachkey)values() 用法同keys items() 用法同keys用元组的形式输出 get方法 用法:dict1.get(键3)dict1.get(键3, 没有值)功能 能避免直接输出时,遇到空值造成的程序错误

修改

clear方法 清空所有字典的键、值包括清空类似dict2 = dict1这样的对其引用的dict2的键、值 pop方法dict.pop(键)弹出(移除+返回)一个键及其对应的值 popitem方法dict.popitem随机弹出一个项 setdefault方法 弹入一个项dict.setdefault(键5, 值5)update方法 更新键对应的元素dict.update(键5, 值7)

拷贝

浅拷贝: copy() 用法:dict2 = dict1.copy()特点:拷贝出一个新的字典 dict2 = dict1 拷贝 两个字典指向同一个id(两个字典是相同的东西)

P28 集合:在我的世界里你就是唯一

集合的特点

集合是无需的集合是不重复的,能把重复的数据清理掉集合不支持索引

集合创建

①用一对花括号表示{ , , }②使用set工厂函数set1 = set([ , , ,])

集合的访问

使用for循环,一个个读取使用 in 或 not in 判断一个元素是否在集合中

集合的修改

添加元素:num1.add(要添加的元素)移除元素:num1.remove(要移除的元素)

不可变集合

不可添加、删除元素

创建mun2 = frozenset([ , , , ])

使用示例

去除列表中的重复部分num1 = list(set(num1))注意:此方法得到的集合是无序的

🔰文件(OLD:P29-32)

P29-30 文件操作

文件打开

语法:file object = open(file_name [, access_mode][, buffering])file_name:要访问的文件路径及名称的字符串值。access_mode:决定了打开文件的模式:只读,写入,追加等。默认文件访问模式为只读®。buffering: 值取0,不会有寄存。值取1,访问文件时会寄存行。值取大于1的整数,表明了这就是的寄存区的缓冲大小。值取负值,寄存区的缓冲大小则为系统默认。f = open('E:\\test1.txt', 'w')

表:python文件打开模式,参考自/python/python-files-io.html

直接print(f),会输出一个文件对象:<_io.TextIOWrapper name='D:\\test1.txt' mode='r' encoding='cp936'>

文件对象方法

list(f)能将文件直接转化为列表

读取文件对象

for each_line in f:

print(each_line)

注意:

文件写入后,关闭文件才能保存写入内容

f.write('i love ivcc')

f.close()

文件内容处理

示例代码

def save_file(count, EM, YZ):# 文件保存if count != 0:file_name_EM = '恶魔_' + str(count) + '.txt'file_name_YZ = '勇者_' + str(count) + '.txt'EM_file = open(file_name_EM, 'w', encoding='utf-8')YZ_file = open(file_name_YZ, 'w', encoding='utf-8')EM_file.writelines(EM)YZ_file.writelines(YZ)EM_file.close()YZ_file.close()def main_split_file():EM = []YZ = []count = 0f = open('.\\file内容分割test_file.txt', encoding='utf-8')for each_line in f:print(each_line)if each_line[:6] != '======':# 按照:分割字符串,保存到序列if count != 0:(role, line_spoken) = each_line.split(':', 1)if role == '恶魔':EM.append(line_spoken)if role == '勇者':YZ.append(line_spoken)else:save_file(count, EM, YZ)EM = []YZ = []count += 1save_file(count, EM, YZ)f.close()if __name__ == '__main__':main_split_file()

测试文本

file内容分割test_file.txt

P31 文件系统

OS模块

访问文件系统的模块,用来处理文件和目录

OS: Operating System 操作系统

os基本方法

注:

'.'表示当前目录'…'表示上一级目录

路径操作中常用到的一些定义

os.curdir 指代当前目录(’.’)os.pardir 指代上一级目录(’…’)os.sep 输出操作系统特定的路径分隔符(Win下为’\’,Linux下为’/’)os.linesep 当前平台使用的行终止符(Win下为’\r\n’,Linux下为’\n’)os.name 指代当前使用的操作系统(包括:‘posix’, ‘nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’)

os.path

P32 永久存储

pickle模块

“Pickling”是将Python对象层次结构转换为二进制字节流的过程,

“unpickling”是反向操作

作用:

简化程序,将大量的数据打包(如: 城市字典)成二进制文件,需要使用时调用即可

示例:

import pickledef dabao():my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']pickle_file = open('my_list.pkl', 'wb')pickle.dump(my_list, pickle_file)pickle_file.close()def diaoyong():pickle_file = open('my_list.pkl', 'rb')my_list2 = pickle.load(pickle_file)print(my_list2)if __name__ == '__main__':#dabao()diaoyong()

🔰异常处理(OLD:P33-34)

P33~34 你不可能总是对的

Python 标准异常总结

python标准异常

表 python常见标准异常

异常层次结构

BaseException SystemExitKeyboardInterruptGeneratorExitException StopIterationArithmeticError FloatingPointErrorOverflowErrorZeroDivisionError AssertionErrorAttributeErrorBufferErrorEOFErrorImportErrorLookupError IndexErrorKeyError MemoryErrorNameError UnboundLocalError OSError BlockingIOErrorChildProcessErrorConnectionError BrokenPipeErrorConnectionAbortedErrorConnectionRefusedErrorConnectionResetError FileExistsErrorFileNotFoundErrorInterruptedErrorIsADirectoryErrorNotADirectoryErrorPermissionErrorProcessLookupErrorTimeoutError ReferenceErrorRuntimeError NotImplementedError SyntaxError IndentationError TabError SystemErrorTypeErrorValueError UnicodeError UnicodeDecodeErrorUnicodeEncodeErrorUnicodeTranslateError Warning DeprecationWarningPendingDeprecationWarningRuntimeWarningSyntaxWarningUserWarningFutureWarningImportWarningUnicodeWarningBytesWarningResourceWarning

#### 异常检测与处理

try-except语句

检测到异常后,不会运行接下来的程序了

try-finally语句

raise语句 自己引发异常raise testerror(‘此为异常解释内容’)

🔰else 和 with(OLD:P35)

P35丰富的else语句及简洁的with语句

else语句用法扩展

while配合else:

如果break,不会进行语句2;如果全部执行完循环,不执行语句2.

while 表达式1:if 表达式2:语句1break语句2else:语句3

try结合else:

如果try下的内容出错,正常执行exception;否则执行else

try:语句1except ValueError as reason:语句2else:语句3

with语句

参考python之with语句

with语句仅仅能对支持上下文管理协议的对象使用。支持本协议的对象

- file

- decimal.Context

- thread.LockType

- threading.Lock

- threading.RLock

- threading.Condition

- threading.Semaphore

- threading.BoundedSemaphore

语法结构

with context_expr() as var:doSomething()

解析

context_expr()为上下文表达式,先执行,获取上下文对象后调用_enter_()方法无论语句是否正常结束,都会调用_exit_()方法

P36 图形用户界面EasyGui

easygui官网

easygui学习文档(中文版)

三种调用方式

import easyguieasygui.msgbox('hi,pig')from easygui import *msgbox('hi,pig')import easygui as gg.msgbox('hi,pig')

🔰类和对象(OLD:P37~P41)

相关名词解释

类(class):用来描述具有相同的属性和方法的对象的集合,类的内部定义了每个对象共有的属性和方法。属性:静态的特征方法:动态的动作,类中定义的函数对象:通过类定义的数据结构实例。对象=属性+方法,对象包括两个数据成员(类变量和实例变量)和方法。实例化:创建一个类的实例,类的具体对象。继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

介绍

类和对象是一种封装python中约定类名以大写字幕开头面向对象:OO,Object Oriented

OO的特征:

封装:将数据、方法封装在class中。只需知道名字进行调用即可,保密性更高 可参考:OO封装、继承、多态 继承:子类能够自动获取父类的数据和方法多态:同一方法可根据发送对象的不同而采用不同的响应 一个对象的实际类型是确定的,但是指向对象的引用类型有很多

类的一个创建和调用、继承、多态的例子:

# 对象的属性、方法调用举例class Cooldream:"""关于类的一个简单例子"""# 属性interesting = '计算机编程、手工DIY'gender = '保密'telephone = '181********'# 方法def learnPython(self):print('先看完看完小甲鱼的教程...')def learnEnglish(self):print('先背单词吧...')# 继承举例,继承listclass Myclass(Cooldream):pass# 多态举例class A:def fun(self):print('这里是A...')class B:def fun(self):print('这里是B...')if __name__ == '__main__':print('----对象的属性、方法调用举例----')# 调用对象的属性test = Cooldream()print('gender:', test.gender)# 调用对象中的方法test = Cooldream()test.learnPython()# 继承举例print('----继承举例,它可以使用现有Cooldream类的所有功能----')class1 = Myclass()print('继承来的gender:', class1.gender)print('继承来的learnPython:👇👇')class1.learnPython()# 多态举例print('----多态举例,调用的方法都是fun,但响应不同----')a = A()b = B()

输出结果:

----对象的属性、方法调用举例----gender: 保密先看完看完小甲鱼的教程...----继承举例,它可以使用现有Cooldream类的所有功能----继承来的gender: 保密继承来的learnPython👇👇先看完看完小甲鱼的教程...----多态举例,调用的方法都是fun,但响应不同----这里是A...这里是B...

相关名词解释:

类(class):类=属性+方法,用来描述具有相同的属性和方法的对象的集合,类的内部了每个对象共有的属性和方法。属性:静态的特征方法:动态的动作,类中的函数对象:通过类的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。实例化:创建一个类的实例,类的具体对象。

OOA:面向对象分享

OOD:面向对象设计

OOP:面向对象编程

self的用法

self 代表类的实例,self 在类的方法时是必须有的,要将self写进第一个参数,虽然在调用时不必传入相应的参数。

例一

# self使用举例1class Ball1:def setName(self, name):self.name = namedef kick(self):print('我叫%s, 哎呀!谁踢我...' % self.name)if __name__ == '__main__':# self使用举例1print('----self使用举例1----')a = Ball1()a.setName('AA')b = Ball1()b.setName('BB')c = Ball1()c.setName('TT')a.kick()c.kick()

###运行结果----self使用举例----我叫AA, 哎呀,谁踢我...我叫TT, 哎呀,谁踢我...

例二、推荐方法,更简化

# self使用举例2class Ball2:def __init__(self, name):self.name = namedef kick(self):print('我叫%s, 哎呀!谁踢我...' % self.name)if __name__ == '__main__':# self使用举例2print('----self使用举例2----')a = Ball2('AA')b = Ball2('BB')c = Ball2('TT')a.kick()c.kick()

###运行结果----self使用举例----我叫AA, 哎呀,谁踢我...我叫TT, 哎呀,谁踢我...

init(self,param1, param2, …)方法称为构造方法 实例化一个对象时,此方法将会在对象创建时自动调用可以在实例化对象时传入参数,这些参数讲自动传入_init__方法中可通过重写_init__方法,来自初始化操作

私有变量或私有函数

在变量名或函数名前加上__,(访问方式一) 私有变量需通过内部函数访问,无法使用p.属性1进行访问,如示例中的“访问方式一”(访问方式二) 但“私有”其实是“伪私有”,可通过p._类名__属性名进行外部访问,如示例中的“访问方式二”

示例

# 公有变量,即普通变量class TestG:attribute = 'attribute变量的值'# 私有变量class TestS:__attribute = '__attribute变量的值'def getAttribute(self):return self.__attributeif __name__ == '__main__':# 访问公有变量print('----访问公有变量----')p = TestG()print(p.attribute)# 访问私有变量print('----访问私有变量----')p = TestS()print('访问方式一:', p.getAttribute())print('访问方式二:', p._TestS__attribute)

继承

语法:class DrivedClassNName(BaseClassName):

DrivedClassNName是子类BaseClassName是父类(基类、超类)子类可继承父类的所有属性和方法

例子见上👆

如果子类中父类同名的方法或属性,则会自动覆盖父类对应的方法或属性 如果子类中的方法覆盖了父类中的方法,需要先引入 父类中的方法,有两种解决办法 调用未绑定的父类方法父类名.父类中被覆盖的方法名(self)super函数(更好的方案)super().父类中被覆盖的方法名()不用传入self参数优点是,修改继承的父类时,不用修改引入代码,super()会自动查找

多重继承

语法:class DrivedClassNName(Base1, Base2, Base3, ...):

# 多重继承class Base1:def t1(self):print('我是t1')class Base2:def t2(self):print('我是t2')class Base3:def t3(self):print('我是t3')class C(Base1, Base2, Base3):passif __name__ == '__main__':c = C()c.t1()c.t2()c.t3()

缺点: 容易造成代码混乱,非必须就不用

拾遗

拾遗_百度百科

组合

把类的实例化放到新类中,就把旧类组合一起了。优点:不需要多重继承,没有造成代码混乱的风险

示例

# 组合举例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))if __name__ == '__main__':pool = Pool(1, 10)pool.print_num()

类、类对象和实例对象

对实例对象的属性进行赋值时,将生成一个新的实例对象属性,去覆盖类对象的属性

示例

# 对实例对象的属性进行赋值时,将生成一个新的实例对象属性,去覆盖类对象的属性,示例class C1:count = 0if __name__ == '__main__':a = C1()b = C1()c = C1()print('----原始 a, b, c 的count属性:----\n', a.count, b.count, c.count)c.count += 10print('----把c 的实例化对象count属性+10 | a, b, c 的count属性:----\n', a.count, b.count, c.count)print('----类对象 C1 的count属性:\n', C1.count)C1.count += 100print('----把类对象 C1 的count属性+100 | a, b, c 的count属性:----\n', a.count, b.count, c.count)

----原始 a, b, c 的count属性:----0 0 0----把c 的实例化对象count属性+10 | a, b, c 的count属性:----0 0 10----类对象 C1 的count属性: 0----把类对象 C1 的count属性+100 | a, b, c 的count属性:----100 100 10

类中的属性时静态的,且类属性和类对象是相互绑定的,不会受实例对象属性的影响

示例对象在对属性操作时,会创建新的实例对象属性,操作实例对象属性时,不影响类属性

注意:

如果属性名与方法名相同,属性会覆盖方法,如下示例

# 如果属性名与方法名相同,属性会覆盖方法,如下示例class C:def x(self):print('X-man')if __name__ == '__main__':c = C()print('---可调用方法 .x() ---')c.x()print('---增加属性名x,方法 .x() 被覆盖---')c.x = 1# 创建一个实例对象c的一个属性,由于python变量不需声明,因此直接赋值就相当于定义了一个x属性print('c.x =', c.x)c.x()print('.x()被覆盖,不能调用了...')

建议:

如果属性和方法多而复杂,可使用 继承 和 组合 的方法扩展类属性名用名词方法名用动词

绑定

实例对象通过self与class中的方法绑定。没绑定的话,实例对象就不能调用class方法,举个没绑定的例子:

示例一、没有self

# 缺少self,将无法与实例对象绑定class BB:def printBB(): # 缺少self,将无法与实例对象绑定print('no zuo no die')if __name__ == '__main__':# 缺少self,将无法与实例对象绑定print('----类对象调用:----')BB.printBB()print('----实例对象调用:----')bb = BB()bb.printBB()

示例二、有self

# 有self,可绑定class CC:def setXY(self, x, y):self.x = xself.y = ydef printXY(self):print(self.x, self.y)if __name__ == '__main__':# 有self,可绑定print('----------------------------------')dd = CC()print('dd属性>>', dd.__dict__)print('CC属性>>', CC.__dict__, '\n')print('----传入参数----')dd.setXY(4, 5)dd.printXY()print('dd属性>>', dd.__dict__)print('CC属性>>', CC.__dict__, '\n')print('----删除类CC,实例对象dd依然可调用CC中的方法,并且设置实例属性dd.x、dd.y ----')del CCdd.printXY()dd.setXY(5, 6)dd.printXY()

注:

通过 dd.dict可查看对象属性,以字典形式返回,加上print才能在pycharm中打印出结果,IDE中无需加print

在这里,self的一个作用是,将实例对象传入class方法,将他们绑定

缺少self,就无法绑定,实例对象调用方法时将会报错

dd.setXY(4, 5)相当于dd.setXY(dd, 4, 5), 默认将实例对象dd传入进方法,形成dd.xdd.y

类和对象相关的BIF

issubclass(class, classinfo) 判断一个类是否是指定类的子类 如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False一个类会被认为是其自身的子类classinfo可以是一个元组,都多个class构成,然后依次检索每个候选的类是否时它的子类如下示例

# issubclas判断一个类是否是指定类的子类,示例class A:passclass B(A):passclass C:passif __name__ == '__main__':print('B 是 A 的子类?', issubclass(B, A), '\n')print('B 是 B 的子类?', issubclass(B, B), '\n')print('B 是 object 的子类?', issubclass(B, object), '\n')# object是所有类的基类print('B 是 C 的子类?', issubclass(B, C), '\n')

isinstance(object, classinfo) 判断一个实例对象是否是指定类的实例对象 如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False如果第一个参数不是对象,则返回False;如果第二个参数不是类或由类组成的元组,则会抛异常TyptErrorclassinfo可以是一个元组,都多个class构成,然后依次检索每个候选的类是否时它的子类如下示例

# isinstance判断一个实例对象是否是指定类的实例对象,示例class A:passclass B(A):passclass C:passif __name__ == '__main__':# issubclas判断是否是子类,示例print('-----------------issubclass判断是否是类的实例对象-----------------')print('B 是 A 的子类?', issubclass(B, A), '\n')print('B 是 B 的子类?', issubclass(B, B), '\n')print('B 是 object 的子类?', issubclass(B, object), '\n')# object是所有类的基类print('B 是 C 的子类?', issubclass(B, C), '\n')# isinstance判断一个实例对象是否是指定类的实例对象,示例print('-----------------isinstance判断是否是类的实例对象-----------------')b1 = B()print('b1 是 B 的实例对象?', isinstance(b1, B), '\n')print('b1 是 C 的实例对象?', isinstance(b1, C), '\n')print('b1 是 A 的实例对象?', isinstance(b1, A), '\n')print('b1 是 (A, B, C)的实例对象?', isinstance(b1, (A, B, C)), '\n')

hasattr(object, name) 判断一个对象里是否有指定的属性 attr = attribute: 属性object是对象,name是属性名(字符串类型,要用引号)

# hasattr 判断一个对象里是否有指定的属性,示例class D:def __init__(self, x=0):self.x = xif __name__ == '__main__':# hasattr 判断一个对象里是否有指定的属性,示例print('-----------------hasattr 判断一个对象里是否有指定的属性-----------------')d1 = D()hasattr(d1, 'x')print('d1 有 x 属性?', hasattr(d1, 'x'), '\n')

getattr(object, name[, default]) 返回对象指定的属性值 如果指定的属性不存在,则返回default(可选参数);若没有设置default参数,则抛异常AttributeError setattr(object, name, value) 设置对象中指定属性的值 如果指定的属性不存在,则会新建属性并赋值 delattr(object, name) 删除对象中指定的属性 如果属性不存在,抛出异常AttributeError

# getattr 返回对象指定的属性值,示例# setattr 设置对象中指定属性的值,示例# delattr 删除对象中指定的属性,示例class D:def __init__(self, x=0):self.x = xif __name__ == '__main__':# getattr 返回对象指定的属性值print('-----------------getattr 返回对象指定的属性值-----------------')d1 = D()print('d1 有 x 属性是:', getattr(d1, 'x'), '\n')print('d1 有 x 属性是:', getattr(d1, 'y', '您所访问的对象不存在!'), '\n')print('d1 有 x 属性是:', getattr(d1, 'y'), '\n')# setattr 设置对象中指定属性的值print('-----------------setattr 设置对象中指定属性的值-----------------')print('d1 有 y 属性是:', getattr(d1, 'y', '您所访问的对象不存在!'), '\n')print('设置 d1 中 y 的属性:FishC')setattr(d1, 'y', 'FishC')print('d1 有 y 属性是:', getattr(d1, 'y'), '\n')# delattr 删除对象中指定的属性print('----------------- delattr 删除对象中指定的属性-----------------')delattr(d1, 'y')delattr(d1, 'y') # 将会报错 AttributeError

property(fget=None, fset=None, fdel=None, doc=None) 用来通过属性操作属性 fget 是获取属性的方法名fset 是设置属性的方法名fdel 是删除属性的方法名可参考:property 的详细使用方法优点: 用户只需调用x来间接获取修改后的一些(fget, fsee, fdel) 属性。不然,如果将class中的方法名全部改了,用户也要跟着改很多代码

# property 通过属性操作属性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.sizex = property(getSize, setSize, delSize)if __name__ == '__main__':# property 通过属性操作属性print('----------- property 通过属性操作属性----------- ')c = C()# print('c.getSize() =', c.getSize())print('通过c.x 自动调用getSize() | c.x =', c.x) # 调用getSize()c.x = 18 # 调用SetSize()print('通过c.x=18 自动调用 SetSize() | c.x =', c.x)print('c.size =', c.size)del c.x # 调用DelSize()print('通过del c.x 自动调用 DelSize() | ', c.size) # 此时,size属性已被删除,将报错AttributeError: 'C' object has no attribute 'size'

🔰魔法方法(OLD:P42~P49)

可参考:Python 魔法方法详解__fishC

总是被双下划线包围,如__init__很强,体现在在适当的时候自动被调用参考: 单下划线、双下划线、头尾双下划线说明:foo: 的是特殊方法,一般是系统名字 ,类似init() 之类的。_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

P42 构造和析构

简单的调用方法:obj = className(args)|

|new(cls[, …])|

- 实例化对象时,第一个被调用的魔法方法

- 它的第一个参数是类,其他的参数会直接传递给__init__()方法

- 需要继承一个不可变类型,又需要进行修改时特性时,就用到了__new__重

|

|del( self )|

- 析构方法, 删除一个对象

- 它是一个垃圾回收机制

- 所有对象对class的引用都被del之后,参会触发。如示例

简单的调用方法 :del obj

|

|repr( self )| 转化为供解释器读取的形式

简单的调用方法 :repr(obj)|

|str( self )| 用于将值转化为适于人阅读的形式

简单的调用方法 :str(obj)|

|cmp( self, x )| 对象比较

简单的调用方法 :cmp(obj, x)|

# __new__(cls[, ...]) 示例class CapStr(str):# 定义一个继承于 str 的大写字符串def __new__(cls, string):string = string.upper()return str.__new__(cls, string)'''这里是要定义一个继承str特性的类CapStr但是CapStr又要把输入的字符串变成大写str没有这个性质,它是不能改变的所以要进行修改__new__方法新建类CapStr,在它那里用str的方法变大写把转换得到的结果作为输入的字符串再传给str的方法__new__,就实现了需求类CapStr就成了继承str且能把输入变大写的类'''if __name__ == '__main__':# __new__(cls[, ...]) 示例a = CapStr('a b cd efg')print('\n__new__重写后,Capstr(str)既继承了str,又可将字符串变大写:', a)

# __del__( self ) 示例class C:def __init__(self):print('我是__init__(),我被调用了...')def __del__(self):print('我是__del__(),我被调用了...')if __name__ == '__main__':# __del__( self ) 示例c1 = C()c2 = c1# c2引用c1c3 = c2# c3引用c2print('\n>>>>现在开始依次del引用 C() 类的实例对象\n')del c3del c2del c1print('\n>>>>看到了吧,直到所有被引用的c1、c2、c3都被del了之后,__del__()才会被自动调用')

P43 算术运算1~

关于工厂函数: python2.2以前,类和类型是分开的。类是属性和方法的封装,类型是整型、字符型、字符串这种python2.2之后,类和类型进行了统一 ,诸如将int()、float()、str()、list()、tuple()等这些内置函数(BIF)转换为工厂函数(类对象)

# 工厂函数于BIF, 示例class C:passif __name__ == '__main__':# 工厂函数于BIF, 示例print('type(len): ', type(len), '\n') # 普通的BIF,返回<class 'builtin_function_or_method'> ,他是一个内置的函数或方法print('type(dir): ', type(dir), '\n') # 普通的BIF,print('type(int): ', type(int), '\n') # 工厂函数,返回<class 'type'> ,print('type(list): ', type(list), '\n')# 工厂函数,当调用它们的时候,其实就是创建了一个相应的实例对象print('type(C): ', type(C), '\n')a = int('123')# 实例化一个int对象,返回一个实例后的对象,传入的参数是123(a是int的实例对象)b = int('459')print('a+b: ', a + b, '\n') # python对两个对象相加

算数运算符

|方法| *描述( 定义|

| — | — |

|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) | 按位或操作:| |

add(self, other)、sub(self, other) ,示例1

# __add__(self, other)、__sub__(self, other) ,示例1class New_int(int):def __add__(self, other):return int.__sub__(self, other)def __sub__(self, other):return int.__add__(self, other)if __name__ == '__main__':# __add__(self, other)、__sub__(self, other) ,示例1a = New_int(3)b = New_int(5)print('a+b:', a + b, '\n') # 加号触发了 __add__(self,other) 方法print('a-b:', a - b, '\n') # 减号触发了 __sub__(self,other) 方法

add(self, other)、sub(self, other) ,示例2

# __add__(self, other)、__sub__(self, other) ,示例2class New_int(int):def __add__(self, other):return (int(self) + int(other)) # 将self与other强制转换为整型,所以不会出现两个对象相加不断触发__add__()的情况def __sub__(self, other):return (int(self) - int(other))if __name__ == '__main__':# __add__(self, other)、__sub__(self, other) ,示例2a = New_int(3)b = New_int(5)print('a + b =', a + b)'''# 无限递归的情况# __add__(self, other)、__sub__(self, other) ,示例2class New_int(int):def __add__(self, other):return (self + other)def __sub__(self, other):return (self + other)if __name__ == '__main__':# __add__(self, other)、__sub__(self, other) ,示例2a = New_int(3)b = New_int(5)print('a + b =', a + b)'''

P44 算数运算2~

当一个对象进行相关算数运算操作时,自动触发对应的魔法方法。一旦重写了魔法方法,就能按照重写的方法运行。增加了更多的灵活性。如:重写int后,当我们进行加法运算时,给出一个减法运算结果, 示例如下

# 重写int:当我们进行加法运算时,给出一个减法运算结果,示例class int(int): # 当类int变成类对象,就能将原来的工厂函数int覆盖掉def __add__(self, other):return int.__sub__(self, other)if __name__ == '__main__':# 重写int:当我们进行加法运算时,给出一个减法运算结果,示例a = int('5')print("int('5') =", a)b = int(3)print('int(3) =', b)print('a + b =', a + b)

反运算

与算术运算符一一对应

示例1,示例2

# 反运算,示例1class Nint(int):def __radd__(self, other):return int.__sub__(self, other)if __name__ == '__main__':print('----------反运算,示例1-----------')a = Nint(5)b = Nint(3)print('a + b =', a + b)print('1 + b =', 1 + b) # 由于 1 没有__add__()方法,所以b的__radd__()被 1 自动触发执行# 注意:1 + b 的时候,return int.__sub__(self, other)中的sel指的时 b,other指的是前面的 1(输出:3 - 1 = 2)# 反运算,示例2class Nint2(int):def __rsub__(self, other):return int.__sub__(other, self)# 将self与other互换位置才能正常进行减法if __name__ == '__main__':print('----------反运算,示例2-----------')c = Nint2(5)print('3 - c =', 3 - c)# 由于3无__add__()方法,所以执行b的反运算__radd__(self,other)方法,将c传入了self

其他运算操作

增量赋值运算

使用时,与重写普通魔法方法一样

一元操作符

类型转换

上下文管理(with 语句)

P45 简单定制(实战任务)

实战任务:简单定制一个计时器

基本要求:

定制一个计时器的类start和stop方法代表启动计时 和 停止计时假设计时器对象t1,print(t1)和直接调用t1均显示结果当计时器未启动或已经停止计时,调用stop方法会给予温馨的提示两个计时器对象可以进行相加:t1 + t2只能使用提供的有限资源完成

需要使用的资源:

使用time模块的localtime方法获取时间 扩展阅读:time 模块详解(时间获取和转换)time.localtime([secs])接收时间辍(1970 纪元年后经过的浮点秒数)并返回当地时间下的时间元组 t(t.tm_isdst 可取 0 或 1,取决于当地当时是不是夏令时) time.localtime返回struct_time的时间格式 以时间元祖(struct_time)的形式返回0~5个元素就是从年到秒 表现你的类:strrepr重写他们,如示例1

重写strrepr,示例1

# 重写 __str__ 和 __repr__,示例1class A:def __str__(self):return '__str__() 被重写了,所以调用 print 时打印出了我!'class B:def __repr__(self):return '__repr__() 被重写了,所以运行 实例对象b 时打印出了我...'if __name__ == '__main__':a = A()print(a)a # 直接运行a,不会有输出。但重写__repr__() 后,就可以有输出了b = B()print(b)b# 需要在IDLE上运行才有输出,才能看到两者的区别:a返回的是<__main__.A object at 0x00000000032683D0>,而b返回的是__repr__() 被重写了,所以运行 实例对象b 时打印出了我...

实战任务:简单定制一个计时器,示例2

import time as t # 导入 time 模块的 timport timeclass Mytimer():# 在 __init__ 中初始化 定义一些变量def __init__(self):self.unit = ['年', '月', '天', '小时', '分钟', '秒']self.prompt = "未开始计时"self.lasted = []self.begin = 0self.end = 0def __str__(self):return self.prompt__repr__ = __str__# 将 __str__ 的方法复制给 __repr__def __add__(self, other): # 重写加法操作符,运行时间相加prompt = "它们总共运行了:"result = []for index in range(6):result.append(self.lasted[index] + other.lasted[index])if result[index]:prompt += (str(result[index]) + self.unit[index])return prompt# 开始计时def start(self):self.begin = t.localtime()self.prompt = ("提示:请先调用stop()停止计时!")print('计时开始...')# 停止计时def stop(self):if not self.begin:print('提示:请先调用start()进行计时!')else:self.end = t.localtime()self._calc()print('计时结束!')# 内部方法,计算运行时间def _calc(self):self.prompt = "总共运行了:"for index in range(6):self.lasted.append(self.end[index] - self.begin[index])if self.lasted[index]:# 判断是否为零,非零才往下走self.prompt += (str(self.lasted[index]) + self.unit[index])# 时间 + 单位# 为下一轮计时初始化变量self.begin = 0self.end = 0if __name__ == '__main__':print('------------开始使用 t1 计时------------')t1 = Mytimer()print('<<<未调用start,未调用stop>>>,将有如下提示:')print(t1)print('<<<未调用start,就调用stop>>>,将有如下提示:')t1.stop() # 提示:请先调用start() 进行计时!print('<<<先调用start,后调用stop>>>,将有如下正常提示:')t1.start()# 计时开始...time.sleep(6)t1.stop() # 计时结束!print(t1) # 总共运行了 秒print('------------开始使用 t2 重新计时------------')t2 = Mytimer()t2.start()# 计时开始...t2.stop() # 计时结束!print(t2) # 总共运行了 秒print('------------t1 和 t2 合计运行------------')print(t1 + t2) # 总共运行了 秒'''# 教程里的原程序,可在IDLE运行t1 = Mytimer()t1t1.stop() # 提示:请先调用start() 进行计时!t1.start()# 计时开始...t1.stop() # 计时结束!t1 # 总共运行了 秒t2 = Mytimer()t2.start()# 计时开始...t2.stop() # 计时结束!t2 # 总共运行了 秒t1 + t2 # 总共运行了 秒'''

P46 属性访问

四种访问方式

直接访问:对象.属性getatter()访问:getatter(对象, '属性名', '没有此属性!')property 通过属性操作属性:示例1魔法方法的重写

# 前三种方法访问属性,示例1class C:def __init__(self, size=10):self.size = sizeself.y = 'Y-man'def getSize(self):return self.sizedef setSize(self, value):self.size = valuedef delSize(self):del self.sizex = property(getSize, setSize, delSize)if __name__ == '__main__':c = C()print('--------------------方法一:')print(c.y)print('--------------------方法二:')print(getattr(c, 'y', '没有此属性!'))print('--------------------方法三:property 通过属性操作属性')print(c.x)'''# IDEL版本c = C()c.ygetattr(c, 'y', '没有此属性!')c.x'''

通过魔法方法的重写获取属性

注意啦,魔法方法会被自动触发调用

看这几个魔法方法被调用的顺序和触发点,示例2

# 看这几个魔法方法被调用的顺序和触发点,示例2class C:def __getattribute__(self, name):print('getattribute')# 使用 super() 调用 object 基类的 __getattribute__ 方法return super().__getattribute__(name)def __setattr__(self, name, value):print('setattr')super().__setattr__(name, value)def __delattr__(self, name):print('delattr')super().__delattr__(name)def __getattr__(self, name):print('getattr')if __name__ == '__main__':c = C()print('-------------------运行 c.x-------')c.xprint('-------------------运行 c.x = 1-------')c.x = 1print('-------------------运行 c.x-------')c.xprint('-------------------运行 del c.x-------')del c.x'''# IDEL版本c = C()c.xc.x = 1c.xdel c.x'''

小练习

练习要求

写一个矩形类,默认有宽和高两个属性;如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都应该等于边长

# 小练习,示例2class Rectangle:def __init__(self, width=0, height=0):self.width = widthself.height = heightdef __setattr__(self, name, value):#一发生赋值操作,则会触发__setattr__()魔法方法if name == 'square':#判断name属性是否为正方形self.width = valueself.height = valueelse:# self.name = value # __init__()中的赋值操作自动触发__setattr__(),self.name = value又进行了赋值操作,又自动触发__setattr__()。如此无线递归循环# super().__setattr__(name, value) # 调用基类的__setattr__(),如果直接使用self.name = value,会形成无限递归self.__dict__[name] = value # 代替上一行程序,__dict__[]以字典的形式显示当前对象的所有属性及其对应的值# super().__setattr__()这种调用基类的魔法方法的方式比较通用def getArea(self):return self.width * self.heightif __name__ == '__main__':r1 = Rectangle(4, 5)r1.getArea()r1.square = 10r1.widthr1.heightr1.getArea()'''# IDEL版本r1 = Rectangle(4,5)r1.getArea()r1.square = 10r1.widthr1.heightr1.getArea()'''

P47 描述符

通过此节可弄清楚描述符,可以研究property的实现原理

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。所谓“特殊类型”,至少要满足 实现以下方法的其中一个__get__(self, instance, owner)– 用于访问属性时会被自动调用,它返回属性的值 self(描述符类本身的一个实例),instance(描述符拥有者的类的实例),owner(描述符拥有者的类)__set__(self, instance, value)– 将在属性分配操作中会被自动调用,不返回任何内容__delete__(self, instance)– 控制删除操作会被自动调用,不返回任何内容

描述符示例,示例1

# 描述符示例,示例1class 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() # 取 MyDecriptor 类的实例指派给Test类的属性x,称MyDecriptor()就是 x 的描述符,MyDecriptor就是描述符类if __name__ == '__main__':test = Test()test.x # 自动调用描述符的 __get__(),输出结果的三个参数分别为: self(描述符类本身的一个实例), instance(描述符拥有者的类Test的实例test), owner(描述符拥有者的类Test)print(test)print(Test)test.x = "X-man" # 自动调用描述符的 __set__(),value参数(test.x = "X-man" 中 的 "X-man")del test.x# 自动调用描述符的__delete__()'''# IDEL版test = Test()test.xtestTesttest.x = "X-man"del test.x'''

定义一个属于自己 的property——MyProperty,实现property所有功能。示例2

property的几个必须的参数;

selffget=Nonefset=Nonefdel=None

# 定义一个属于自己 的property——MyProperty,实现property所有功能。示例2class MyProperty:def __init__(self, fget=None, fset=None, fdel=None):self.fget = fgetself.fset = fsetself.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)class C:def __init__(self):self._x = Nonedef getX(self):return self._xdef setX(self, value):self._x = valuedef delX(self):del self._xx = MyProperty(getX, setX, delX)if __name__ == '__main__':c = C()c.x = "XXXXXX"print(c.x)print(c._x)del c.x'''# IDEL版c = C()c.x = "HELLOW"c.xc._xdel c.x'''

小练习:

练习要求

先定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性。要求两个属性会自动进行转换,也就是说你可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。华氏度与摄氏度转换公式:摄氏度*1.8+32 = 华氏度

小练习,描述摄氏度和华氏度两个属性及自动转换,示例3

# 小练习,描述摄氏度和华氏度两个属性及自动转换,示例3class Celsius: # 摄氏度描述符类def __init__(self, value=26.0): # self为描述符类自身(此为摄氏度描述符类)的实例(此为cel)self.value = float(value) # 转换成浮点数运算def __get__(self, instance, owner): # instance是这个描述符的拥有者所在的类的实例(此为temp)return self.value # 当class Temperature: 中的cel属性被获得时,返回self.valuedef __set__(self, instance, value): # owner是这个描述符的拥有者所在的类本身(此为温度类)self.value = float(value) # 当class Temperature: 中的cel属性被设置时,进行赋值操作class Fahrenheit: # 华氏度描述符类def __get__(self, instance, owner):return instance.cel * 1.8 + 32 # 摄氏度转华氏度def __set__(self, instance, value):instance.cel = ((float)(value) - 32) / 1.8 # 华氏度转摄氏度class Temperature:# 温度类cel = Celsius()# 设置摄氏度属性(描述符类的实例指派给了温度类的属性)fah = Fahrenheit() # 设置华氏度属性if __name__ == '__main__':temp = Temperature()print(temp.cel)temp.cel = 30print(temp.fah)temp.fah = 100print(temp.cel)'''# IDEL版temp = Temperature()temp.celtemp.cel = 30 temp.fahtemp.fah = 100temp.cel'''

P48 定制序列(定制容器)

协议

协议(Protocols)与其他编程语言中的接口很相似,它规定你哪些方法必须要定义。而在Python中的协议就显得不那么正式,在Python中的协议更像是一种指南。

容器

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。容器是一种可以包含其他类型对象(如列表、元组、字典等)作为元素的对象。

容器类型的协议

如果说你希望定制的容器是不可变的话,你只需要定义__len__()和__getitem__()方法。如果你希望定制的容器是可变的话,除了__len__()和__getitem__()方法,你还需要定义__setitem__()和__delitem__()两个方法。

容器类型的魔法方法

# 定义记录列表中每个元素访问次数类,示例class CountList:# 定义记录列表中每个元素访问次数类def __init__(self, *args): # 参数是可变类型的self.values = [x for x in args] # 将args的数据存入列表中,通过列表推导式存放到values列表self.count = {}.fromkeys(range(len(self.values)),0)# 创建字典,初试化为0(列表下标对应字典中的键,值就对应键值)def __len__(self): # 返回容器中元素的个数return len(self.values)def __getitem__(self, key):# 获取容器中指定元素的行为self.count[key] += 1 # 每访问一次,字典键对应的键值加1return self.values[key]if __name__ == '__main__':c1 = CountList(1, 3, 5, 7, 9)c2 = CountList(2, 4, 6, 8, 10)print(c1[1]) # c1[1]第一次访问print(c2[2])c1[1] + c2[2]# c1[1]第二次访问print(c1.count)print(c2.count)'''# IDEL版c1 = CountList(1,3,5,7,9)c2 = CountList(2,4,6,8,10)c1[1] #c1[1]第一次访问c2[2]c1[1] + c2[2] #c1[1]第二次访问c1.countc2.count'''

迭代器

提供迭代方法的容器就是迭代器

通常的迭代器有:序列、字典,如: 使用for循环对序列进行迭代,每次从容器中拿取一个数据

迭代类似循环,每次重复的过程就是一次迭代;而一次迭代的结果往往作为下次迭代的初始值

序列、字典的迭代,示例1

# 序列、字典的迭代,示例1for i in 'abcdefg':print(i)test = {'a':'A', 'b':'B','c':'C' ,'d':'D' ,'e':'E'}for each in test:print("%s -> %s" %(each, test[each]))

python提供了两个迭代器BIF:

inter() 一个容器对象调用inter()就得到了迭代器 next() 调用next(),迭代器就会返回下一个值,若没有下个值,就抛异常

inter()、next(),示例2

#inter()、next(),示例2string = "FishC"it = iter(string)print(next(it))print(next(it))print(next(it))print(next(it))print(next(it))# next(it) # 运行将抛异常'''IDLE版string = "FishC"it = iter(string)next(it)next(it)next(it)next(it)next(it)'''

for语句工作原理,用while语句实现for,示例3

# for语句工作原理,用while语句实现for,示例3string = "FishC"it = iter(string)while True:try:each = next(it)except StopIteration:breakprint(each)

迭代器的魔法方法

iter()、next()分别是inter()、next()对应的魔法方法

一个容器如果是迭代器,那就必须实现__iter__(),iter()能返回迭代器本身return selfnext()决定了迭代器规则

迭代器实现可控斐波那契数列,示例4、5

# 迭代器实现斐波那契数列,示例4class Fibs:def __init__(self):self.a = 0self.b = 1def __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.breturn self.afibs = Fibs()for each in fibs:if each < 20:print(each)else:break'''# 迭代器实现斐波那契数列,可控制迭代范围,示例5class Fibs:def __init__(self, n=10):self.a = 0self.b = 1self.n = ndef __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > self.n:raise StopIterationreturn self.afibs = Fibs()for each in fibs:print(each)print('------------------------')fibs = Fibs(100)for each in fibs:print(each)'''

小甲鱼零基础入门学习python笔记

🔰生成器(OLD:P50)

P50乱入,生成器

无需类和方法对象,仅需要普通函数即可实现,相比迭代器,生成器使得ython更为简洁生成器需要在普通函数里有 yield 语句生成器使得协同程序可以实现可参考: 提高你的 Python:解释 yield 和 Generators(生成器)—— 鱼C工作室

协同程序(生成器的应用)

所谓协同程序,就是可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始。

yield相当于普通函数中的return语句,它在返回数据的同时,能将函数执行过程暂停于此

用生成器实现的几个例子,示例1~2

# 用生成器实现的几个例子,示例1~# 生成器运行过程示例,示例1def myGen():print("生成器被执行了!")yield 1yield 2yield 3myG = myGen()next(myG)next(myG)for i in myGen():print(i)print('-------------------------------')# 斐波那契也可以用生成器来实现,示例2def fibs():a = 0b = 1while True: # 生成器随时都会暂停,不用担心死循环a, b = b, a + byield afor each in fibs():if each > 100:breakprint(each, end=' ')

四种推导式(包含了生成器推导式)

# 列表推导式a = [i for i in range(100) if not (i % 2) and (i % 3 )]# 100以内,能被2整除,但不能被3整除的所有整数print(a)print('-------------------------------')# 字典推导式:a = {i:i % 2 == 0 for i in range(10)} # 10以内是否为偶数print(a)print('-------------------------------')# 集合推导式:a = {i for i in [1, 2, 3, 3, 3, 6, 5, 5, 6, 7, 7, 8]}print(a)print('-------------------------------')# (元组)生成器推导式:e = (i for i in range(5))print(next(e))print(next(e))print(next(e))for each in e:print(each, end=' ')print('\n-------------------------------')# 生成器推导式可作为函数的参数:把sum里面的内容是生成器推导式,把生成器推导式里生成的数据都加起来,计算100以内不能被2整除的数的和print(sum(i for i in range(100) if i % 2))

🔰模块 (OLD:P51~P53)

P53 模块就是程序

介绍

容器是对数据的封装

函数是对语句的封装

类是对方法和属性的封装

模块就是对程序的封装,一个python文件

命名空间

模块.方法,如:hello.hi()

导入与调用模块

方法一、import 模块名调用:模块.模块中的函数名(参数)方法二、from 模块名 import 函数名,函数名可以使用*代替,用于导入模块中的所有命名空间 调用:模块中的函数名(参数)缺点:可能出现模块中的函数名与程序中的函数名重复的情况方法三、import 模块名 as 新模块名推荐! 调用:新模块名.模块中的函数名(参数)优势:重命名模块名,可使长的模块名缩短

示例 - 模块

# TemperatureConversion.pydef c2f(cal):fah = cal * 1.8 + 32return fahdef f2c(fah):cal = (fah - 32)/1.8return cal

示例 - 调用

# 方法一import TemperatureConversion print("32 摄氏度 = %.2f 华氏度" % TemperatureConversion.c2f(32))print("99 华氏度 = %.2f 摄氏度" % TemperatureConversion.f2c(99))# 方法二from TemperatureConversion import c2f, f2c # 或from TemperatureConversion import * print("32 摄氏度 = %.2f 华氏度" % c2f(32))print("99 华氏度 = %.2f 摄氏度" % f2c(99))# 方法三import TemperatureConversion as tc print("32 摄氏度 = %.2f 华氏度" % tc.c2f(32))print("99 华氏度 = %.2f 摄氏度" % tc.f2c(99))

P52name==‘main’、搜索路径和包

模块的好处:

实现代码的重复利用:先封装成模块,需要使用时,导入模块,再调用函数即可

ifname=='main’

注意:

模块文件在前期编写、调试的时候,要添加测试程序,已测试模块中的各个方法能否正常运行,如示例1

# 示例1def c2f(cal ):return cal * 1.8 + 32def f2c(fah):return (fah - 32)/1.8def test():print("测试:", "0摄氏度 = %.2f 华氏度\n" % c2f(0))print("测试:", "0华氏度 = %.2f 摄氏度" % f2c(0))test()

__name__变量如何使用?

如果在主程序中运行__name__,会返回__main__如果在主程序中使用模块调用__name__,如tc.__name__,会返回模块名

ifname= _ ‘main’_:可以方便避免在主程序调用模块的时候,运行到模块中的test()程序

if ``__name__ == _ ``_'main'_:_test()加入主程序,这就是个程序运行入口把if ``__name__ == _ ``_'main'_:_test()加入模块文件,那么它里面的test()就不会运行,因为不满足if的条件

搜索路径

查看搜索路径:import syssys.path最佳存放模块的路径:site-packages 文件夹 添加搜索路径sys.path.append('你的模块目录路径'),如sys.path.append("C:\\Python39\\test")

包(package)

用于解决模块太多而杂乱无章、并且可能出现命名冲突的问题

创建

创建一个文件夹,用于存放模块,文件夹的名字即包的名字;在文件夹中创建一个__init__.py的模块文件,内容可以为空,用于告诉python要将这个文件夹当成一个包;将相关的模块放入文件夹中。

调用

import 包名.模块名

然后,参考模块的导入与调用即可,同样的方法,有三种方法

P53 像一个极客去思考

使用现成的模块,如:python标准库中的模块

python标准库中的模块数百个,怎么自己去探索模块?如下:

查看pyhon自带文档:IDLE -> Help ->Python Docs F1

文档搜索:

在文档点索引,或搜索,如搜索timeit

其中:

第一段时介绍模块

Basic Examples:基础例程

Examples:详细运用的例子

快速掌握模块的用法

先导入模块,然后调用__doc__属性,查看模块简介。如import timeitprint(timeit.__doc__)使用dir()可以查询到该模块定义了哪些变量、函数和类。如dir(timeit), 其中的__all__属性:timeit.__all__可以给我们提供可供外界调用的东西其中的__file__属性:timeit.__file__可以给我们提供模块源代码所在位置 阅读源代码可以快速提升能力哦! 使用help(timeit)帮助文档,比print(timeit.__doc__)调出来的简单一点 注意: 不是所有模块都有__all__属性如果模块有__all__属性,那么使用*导入全部命名空间的话 如from timeit import *,只有timeit.__all__显示出来的才能被导入因此,推荐在编写模块文件时,将所有对外提供的接口和类,都设置到__all__属性的列表中 IT英语: IT英语版块 ——FishC每天进步一点点,做最好的自己[专辑] ——FishC:破渔网兜兜 最后 timeit模块太有用了,建议阅读源码等 [扩展阅读] timeit 模块详解(准确测量小段代码的执行时间)

🔰爬虫

P54 论一只爬虫的自我修养

python如何访问互联网?

url + lib = urllib

url就是网址,lib就是网址首页urllib是一个包,包含了4个模块:urllib.requestfor opening and reading URLsurllib.errorcontaining the exceptions raised by urllib.requesturllib.parsefor parsing URLsurllib.robotparserfor parsing robots.txt files

url的一般格式

protocol 😕/ hostname[:port] / path / [;parameters][?query]#fragment

URL由三部分组成:

协议:http,https,ftp,file,ed2k…存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口为80)。资源的具体地址,如目录或文件名等。

urllib中访问网页的函数

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)url是必须的,其他都是有默认参数或是可选参数

示例

import urllib.requestresponse = urllib.request.urlopen('')html = response.read()# 读取网页print(html)print('-------------------------------------------------------------')html = html.decode('utf-8') # 网页二进制解码print(html)

P55 论2:实战

程序注释都写了

爬取下载一只猫,示例1

一只猫的网站url:/g/500/600

# 爬取下载一只猫的示例import urllib.requestresponse = urllib.request.urlopen('/g/500/600') # 括号里面可以是url地址cat_imag = response.read()with open('cat_500_600.jpg', 'wb') as f: # 图片也是二进制格式的,用'wb'参数控制写入文件f.write(cat_imag)'''import urllib.request# 也可以这样写,将上面的response = urllib.request.urlopen()拆成下面的两行req = urllib.request.Request('/g/500/600')# 获取request对象response = urllib.request.urlopen(req)# 括号里面也可以是request对象cat_imag = response.read()with open('cat_500_600.jpg', 'wb') as f: # 图片也是二进制格式的,用'wb'参数控制写入文件f.write(cat_imag)''''''print(response.geturl(), '\n\n') # 得到访问的链接地址response.info()# 得到httpmessage对象,是远程服务器返回来的信息,包含了header信息print(response.info(), '\n\n')print(response.getcode(), '\n\n') # 得到http的状态码,200表示ok,就是正常响应'''

有道词典翻译

知识点

网页请求方式(客户端向服务器请求): get 从服务器请求获得数据post 向指定服务器提交被处理的数据 Headers——request headers 客户端请求头User-Agent:包含了客户端信息,能用于在服务器端判断是非为人或爬虫程序访问 Headers——Form Data 提交的主要内容 [技术交流] Python编码问题的解决方案总结

有道词典翻译,可参考:用Python破解有道翻译反爬虫机制/p/47785984

'''思路是:输入翻译内容打开检查 -- network点击翻译按钮,或按回车看到network下有很多GET类型的请求和一个Post类型的请求那么Post请求就是要研究的目标点开Post请求对应的路径:进入headers,有很多重要信息,包括:request urldata输出html后发现得到一段json数据,字符串json的形式,包含了翻译结果。json里面包含了字典。import json, 处理json数据,通过json.loads()载入字符串,得到字典通过关键词访问字典中键对应的值,获得一个两层列表'''# 此程序和教程中稍有不同,因为相比,现在的有道翻译做了调整(表单结构data)。按照教程中的思路总结如上import urllib.requestimport urllib.parseimport jsoncontent = input('请输入需要翻译的内容:')url = '/translate?smartresult=dict&smartresult=rule'data = {}data['i'] = '啊啊啊啊'data['from'] = 'AUTO'data['to'] = 'AUTO'data['smartresult'] = 'dict'data['client'] = 'fanyideskweb'data['salt'] = '16285587902727'data['sign'] = '296a1061a0ba4763f7cd7e22d5790840'data['lts'] = '1628558790272'data['bv'] = 'eda468fc64295ecf2810ab8a672c2db1'data['doctype'] = 'json'data['version'] = '2.1'data['keyfrom'] = 'fanyi.web'data['action'] = 'FY_BY_REALTlME'data = urllib.parse.urlencode(data).encode('utf-8')# 把编码后的data值覆盖dataresponse = urllib.request.urlopen(url, data)html = response.read().decode('utf-8') # read()之后得到的是utf-8编码文件'''decode()是把其他编码形式变成Unicode的形式encode()是把Unicode的形式变成其他形式'''# print(html) # 输出的是json格式,接下来还要处理提取 ↓# json.loads(html)target = json.loads(html)# type(target) # 观察target类型,是字典类型# target['translateResult']# target['translateResult'][0][0]print('翻译结果为 %s:' % (target['translateResult'][0][0]['tgt']))

P56 论3:隐藏

服务器一般通过headers中的UA检查 是什么东西在访问

两种方式添加/修改headers:

设置一个headers,作为参数传给request在request生成之后,通过调用.add_header()把它加进去

有道词典翻译,示例1

可参考,助于理解:用Python破解有道翻译反爬虫机制/p/47785984

'''# 有道词典翻译,示例1基于上一个程序,增加隐藏手段思路是:增加headers中的UA'''import urllib.requestimport urllib.parseimport jsoncontent = input('请输入需要翻译的内容:')url = '/translate?smartresult=dict&smartresult=rule''''# 设置一个headers,作为参数传给requesthead = {}head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36''''data = {}data['i'] = contentdata['from'] = 'AUTO'data['to'] = 'AUTO'data['smartresult'] = 'dict'data['client'] = 'fanyideskweb'data['salt'] = '16285587902727'data['sign'] = '296a1061a0ba4763f7cd7e22d5790840'data['lts'] = '1628558790272'data['bv'] = 'eda468fc64295ecf2810ab8a672c2db1'data['doctype'] = 'json'data['version'] = '2.1'data['keyfrom'] = 'fanyi.web'data['action'] = 'FY_BY_REALTlME'data = urllib.parse.urlencode(data).encode('utf-8')# 把编码后的data值覆盖datareq = urllib.request.Request(url, data)req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36')response = urllib.request.urlopen(url, data)html = response.read().decode('utf-8') # read()之后得到的是utf-8编码文件'''decode()是把其他编码形式变成Unicode的形式encode()是把Unicode的形式变成其他形式'''# print(html) # 输出的是json格式,接下来还要处理提取 ↓# json.loads(html)target = json.loads(html)# type(target) # 观察target类型,是字典类型# target['translateResult']# target['translateResult'][0][0]print('翻译结果为: %s' % (target['translateResult'][0][0]['tgt']))

还有个一问题,服务器记录你的访问速度,如果你的IP一秒访问很多次,那一定是爬虫,就被识别到了

两个方法

方法一、延迟每次访问时间方法二、使用代理ip 步骤: 参数是一个字典 {‘类型’:‘代理ip:端口号’}proxy_support = urllib.request.ProxyHandler({})定制、创建一个 opener opene用于打开网页,可以给它加上特殊的headers、指定相关的代理等opener = urllib.request.build_opener(proxy_support)安装 opener 安装后,以后调用方便urllib.request.install_opener(opener)调用 opener 可以可以不安装opener.open(url)

方法一,示例2

'''# 有道词典翻译,示例2基于上一个程序,增加:自动执行下一次、延迟、增加退出程序提示思路是:在外层增加while循环,用于自动执行下一次纯粹增加等待时间time.sleep(3)使用if判断输入内容是否为指定内容,而让程序退出'''import urllib.requestimport urllib.parseimport jsonimport timewhile True:content = input('请输入需要翻译的内容:')if content == 'q!':breakurl = '/translate?smartresult=dict&smartresult=rule''''# 设置一个headers,作为参数传给requesthead = {}head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36''''data = {}data['i'] = contentdata['from'] = 'AUTO'data['to'] = 'AUTO'data['smartresult'] = 'dict'data['client'] = 'fanyideskweb'data['salt'] = '16285587902727'data['sign'] = '296a1061a0ba4763f7cd7e22d5790840'data['lts'] = '1628558790272'data['bv'] = 'eda468fc64295ecf2810ab8a672c2db1'data['doctype'] = 'json'data['version'] = '2.1'data['keyfrom'] = 'fanyi.web'data['action'] = 'FY_BY_REALTlME'data = urllib.parse.urlencode(data).encode('utf-8')# 把编码后的data值覆盖datareq = urllib.request.Request(url, data)req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36')response = urllib.request.urlopen(url, data)html = response.read().decode('utf-8') # read()之后得到的是utf-8编码文件'''decode()是把其他编码形式变成Unicode的形式encode()是把Unicode的形式变成其他形式'''# print(html) # 输出的是json格式,接下来还要处理提取 ↓# json.loads(html)target = json.loads(html)# type(target) # 观察target类型,是字典类型# target['translateResult']# target['translateResult'][0][0]target = target['translateResult'][0][0]['tgt']print('翻译结果为: %s' % target)time.sleep(3)

方法二,通过代理访问,示例3

'''# 通过代理访问,示例3免费代理网址 /dailiip/2/1.html/getapi/ _/8/10 可用,不报错出错有可能是代理IP的问题'''import urllib.requestimport random# url = '.tw/' # 可测试目前ipurl = '/'iplist = ['183.162.159.227:4245', '115.239.102.56:4267', '59.58.104.78:4245', '221.231.75.90:4232', '114.239.172.153:4245']proxy_support = urllib.request.ProxyHandler({'http': random.choice(iplist)})opener = urllib.request.build_opener(proxy_support)opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36')]urllib.request.install_opener(opener)response = urllib.request.urlopen(url)html = response.read().decode('utf-8')print(html)

P57 论4:OOXX

教程源码,含必要注释:

'''目前/8/10,程序从网站爬取图片出现404错误,即使增加了header中的所有内容,也暂时无法解决网站增加了base编码:编码与解码参考:python中base64编码与解码:/fireflylane/article/details/84674509类似网站:• /245908/1• /albums/4701/1'''import urllib.requestimport osimport randomdef url_open(url):req = urllib.request.Request(url)req.add_header(':authority', '')req.add_header(':method', 'GET')req.add_header(':path', '/ooxx')req.add_header(':scheme', 'https')req.add_header('accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9')req.add_header('accept-encoding', 'gzip,deflate,br')req.add_header('accept-language', 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7')req.add_header('cache-control', 'max-age=0')req.add_header('cookie','BAIDU_SSP_lcr=/link?url=Ezh6mU9WWWexbF_wRh-yJ2ETgTgeIbv_TK5znIZoTpG&wd=&eqid=cee1c8350007d23f00000003611246f2;_ga=GA1.2.469504217.1628587767;_gid=GA1.2.3149650.1628587768;__gads=ID=b0a6d594108c21ef-2240c337bdca00e8:T=1628587768:RT=1628587768:S=ALNI_MZWPHOJA7J3PtkE2I4fl7nirml7dg;PHPSESSID=ubbl5s6g2rqh14fvcao6lonl1b')req.add_header('sec-ch-ua', '"Chromium";v="92","NotA;Brand";v="99","GoogleChrome";v="92"')req.add_header('sec-ch-ua-mobile', '?0')req.add_header('sec-fetch-dest', 'document')req.add_header('sec-fetch-mode', 'navigate')req.add_header('sec-fetch-site', 'none')req.add_header('sec-fetch-user', '?1')req.add_header('User-Agent','Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/92.0.4515.131Safari/537.36')# -----------------------可选择使用代理---------------------iplist = ['183.162.159.227:4245', '115.239.102.56:4267', '59.58.104.78:4245', '221.231.75.90:4232', '114.239.172.153:4245']proxy = random.choice(iplist)proxy_support = urllib.request.ProxyHandler({'http': proxy})opener = urllib.request.build_opener(proxy_support)urllib.request.install_opener(opener)# -----------------------可选择使用代理---------------------'''response = urllib.request.urlopen(url)html = response.read()print(html)return htmldef get_page(url):html = url_open(url).decode('utf-8')a = html.find('current-comment-page ') + 23b = html.find(']', a)print('html[a:b] = ', 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(html[a+9:b+4])else:b = a + 9a = html.find('img src=', b)# for each in img_addrs:# print(each)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='OOXX', pages=10): # 主函数os.mkdir(folder) # 创建文件夹os.chdir(folder) # 切换工作目录url = '/ooxx/'page_num = int(get_page(url)) # 将返回的字符串变为整型for i in range(pages): # 循环获取前十页page_num -= ipage_url = url +'page-' + str(page_num) + '#comments'img_addrs = find_imgs(page_url)save_imgs(folder, img_addrs)if __name__ == '__main__':download_mm()

技巧总结:

编写主函数,分析所需子函数:搭建好子函数框架编写子函数调试运行

P58 论5:正则表达式

小甲鱼教程:[扩展阅读] Python3 如何优雅地使用正则表达式(详解一)

工具网站:

/,练习正则表达式,实时显示标记匹配结果

常用的通配符

,如.docx --> 查找docx后缀的文件?

python爬虫需求:

按照需要的内容特征自动去网页里查找

而,正则表达式本身就是用于描述那些复杂特征的

正则表达式

python通过re模块实现正则表达式

re.search()方法 扫描整个字符串,并返回第一个成功的匹配。如果匹配失败,则返回None。参考:/python/python-reg-expressions.htmlre.search(pattern, string, flags=0)pattern : 正则中的模式字符串,也就是搜索规则。string : 要被查找/替换的原始字符串。flags : 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

正则表达式特殊符号

**.**,通配符 一个英文的句号,他能代表换行符以外的任何字符\,反斜杠 能使元字符(如 . )失去它的特殊能力如果要消除表达式的某个功能,就在表达式前加上反斜杠。如示例中的re.search(r'\.', 'it is ')\d,匹配任何数字[],字符类 为了表示一个字符串的范围,可创建一个字符类只要匹配字符类中的任一个字符,都算匹配不区分大小写:[ - ]表示一个范围 如[a-z][0-9]{},限定重复匹配的次数

示例

import re# 用于搜索指定字符串位置,正则和find()方法都行test1_1 = re.search(r'fishc', 'it is ')test1_2 = 'it is '.find('fishc')print('test1-------', test1_1, test1_2, '\n')# . 它能代表换行符以外的任何字符test2_1 = re.search(r'.', 'it is ')test2_2 = re.search(r'fishc.', 'it is ')print('test2-------', test2_1, test2_2, '\n')# 如果想要单单匹配一个点test3_1 = re.search(r'\.', 'it is ')print('test3-------', test3_1, '\n')# \dtest4_1 = re.search(r'\d', 'aaa123 it is ')test4_2 = re.search(r'\d\d\d', 'aaa123 it is ')print('test4-------', test4_1, test4_2, '\n')# 匹配一个ip地址test5_1 = re.search(r'\d\d\d\.\d\d\d\.\d\d\d', 'cba 192.168.000.100 abc')test5_2 = 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])', 'cba 192.168.0.1 abc')print('test5-------', test5_1, test5_2, '\n')# []test6_1 = re.search(r'[aeiou]', 'it is ')test6_2 = re.search(r'[a-e]', 'it is ')print('test6-------', test6_1, test6_2, '\n')# {}test7_1 = re.search(r'ab{3}c', 'abbbcddefffg')test7_2 = re.search(r'ab{3,10}c', 'abbbbbbcddefffg') # b可匹配3~10个皆可print('test7-------', test7_1, test7_2, '\n')# 表示一个0-255test8_1 = re.search(r'[01]\d\d|2[0-4]\d|25[0-5]', '188')print('test8-------', test8_1, '\n')

P59 论6:正则表达式2

[扩展阅读] Python3 正则表达式特殊符号及用法(详细列表)——小甲鱼 付费

Python——正则表达式特殊符号及用法 —— 免费 参考

特殊符号会用就行,用到去查

特殊符号示例

import re# |test1_1 = re.search(r'fish(c|d)', 'it is ')test1_2 = re.search(r'fish(c|d)', 'it is ')print('test1-------', test1_1, test1_2, '\n')# ^ 脱字符 指定字符必须出现在被搜索字符串开头test2_1 = re.search(r'^fish(c|d)', 'it is ')test2_2 = re.search(r'^fish(c|d)', '')print('test2-------', test2_1, test2_2, '\n')# $ 匹配结尾位置test3_1 = re.search(r'fish(c|d)$', '')test3_2 = re.search(r'fish(c|d)$', 'it is fishc')print('test3-------', test3_1, test3_2, '\n')# \ ()test4_1 = re.search(r'(fishc)\1', 'it is ') # (fishc)\1 相当于fishcfishc ,镜像复制test4_2 = re.search(r'(fishc)\1', 'it is fishcfishc')test4_3 = re.search(r'(fishc)\060', 'it is fishcfishc0')test4_4 = re.search(r'(fishc)\141', 'it is fishcfishca')print('test4-------', test4_1, test4_2, test4_3, test4_4, '\n')# ^ [] findall能返回列表test5_1 = re.search(r'[.]', 'cba 192.168.000.100 abc')# 表示一个点test5_2 = re.findall(r'[\n]', 'cba 192.168.000.100 abc\n') # 此时表示转义符test5_3 = re.findall(r'[^a-z]', 'cba 192.168.000.100 abc\n') # ^放在前面表示取反,除了a-z 其他的都搜print('test5-------', test5_1, test5_2, test5_3, '\n')# {M,N}test6_1 = re.search(r'ab{3}c', 'abbbcddefffg') # 匹配b3此test6_2 = re.search(r'(ab){3}c', 'abababccd') # 匹配ab三次test6_3 = re.search(r'(ab){1,3}c', 'abababccd') # 匹配ab1~3次print('test6-------', test6_1, test6_2, test6_3, '\n')# 贪婪模式 与 非贪婪模式s = '<html><title></title></html>'test7_1 = re.search('r<.+>', s)test7_2 = re.search('r<.+?>', s)print('test7-------', test7_1, test7_2, '\n')

P60 论7:正则表达式3

Python——正则表达式特殊符号及用法 —— 免费 参考

特殊符号会用就行,用到去查

但是你要知道有这个方法,所以要先看一遍都有啥

编译正则表达式 如果需要重复使用某个正则表达式,就可以线将该正则表达式编译成模式对象pile()

import re# 编译正则表达式p = pile(r"[A-Z]")test1_1 = p.search('it is ')test1_2 = p.findall('it is ')print('-------------test1', test1_1, test1_2, '\n')

编译标志

通过编译标志,可以修改正则表达式的工作方式可同时使用多个编译标志,中间用 | ,如re.I | re.M[扩展阅读] Python3 如何优雅地使用正则表达式(详解三)

开启详细正则表达式模式

此模式支持空格和tab缩进和注释,能让表达式看上去更直观、易读re.VERBOSE

P61 论8:正则表达式4

srearch()方法 有两种调用方法: 模块形式调用:re.search(pattern, string, flag=0) 参数 pattern参数:模式string参数:要搜索的字符串flag参数:编译标志位 返回结果的捕获 .group(),如下示例1 result = re.search(f" (\w+) (\w+)", ‘it is ’)print(result.group()) .group()可以设置参数 .group(1),参数代表子组索引。没有参数默认提取所有内容 返回匹配的起始位置及范围 .start().end().span() 范围 编译后的正则表达式模式对象:regex = pile(),regex.secrch(string[, pos[, endpos]]) string[参数:要搜索的字符串pos[可选参数:要搜索的起始位置endpos]]可选参数:要搜索的结束位置 示例:rx.rearch(string, 0, 50) 等价于 rx.rearch(string[:50], 0) findall()方法 功能 返回匹配到的内容 调用 re.findall(pattern, string, flags=0) 如果正则表达式包含子组,将会把子组内容单独返回;如果存在多个子组,将会将匹配内容组合成元组再返回 如示例中的p = r’<img class=“BDE_Image” src="([^"]+.jpg)’ imglist = re.findall(p, html) 其中的src="([^"]+.jpg中的括号就是子组 如何不捕获子组? (?:…) 非捕获组,即该子组匹配的字符串无法从后面获取

下载贴吧中的图片,示例1

# 下载贴吧中的图片/p/7473449745import reimport urllib.request#def open_url(url):req = urllib.request.Request(url)req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36')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)filename = each.split("/")[-1]urllib.request.urlretrieve(each, filename, None)if __name__ == '__main__':url = "/p/7473449745"get_img(open_url(url))

爬取免费代理ip清单,示例2

# 爬取免费代理ip清单 /import reimport urllib.requestdef open_url(url):req = urllib.request.Request(url)req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36')page = urllib.request.urlopen(req)html = page.read().decode('utf-8')return htmldef get_img(html):p = r'(?:(?:[0,1]?\d?\d|2[0-4]\d|25[0-5])\.){3}(?:[0,1]?\d?\d|2[0-4]\d|25[0-5])'iplist = re.findall(p, html)for each in iplist:print(each)if __name__ == '__main__':url = "/"# open_url(url)get_img(open_url(url))

P62 论9:异常处理

本节内容:

处理URLError(访问网页异常) 见示例1 处理HTTPError,如状态码404 HTTP 状态码大全400-499的异常来自客户端,500-599异常来自服务器示例2 两种常用的写法 示例3

# URLError 处理。示例1import urllib.requestimport urllib.errorreq = urllib.request.Request("") # 随便一个不存在的网址try:urllib.request.urlopen(req)except urllib.error.URLError as e:print(e.reason)

# HTTPError处理,如状态码404.示例2import urllib.requestimport urllib.errorreq = urllib.request.Request("/ooxx.html") # 随便一个不存在的网址try:urllib.request.urlopen(req)except urllib.error.HTTPError as e:print(e.code)print(e.read())# 读取错误页面,可对这个页面可以进行进一步处理

# 处理异常的两种写法,示例3from urllib.request import Request, urlopenfrom urllib.error import URLError, HTTPErrorreq = Request('') # Request(someurl)try:response = urlopen(req)except HTTPError as e:print('The server couldn\'t fulfill the request.')print('Error code:', e.code)except URLError as e:print('We failed to reach a server')print('Reason: ', e.reason)else:pass# everything is fine# 第二种from urllib.request import Request, urlopenfrom urllib.error import URLErrorreq = Request('') # Request(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:pass# everything is fine

P63 论10:安装 scrapy

Scrapy介绍:

Scrapy是用纯Python实现的一个爬取网站数据、提取结构性数据的应用框架。有了框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片。

最初是为了页面抓取所设计的,也可以应用在获取API所返回的数据或者通用的 网络爬虫。

优点:快速、高层次的屏幕抓取和web抓取框架用途:数据挖掘、监测和自动化测试。

python如果安装多个版本并不冲突,他们独立存在

安装Scrapy所需要的前提和步骤

python 大前提,也可以加上pycharme。 pywin32 可提供一个像是PC一样的IDEpip install pywin32pip install lxmlpip install py``OpenSSLpip install Scrapy

P64 论11:scrapy

使用Scrapy抓取一个网站的四个步骤

创建Scrapy项目定义Item容器编写爬虫存储内容

Scrapy框架结构

绿色线条代表数据流

各个组件介绍 Scrapy Engine(引擎):核心部分, 负责各组件之间的通讯。Downloader(下载器):从Scheduler(调度器)获取页面数据,交给Spider处理。Scheduler(调度器):接收从Scrapy Engine(引擎)发过来的请求,并排列整理。Spiders(爬虫):发送需要爬取的链接给Scrapy Engine(引擎),再接收请求回来的数据,通过用户自己编写的程序,去解析数据。Item Pipeline(管道):将Spider(爬虫)传递过来的数据进行存储。Downloader Middlewares(下载器中间件):可以扩展下载器和引擎之间通信功能的中间件。处理Downloaderr发到ScrapyEngine的Responses。Spider Middlewares(Spider中间件):可以扩展引擎和爬虫之间通信功能的中间件。

可参考scrapy框架

练手网站http://www.dmoz-/ 失效,而且像个八年用法有变,以后单独学习scrapy吧,scrapy学习笔记链接如下:

(scrapy待更新…)

🔰GUI(OLD:P64~P77)

P64 GUI的终极选择:Tkinter 1

Tkinter 是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。

由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。

注意:Python3.x 版本使用的库名为 tkinter,即首写字母 T 为小写。import tkinter

——Python GUI 编程(Tkinter) | 菜鸟教程

tkinter测试,示例1

# tkinter测试,示例1import tkinter as tkapp = tk.Tk() # 创建top主窗口,注意大写T、小写kapp.title("FishC.demo") # top主窗口标题theLable = tk.Label(app, text="第二个窗口程序")# 创建第二个窗口, Label 用于显示文本、图标、图片theLable.pack()# 用于自动调节组件自身尺寸、位置app.mainloop()# 窗口主事件循环

把GUI封装成类,示例2

import tkinter as tkclass App:def __init__(self, root):frame = tk.Frame(root) # 创建一个框架frame.pack(side=tk.LEFT, padx=10, pady=10) # 设置左对齐、x轴间距0、y轴间距10# 创建一个按钮组件,text为文本属性,bg为背景色,fg为前景色,command为按钮按下时要执行的命令属性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()# 创建一个top主窗口app = App(root)# 实例化Approot.mainloop()

P65 GUI的终极选择:Tkinter 2

示例1 - 添加图片,

# 添加图片,示例1from tkinter import *root = Tk() # 创建主窗口textLabel = Label( # 创建一个文本Label对象root,# 在root上面显示Labeltext="18🈲,\n请稍候再来!",justify=LEFT, # 设置文字左对齐padx=10)textLabel.pack(side=LEFT)# 设置文字排版photo = PhotoImage(file="18.gif")# 创建一个图像Label对象,(这里只有gif的 可以,不然会报错_tkinter.TclError: couldn't recognize data in image file "")imgLabel = Label(root, image=photo)imgLabel.pack(side=RIGHT) # 设置图片排版mainloop()

示例2 - 图片作为背景,文字显示上面,设置Label的compound就可以,

# 图片作为背景,文字显示上面,设置Label的compound就可以,示例2from tkinter import *root = Tk() # 创建主窗口photo = PhotoImage(file="bg.gif")theLabel = Label( # 创建一个文本Label对象root,# 在root上面显示Labeltext="学 python\n到 FishC!",justify=LEFT, # 设置文字左对齐image=photo, # 图片compound=CENTER, # 文字显示在正上方font=("华康少女字体", 50),fg="black")theLabel.pack()mainloop()

示例3 - Button组件,改变Label文字内容,

'''思路:在原有的基础上,增加一个框架 frame 放置按钮文本的改变,可通过 Label 的 textvariable 属性显示一个变量'''from tkinter import *def callback():var.set("吹吧你,我才不信呢~")root = Tk()frame1 = Frame(root)frame2 = Frame(root)var = StringVar()var.set("您下载的影片含有未成年人限制内容,\n请满18周岁后再点击观看!")textLabel = Label(frame1,textvariable=var,# textvariable 可以显示一个变量justify=LEFT)textLabel.pack(side=LEFT)photo = PhotoImage(file="18.gif")imgLabel = Label(frame1, image=photo)imgLabel.pack(side=RIGHT)theButton = Button(frame2, text="我已满 18 周岁", command=callback)theButton.pack()frame1.pack(padx=10, pady=10)frame2.pack(padx=10, pady=10)mainloop()

小甲鱼在发布的,供参考(付费内容…):Tkinter窗口组件:LabelTkinter窗口组件:MenuTkinter窗口组件:TextTkinter窗口组件:ListboxTkinter窗口组件:ButtonTkinter窗口组件:EntryTkinter窗口组件:CanvasTkinter窗口组件:SpinboxTkinter窗口组件:ToplevelTkinter窗口组件:LabelFrameTkinter窗口组件:PanedWindowTkinter窗口组件:CheckbuttonTkinter窗口组件:FrameTkinter窗口组件:ScrollbarTkinter窗口组件:RadiobuttonTkinter窗口组件:MessageTkinter窗口组件:ScaleTkinter窗口组件:MenubuttonTkinter窗口组件:OptionMenu

P66 GUI的终极选择:Tkinter 3

示例1 - Checkbutton 组件,实现勾选 ,

# Checkbutton 组件,实现勾选 ,示例1from tkinter import *root = Tk()v = IntVar() # Tkinter变量,用于表示该按钮是否被选中c = Checkbutton(root, text="测试一下", variable=v)c.pack()lable = Label(root, textvariable=v)# v用来存放 Checkbutton 的选中状态lable.pack()mainloop()

示例2 - Checkbutton 多选,

# Checkbutton 多选,示例2from tkinter import *root = Tk()GIRLS = ["西施", "貂蝉", "王昭君", "杨玉环"]v = [] # 定义个空列表,存放勾选状态for girl in GIRLS:v.append(IntVar()) # 如果被选中,IntVar() 被赋值为1,否则为0b = Checkbutton(root, text=girl, variable=v[-1])b.pack(anchor=W)# anchor 用于指定显示位置,W=western=左对齐mainloop()

示例3 - Radiobutton 单选按钮。

# Radiobutton 单选按钮。示例3from tkinter import *root = Tk()v = IntVar()Radiobutton(root, text="One", variable=v, value=1).pack(anchor=W) # 通过对比 variable 和value 的值,实现勾选的显示Radiobutton(root, text="Two", variable=v, value=2).pack(anchor=W)Radiobutton(root, text="Three", variable=v, value=3).pack(anchor=W)mainloop()

示例4 - Radiobutton 单选按钮,用循环实现。

# Radiobutton 单选按钮,用循环实现。示例4from tkinter import *root = Tk()LANGS = [("Python", 1),("Perl", 2),("Ruby", 3),("Lua", 4)]v = IntVar()v.set(1) # 设置默认值1for lang, num in LANGS:# b = Radiobutton(root, text=lang, variable=v, value=num)# b.pack(anchor=W)b = Radiobutton(root, text=lang, variable=v, value=num, indicatoron=False) # indicatoron=False 将显示为文字按钮效果b.pack(fill=X)# X = 横向填充mainloop()

示例5 - 用 LabelFrame 实现组件分组。

from tkinter import *root = Tk()group = LabelFrame(root, text="最好的脚本语言是?", padx=5, pady=5)group.pack(padx=10, pady=10)LANGS = [("Python", 1),("Perl", 2),("Ruby", 3),("Lua", 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()

P67 GUI的终极选择:Tkinter 4

输入框组件

示例1 - 输入框 Entry 组件,增加、删除。

增加、删除,用insert、delete。如示例1获取输入框内容: 用 组件的get()用 变量value的 get() grid 以表格形式管理组件。如示例2

# 输入框 Entry 组件,增加、删除。示例1from tkinter import *root = Tk()e = Entry(root)e.pack(padx=20, pady=20)e.delete(0, END)# 清空输入框e.insert(0, "默认文本...") # 设置输入内容mainloop()

示例2 - 获取输入框内容。

# 获取输入框内容。示例2from tkinter import *root = Tk() # 创建主窗口Label(root, text="作品:", padx=20, pady=10).grid(row=0, column=0) # grid(row=0, column=0)表示第0行第0列Label(root, text="小甲鱼:").grid(row=1, column=0) # 第1行第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 button1_show():print("作品:《%s》" % e1.get())print("作者:%s" % e2.get())Button(root, text="获取信息", command=button1_show)\.grid(row=2, column=0, sticky=W, padx=10, pady=10) # sticky=W 表示位置在西(左)Button(root, text="退出", command=root.quit)\.grid(row=2, column=1, sticky=E, padx=10)mainloop()

示例3 - 账号密码输入,获取。

# 账号密码输入,获取。示例3from tkinter import *root = Tk()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="芝麻开门", command=show)\.grid(row=2, column=0, sticky=W, padx=10, pady=5)Button(root, text="退出", command=root.quit)\.grid(row=2, column=1, sticky=E, padx=10)mainloop()

示例4 - 输入验证。

启用验证开关:validate选项

验证函数:validatecommand,返回True或False。通过Entry组件的 get() 方法获得该验证字符串

# 输入验证。示例4# 在第一个输入框输入,并通过tab键将焦点转移到第二个输入框时,验证功能被触发from tkinter import *master = Tk()def test():if e1.get() == "小甲鱼":print("正确!")return Trueelse:print("错误!")e1.delete(0, END) # 清空输入框return Falsev = StringVar()e1 = Entry(master, textvariable=v, validate="focusout", validatecommand=test) # validate="focusout"表示焦点移出时,validatecommand=test自动触发验证函数e2 = Entry(master)e1.pack(padx=10, pady=10)e2.pack(padx=10, pady=10)mainloop()

示例5 - invalidcommand函数。

invalidcommand函数只有在validatecommand的返回值 为False时才被调用

# invalidcommand函数。示例5from tkinter import *master = Tk()v = StringVar()def test():if e1.get() == "小甲鱼":print("正确!")return Trueelse:print("错误!")e1.delete(0, END)return Falsedef test2():print("我被调用了...")e1 = Entry(master, textvariable=v, validate="focusout",\validatecommand=test, invalidcommand=test2)e2 = Entry(master)e1.pack(padx=10, pady=10)e2.pack(padx=10, pady=10)mainloop()

示例6 - validatecommand的其他参数。

validatecommand的参数 %P 当输入框的值允许改变的时候,该值有效;该值为输入框的最新文本内容%v 该组件当前的 validata 选项的值%W 该组件的名称

# validatecommand的其他参数。示例6from tkinter import *master = Tk()v = StringVar()def test(content, reason, name):if content == "小甲鱼":print("正确!")print(content, reason, name)return Trueelse:print("错误!")print(content, reason, name)return FalsetestCMD = master.register(test)e1 = Entry(master, textvariable=v, validate="focusout",\validatecommand=(testCMD, '%P', '%v', '%W'))e2 = Entry(master)e1.pack(padx=10, pady=10)e2.pack(padx=10, pady=10)mainloop()

示例7 - 计算器。

validate选项指定为“key"的时候,有任何输入操作都会被拦截去验证,如果返回True,才会给关联的变量textvariable赋值

state: Entry可以设置的状态:NORMAL,DISABLED(禁用选中、拷贝、修改)或"readonly"(支持选中和拷贝,不能修改)默认值时NORMAL如果值为DISABLED或"readonly",那么调用 insert() 和 delete() 都会被忽略

# 计算器。示例7from tkinter import *root = Tk()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) # state="readonly" = 只读模式,v3的数据赋值给textvariable进行输出显示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()

P68 GUI的终极选择:Tkinter 5

Listbox组件

列表框+滚动条 = 支持大量选项的情况下

示例1 - Listbox简单示例,添加、删除。

添加 .insert()删除 .delete()selectmode选项的四种选择模式 SINGLE 单选BROWSE 单选,通过鼠标拖动或方向键MULTIPLE 多选EXTENDED 多选,但需同时按住Shift或Ctrl

# Listbox简单示例,添加、删除。示例1from tkinter import *master = Tk()#创建主窗口theLB = Listbox(master, setgrid=True, selectmode=SINGLE)theLB.pack()# 添加,基础方法# theLB.insert(0, '你是猪')# 0 表示第一个位置# theLB.insert(END, '小甲鱼不是猪') # END 表示最后一个位置# 添加,循环添加for item in ["鸡蛋", "鸭蛋", "鹅蛋", "李狗蛋"]:theLB.insert(END, item)# END表示列表中每一项的最后位置# 删除,基础方法# theLB.delete(0, END) # 删除所有项目,两个参数分别是起始位置、结束位置# theLB.delete(2) # 删除指定# 删除,通过按钮删除theButton = Button(master, text="删除它", command=lambda x=theLB:x.delete(ACTIVE)) # ACTIVE表示当前选中的数据theButton.pack() # ↑ lambda表达式mainloop()

示例2 - height 选项控制行数。

# height 选项控制行数。示例2from tkinter import *root = Tk()theLB = Listbox(root, setgrid=True, selectmode=BROWSE, height=11) # height=11 显示11行theLB.pack()for item in range(11):theLB.insert(END, item)theButton = Button(root, text="删除", command=lambda x=theLB: x.delete(ACTIVE))theButton.pack()mainloop()

示例3 - 滚动条 Scrollbar组件。

在组件上安装垂直滚动条: 设置该组件的yscrollbarcommand选项为Scrollbar组件的set()方法设置Scrallbar组建的command选项为该组件的yview()方法,才能将滚动条与列表相链接

# 滚动条 Scrollbar组件。示例3from tkinter import *root = Tk()sb = Scrollbar(root)sb.pack(side=RIGHT, fill=Y)# 右边,填充整个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)# yview 是Listbox的一个默认方法,能自动跟随垂直滚动mainloop()

示例4 - 滑块 Scale组件。

Scale组件是; 通过滑块来表示某个范围内的值通过Scale(root, from_=0, to=100),显示范围通过get方法,获取滑块当前位置

# 滑块 Scale组件。示例4from tkinter import *root = Tk()Scale(root, from_=0, to=42).pack() # from_=0, to=42 表示范围Scale(root, from_=0, to=200, orient=HORIZONTAL).pack() # orient=HORIZONTAL水平显示mainloop()

示例5 - 通过get方法,获取滑块当前位置。

# 通过get方法,获取滑块当前位置。示例5from tkinter import *root = Tk()s1 = Scale(root, from_=0, to=42)s1.pack()s2 = Scale(root, from_=0, to=200, orient=HORIZONTAL)s2.pack()def show():print(s1.get(), s2.get())Button(root, text="获取位置", command=show).pack()mainloop()

示例6 - 设置精度和刻度。

通过 resolution 选项,控制精度(步长)通过 tickinterval 选项,设置刻度

# 设置精度和刻度。示例6from tkinter import *root = Tk()# tickinterval=5 最小刻度是5;resolution=5 每个5个数值,走一步;length=200 设置滚动条长度Scale(root, from_=0, to=42, tickinterval=5, length=200, resolution=5, orient=VERTICAL).pack() #创建铅锤方向滚动条Scale(root,from_=0, to=200, tickinterval=10, length=600, orient=HORIZONTAL).pack()mainloop()

P69 GUI的终极选择:Tkinter 6

示例1 - Text组件简单示例

Text组件 Text(文本) 作用:用于显示和处理多行文本常也用于作为简单的文本编辑器和网页浏览器使用

# Text组件简单示例 示例1from tkinter import *root = Tk()text = Text(root, width=30, height=2) # width=30 30个字符平均宽度;height=2 两行text.pack()text.insert(INSERT, "I love\n") # INSERT索引值,表示输入光标所在位置text.insert(END, "!")# END索引值,表示在文本末尾插入内容mainloop()

示例2 - 插入Windows组件

# 插入Windows组件 示例2from tkinter import *root = Tk()def show():print("哟,我被点了一下~")text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love\n")text.insert(END, "!")b1 = Button(text, text="点我点我", command=show) # Button(父组件, , ...)text.window_create(INSERT, window=b1)mainloop()

示例3 - 插入image对象

# 插入image对象 示例3from tkinter import *root = Tk()text = Text(root, width=80, height=30)text.pack()photo = PhotoImage(file='fishc.gif')def show():text.image_create(INSERT, image=photo)b1 = Button(root, text="点我点我", command=show)text.window_create(INSERT, window=b1)mainloop()

Indexer用法 lin.column 最基础的索引方式将行列号以字符串形式表示,如“1.0”行号以 1 开始,列号以 0 开始 lin.end 表示该行最后一个字符的位置用法如:text.get(1.2, 1.end) INSERT 光标位置 CURRENT 与鼠标坐标最接近的位置 END Text 组件最后一个字符的下一个位置

# line.column 示例4from tkinter import *root = Tk()text = Text(root, width=30, height=30)text.pack()text.insert(INSERT, "I love !")print(text.get(1.2, 1.12))print(text.get("1.2", "1.end"))mainloop()

示例5 - Marks用法。

Marks用法

嵌入到Text组件中的不可见对象指定字符间的位置,并跟随相应的字符一起移动。用法如:text.mark_set(“here”, “1.2”) text.insert(“here”, “插入”)mark能记住它后面是谁,下次插入找到后面那个往前插;通过mark_gravity()可以实现找到后面那个往后插

# Marks用法。示例5from tkinter import *root = Tk()text = Text(root, width=30, height=30)text.pack()text.insert(INSERT, "I love !") # 光标当前的位置插入text.mark_set("here", "1.2") # 设置光标位置为1.2text.insert("here", "插1")text.insert("here", "插2")# Mark的位置会跟随移动text.insert("here", "入") # Mark的位置也会跟着移动# text.delete("1.0", END)# text.insert("here", "插3") # 如果Mark周围的文本被删除了,Mark仍然存在.默认插在1.0的位置# text.mark_unset("here") # mark_unset()方法可以解除Mark,解除后再插入将报错# text.insert("here", "插4") # here表示当前Mark的位置text.mark_gravity("here", LEFT) # 插入内容到Mark的左侧,而不是mark后面内容的左侧text.insert("here", "插5")text.insert("here", "入")mainloop()

P70 GUI的终极选择:Tkinter 7

Tags 用法

作用: 改变Text组件中的内容样式和功能,如:修改文本字体、尺寸、颜色将文本、嵌入的组件、图片与键盘鼠标等事件相关联 类型: user-defined tags 用户自定义TagsSEL 预定义的特殊Tag SEL 用于表示对应的选中内容 定义 用户可自定义任意数量的Tags任何文本内容都支持多个Tags描述任何Tag 也可用于描述多个不同的文本内容 用法 添加标签 text.tag_add() 设置标签 text.tag_config() 注意 如果对同一个范围的文本内容添加了多个相同的tags,那么,旧的tag样式会被覆盖。但是可通过tag_raise()、tag_lower()改变tag的优先级

示例1 - 为文本添加、设置 Tags

# 为文本添加、设置 Tags 示例1from tkinter import *root = Tk()text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love !")text.tag_add("tag1", "1.7", "1.12", "1.14") # "1.7" 第一行第八列text.tag_config("tag1", background="yellow", foreground="red")mainloop()''''''# Tags被覆盖,演示from tkinter import *root = Tk()text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love !")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="yellow", foreground="red")text.tag_config("tag2", background="blue")# text.tag_lower("tag2") # 降低tag2的优先级mainloop()'''

示例2 - Tags事件绑定

# Tags事件绑定 示例2from tkinter import *import webbrowser # 网页模块root = Tk()text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love !")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):webbrowser.open("")text.tag_bind("link", "<Enter>", show_arrow_cursor) # 绑定事件。 "<Enter>" 当鼠标进入。show_hand_cursor 调用的函数text.tag_bind("link", "<Leave>", show_xterm_cursor)text.tag_bind("link", "<Button-1>", click) # 当触发鼠标“左键单击”时,使用默认浏览器打开鱼C网址mainloop()

示例3 - 检查内容是否发生改变

获取md5,对比摘要

# 检查内容是否发生改变 示例3from tkinter import *import hashlibroot = Tk()text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love !")contents = text.get(1.0, END) # 获取文本内容def getSig(contents):m = hashlib.md5(contents.encode()) # 获取md5的值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()

示例4 - 查找

查找 search() 搜索Text组件中的内容 只能返回第一个匹配的位置,如果要全文搜索 加循环即可

# 查找 示例4from tkinter import *root = Tk()text = Text(root, width=30, height=5)text.pack()text.insert(INSERT, "I love !")def getIndex(text, index):# index可将任何支持的格式转化为元组返回return tuple(map(int, str.split(text.index(index), ".")))start = 1.0while True:pos = text.search("o", start, stopindex=END)if not pos:breakprint("找到了,位置是:", getIndex(text, pos))start = pos + "+1c" # 将start指向找到的字符位置的下一个字符,以便进行下一次搜索mainloop()

示例5 - 撤销

撤销删除文本的操作

首先要将Text()方法中写入 undo=True输入文本就是入栈,“撤销”就是一次弹栈,“恢复”就是再次入栈。

自定义撤销的长度

默认的长度是:”焦点切换“、”按下Enter“、删除等操作代表的一次完整操作自定义 先将将Text()方法中写入 autoseparators=False

# 撤销 示例5from tkinter import *root = Tk()text = Text(root, width=30, height=5, undo=True)text.pack()text.insert(INSERT, "I love ")def show():text.edit_undo()Button(root, text="撤销", command=show).pack()mainloop()'''# 每次撤销一个字符from tkinter import *root = Tk()text = Text(root, width=30, height=5, undo=True, autoseparators=False)text.pack()text.insert(INSERT, "I love ")def callback(event):text.edit_separator()text.bind('<Key>', callback) # 每次输入就插入一个分隔符def show():text.edit_undo()Button(root, text="撤销", command=show).pack()mainloop()'''

P71 GUI的终极选择:Tkinter 8

Canvas(画布)组件

用于显示和编辑图形 可 绘制直线、图形、多边形

示例1 - 开始绘制

开始绘制

直线 create_line(x0, y0, x1, y1)矩形 create_rectangle(x0, y0, x1, y1)

# 开始绘制 示例1from tkinter import *root = Tk()w = Canvas(root, width=200, height=100)# 创建canvas对象w.pack()w.create_line(0, 50, 200, 50, fill="yellow")# 黄色实线w.create_line(100, 0, 100, 100, fill="red", dash=(4, 4)) # 红色虚线w.create_rectangle(50, 25, 150, 75, fill="blue") # 蓝色矩形mainloop()

示例2 - 修改图形

修改图像的方法:

.coords(移动对象,x0, y0, x1, y1) 移动到新的位置.itemconfig(对象, 选项样式, …) 设置样式.move.delete(对象)

# 修改图形 示例2from tkinter import *root = Tk()w = Canvas(root, width=200, height=100)# 创建canvas对象w.pack()line1 = w.create_line(0, 50, 200, 50, fill="yellow")# 黄色实线line2 = w.create_line(100, 0, 100, 100, fill="red", dash=(4, 4)) # 红色虚线rect1 = w.create_rectangle(50, 25, 150, 75, fill="blue") # 蓝色矩形w.coords(line1, 0, 25, 200, 25)# 将line1移动到新的位置w.itemconfig(rect1, fill="red")# 设置矩形填充色红色w.delete(line2) # 删除line2Button(root, text="删除全部", command=(lambda x=ALL: w.delete(x))).pack() # 按钮,删除所有图形;ALL表示画布所有对象mainloop()

示例3 - 在 Canvas 上显示文本

显示文本

create_text(x0, y0, text="")

# 在 Canvas 上显示文本 示例3from tkinter import *root = Tk()w = Canvas(root, width=200, height=100)# 创建canvas对象w.pack()line1 = w.create_line(0, 0, 200, 100, fill="green", width=3) # 绿色的斜线line2 = w.create_line(200, 0, 0, 100, fill="green", width=3) # 色的斜线rect1 = w.create_rectangle(40, 20, 160, 80, fill="blue") # 蓝色矩形rect2 = w.create_rectangle(60, 35, 145, 65, fill="yellow")# 蓝色矩形w.create_text(100, 50, text="FishC")mainloop()

示例4 - 绘制矩形、圆与椭圆

绘制矩形

.create_rectangle

绘制椭圆.create_oval 在同尺寸的矩形下的椭圆

绘制圆形 特殊椭圆法 将限定矩形改为正方形

# 绘制矩形、圆与椭圆 示例4from tkinter import *root = Tk()w = Canvas(root,width=200,height=100,background="white")w.pack()w.create_rectangle(40, 20, 160, 80, dash=(4, 4)) # 虚线的矩形w.create_oval(40, 20, 160, 80, fill="pink") # 椭圆,粉色填充w.create_oval(70, 20, 130, 80, fill="black") # 圆形mainloop()

示例5 - 多边形-五角星

绘制多边形

create_polygon

# 多边形-五角星 示例5from tkinter import *import math as mroot = Tk()w = Canvas(root, width=200, height=150, background="red")w.pack()center_x = 100center_y = 80r = 70points = [# 左上点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="green", fill="yellow")mainloop()

P72 GUI的终极选择:Tkinter 9

Canvas实现画板

利用超小圆形代笔一个画笔的点

from tkinter import *root = Tk()w = Canvas(root, width=500, height=800, background="white")w.pack()def paint(event):x1, y1 = (event.x - 1), (event.y - 1)x2, y2 = (event.x + 5), (event.y + 5)w.create_oval(x1, y1, x2, y2, fill="red")w.bind("<B1-Motion>", paint) # 画布与鼠标左键绑定paint方法Label(root, text="按住鼠标左键并移动,开始绘制你的理想蓝图吧......").pack(side=BOTTOM)mainloop()

Canvas组件支持对象

arc 弧形、弦、扇形bitmap 内建的位图文件或XBM格式文件image BitmapImage、PhotoImage 的实例对象line 线oval 圆形、椭圆polygon 多边形rectangle 矩形text 文本windows 组件

样式

轮廓线填充颜色 fill = “”

坐标系

窗口坐标系: 以窗口左上角为坐标原点画布坐标系: 以画布左上角为坐标原点转换 canvasx()canvasy()

显示顺序

可以移动到顶部或底部

指定画布对象

Iteam handles: 指定画布对象的整型数字,如IDTags: 标签ALL: 所有画布对象CURRENT: 鼠标指针下的画布对象

P73 GUI的终极选择:Tkinter 10

示例1 - 添加菜单

创建菜单用 Menu 组件

功能:

现顶级菜单、下拉菜单、弹出菜单

添加组件.add().add_command(label="", command= )

# 添加菜单 示例1from tkinter import *root = Tk()def callback():print("你好~")menubar = Menu(root)# 创建菜单menubar.add_command(label="hello", command=callback) # 创建菜单对象menubar.add_command(label="quit", command=root.quit)root.config(menu=menubar) # (必须)将菜单与窗口关联,不然不显示mainloop()

示例2 - 创建一组菜单

# 创建一组菜单 示例2from tkinter import *root = Tk()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=root.quit)menubar.add_cascade(label="文件", menu=filemenu)# 级联一级菜单,下级菜单是 filemenueditmenu = Menu(menubar, tearoff=False)editmenu.add_command(label="剪切", command=callback)editmenu.add_command(label="拷贝", command=callback)editmenu.add_command(label="粘贴", command=callback)menubar.add_cascade(label="编辑", menu=editmenu)# 级联一级菜单,下级菜单是 editmenuroot.config(menu=menubar)mainloop()

示例3 - 创建右键弹出菜单

# 创建右键弹出菜单 示例3from tkinter import *root = Tk()def callback():print("你好~")def popup(event):menu.post(event.x_root, event.y_root) # 在指定位置弹出菜单menu = Menu(root, tearoff=False)# 绑定 root, tearoff=True能将菜单放到新窗口menu.add_command(label="撤销", command=callback)menu.add_command(label="重做", command=callback)frame = Frame(root, width=512, height=512)# 创建一个框架frame.pack()frame.bind("<Button-3>", popup) # 绑定 popup,<Button-3> 是鼠标中间键mainloop()

示例4 - 带有按钮的菜单

菜单中可添加单选、多选按钮radiobutton checkbutton

# 带有按钮的菜单 示例4from tkinter import *root = Tk()def callback():print("你好~")menubar = Menu(root)openVar = IntVar()# 存放按钮当前的状态saveVar = IntVar()exitVar = IntVar()filemenu = Menu(menubar, tearoff=False)filemenu.add_checkbutton(label="打开", command=callback, variable=openVar)# 创建一个下拉菜单对象filemenu.add_checkbutton(label="保存", command=callback, variable=saveVar)filemenu.add_separator() # 插入分隔线filemenu.add_checkbutton(label="退出", command=root.quit, variable=exitVar)menubar.add_cascade(label="文件", menu=filemenu)# 级联一级菜单,下级菜单是 filemenueditVar = IntVar()editmenu = Menu(menubar, tearoff=False)editmenu.add_radiobutton(label="剪切", command=callback, variable=editVar, value=1)editmenu.add_radiobutton(label="拷贝", command=callback, variable=editVar, value=2)editmenu.add_radiobutton(label="粘贴", command=callback, variable=editVar, value=3)menubar.add_cascade(label="编辑", menu=editmenu)# 级联一级菜单,下级菜单是 editmenuroot.config(menu=menubar)mainloop()

示例5 - Menubutton

Menubutton 组件

button可以出现在任何位置,点开是一个menu

# Menubutton 示例5from tkinter import *root = Tk()def callback():print("你好~")mb = Menubutton(root, text="点我", relief=RAISED)mb.pack()filemenu = Menu(mb, tearoff=False)filemenu.add_command(label="打开", command=callback)# 创建一个下拉菜单对象filemenu.add_command(label="保存", command=callback)filemenu.add_separator() # 插入分隔线filemenu.add_command(label="退出", command=root.quit)mb.config(menu=filemenu)mainloop()

# OptionMenu 菜单中的选项 示例6from tkinter import *root = Tk()def callback():print("你好~")variable = StringVar()# 字符串变量variablevariable.set("one") # 初始值为"one"w = OptionMenu(root, variable, "one", "two", "three")w.pack()mainloop()

示例7 - OptionMenu菜单 中 添加列表

# OptionMenu菜单 中 添加列表 示例7from tkinter import *root = Tk()OPTIONS = ["1","2","3","4"]def callback():print("你好~")variable = StringVar()# 字符串变量variablevariable.set("one") # 初始值为"one"w = OptionMenu(root, variable, *OPTIONS) # * 用来解包,将列表内容变为一个个单独的数据w.pack()mainloop()

P74 GUI的终极选择:Tkinter 11

示例1 - 事件绑定简单示例 - 获取鼠标左键点击相对坐标

事件绑定

创建一个frame框架,在框架中响应事件如: 左边是事件本身、右边是事件描述。Button 代表鼠标点击事件、1 代表鼠标左键(2为中间键,3为右键)按键响应

# 事件绑定简单示例 - 获取鼠标左键点击相对坐标 - 示例1from tkinter import *root = Tk()def callback(event):print("点击位置:", event.x, event.y)frame = Frame(root, width=200, height=200)frame.bind("<Button-1>", callback) # <Button-1> 左边是事件本身、右边是事件描述;绑定callback方法frame.pack()mainloop()

示例2 - 响应键盘事件-获取键盘输入

必须先获得焦点,才能响应键盘。用.focus_set()

from tkinter import *root = Tk()def callback(event):print(event.char)frame = Frame(root, width=200, height=200)frame.bind("<Key>", callback) # 绑定callback方法frame.focus_set()frame.pack()mainloop()

示例3 - 响应鼠标事件-获取鼠标实时位置

当鼠标进入组件中,触发事件响应

# 响应鼠标事件-获取鼠标实时位置-示例3from tkinter import *root = Tk()def callback(event):print("当前位置:", event.x, event.y)frame = Frame(root, width=200, height=200)frame.bind("<Motion>", callback) # 绑定callback方法frame.focus_set()frame.pack()mainloop()

P75 GUI的终极选择:Tkinter 12

示例1 - Message 组件

Message 组件

功能: 用于显示多行文本能够自动换行,并调整文本的尺寸

# Message 组件 - 示例1from tkinter import *root = Tk()w1 = Message(root, text="这是一则消息", width=100)w1.pack()w2 = Message(root, text="这是一条骇人听闻的长~~~~~~~~~~~~~~~~~消息!", width=100)w2.pack()mainloop()

示例2 - Spinbox 组件

Spinbox 组件

功能: 限定用户输入的内容

# Spinbox 组件 - 示例2from tkinter import *root = Tk()w = Spinbox(root, from_=0, to=10, increment=0.5) # 限定输入为0-10,increment=0.5 精度为0.5# w = Spinbox(root, value=("a", "b", "3")) w.pack()mainloop()

示例3 - PanedWindow 组件 - 二窗格、三窗格

PanedWindow 组件

功能: 空间管理,为子组件提供一个框架

# PanedWindow 组件 - 二窗格、三窗格 - 示例3from tkinter import *root = Tk()m = PanedWindow(orient=VERTICAL) # orient=VERTICAL 设置为上下分布m.pack(fill=BOTH, expand=1) # 设置为框架覆盖全局top = Label(m, text="top pane") # 顶窗格m.add(top)bottom = Label(m, text="bottom pane") # 底窗格m.add(bottom)mainloop()'''# 三窗格from tkinter import *root = Tk()m1 = PanedWindow() m1.pack(fill=BOTH, expand=1)left = Label(m1, text="left pane")# 左窗格m1.add(left)m2 = PanedWindow(orient=VERTICAL)m1.add(m2)top = Label(m2, text="top pane") # 顶窗格m2.add(top)bottom = Label(m2, text="bottom pane") # 底窗格m2.add(bottom)mainloop()''''''# 显示线条边界from tkinter import *root = Tk()m1 = PanedWindow(showhandle=True, sashrelief=SUNKEN) # showhandle=True 显示手柄;sashrelief=SUNKEN 样式为向下凹m1.pack(fill=BOTH, expand=1)left = Label(m1, text="left pane")# 左窗格m1.add(left)m2 = PanedWindow(orient=VERTICAL, showhandle=True, sashrelief=SUNKEN)m1.add(m2)top = Label(m2, text="top pane") # 顶窗格m2.add(top)bottom = Label(m2, text="bottom pane") # 底窗格m2.add(bottom)mainloop()'''

示例4 - Toplevel 组件

Toplevel 组件

独立的顶级窗口,通常拥有标题栏、边框等部件功能:

显示额外的窗口、对话框和其他弹出窗口

# Toplevel 组件 - 示例4from tkinter import *root = Tk()def create():top = Toplevel()top.title("FishC Demo")msg = Message(top, text="I love ", width=100)msg.pack()Button(root, text="创建顶级窗口", command=create).pack()mainloop()'''# 设置透明度from tkinter import *root = Tk()def create():top = Toplevel()top.title("FishC Demo")top.attributes("-alpha", 0.8)# 设置为80%透明度msg = Message(top, text="I love ", width=100)msg.pack()Button(root, text="创建顶级窗口", command=create).pack()mainloop()'''

P76 GUI的终极选择:Tkinter 13

布局管理器

管理组件如何排列

三大布局管理器

pack
按照添加顺序排列(默认纵向排列)简单;适用于少量的组件
grid
按照行列行hi排列最灵活、最重要可实现用很多个框架和pack搭建起来的效果使用grid排列组件,只需告诉它你想要将组件放置的位置(行row/列column)。
place
允许程序员指定组件的大小、位置

注意:

pack 和 grid 不能混合使用

示例1 - pack

# pack - 示例1from tkinter import *root = Tk()listbox = Listbox(root)listbox.pack(fill=BOTH, expand=True) # fill=BOTH 紧挨着父组件;expand=True 拉伸时跟随填充for i in range(10):listbox.insert(END, str(i))mainloop()

示例2 - pack - 纵向排列 fill=X

# pack - 纵向排列 fill=X - 示例2from tkinter import *root = Tk()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)mainloop()

示例3 - pack - 横向排列 side=LEFT

# pack - 横向排列 side=LEFT - 示例3from tkinter import *root = Tk()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()

示例4 - grid - 登录页面示例

# grid - 登录页面示例 - 示例4from tkinter import *root = Tk()Label(root, text="用户名").grid(row=0, sticky=W) # sticky=W 左对齐Label(root, text="密码").grid(row=1, sticky=W)Entry(root).grid(row=0, column=1)Entry(root, show="*").grid(row=1, column=1)mainloop()

示例5 - grid - 跨行、跨列

# grid - 跨行、跨列 - 示例5from tkinter import *root = Tk()Label(root, text="用户名").grid(row=0, sticky=W) # sticky=W 左对齐Label(root, text="密码").grid(row=1, sticky=W)Entry(root).grid(row=0, column=1)Entry(root, show="*").grid(row=1, column=1)photo = PhotoImage(file="18.gif") # 插入Label图像Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx=5, pady=5) # rowspan=2 跨两行;padx=5, pady=5 边距Button(text="提交", width=10).grid(row=2, columnspan=3, pady=5)mainloop()

示例6 - place - 将子组件显示在父组件的正中间

# place - 将子组件显示在父组件的正中间 - 示例6from tkinter import *root = Tk()def callback():print("正中靶心")Button(root, text="点我", command=callback).place(relx=0.5, rely=0.5, anchor=CENTER)# relx=0.5, rely=0.5 相对父组件的位置(0.5表示正中间,1表示最右边,0表示最左边);# anchor=CENTER 表示居中显示mainloop()

示例7 - place - 图像中显示label

# place - 图像中显示label - 示例7 from tkinter import *root = Tk()def callback():print("正中靶心")photo = PhotoImage(file="logo_big.gif")Label(root,image=photo).pack()Button(root, text="点我", command=callback).place(relx=0.5, rely=0.5, anchor=CENTER)mainloop()

示例8 - place - relheigh、relwidth 相对高度,相对宽度

# place - relheigh、relwidth 相对高度,相对宽度 - 示例8from tkinter import *root = Tk()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="green").place(relx=0.5, rely=0.5, relheight=0.25, relwidth=0.25, anchor=CENTER)mainloop()

P77 GUI的终极选择:Tkinter 14

示例1 - messagebox.askokcancel 消息对话框

messagebox.askokcancel(title, message, options)

title 设置标题栏文本message 设置对话框主要文本内容,可使用\noptions
defaulticonparent

返回值:

ture: 用户按下了 yesfalse: 用户按下了 no

# messagebox.askokcancel 消息对话框 示例1from tkinter import *from tkinter import messageboxmessagebox.askokcancel("FishC Demo", "发射核弹?")mainloop()

示例2 - 文件对话框

filedialog.askopenfilename() 打开文件

参数:

defaultextension 指定文件名后缀filetypes 指定筛选文件类型的下拉菜单选项initialdir 指定打开/保存文件的默认路径parenttitle

返回值:返回文件完整路径: 用户选择了文件空字符串: 用户点击了取消

filedialog.asksavefilename() 保存文件

# 文件对话框 示例2from tkinter import *from tkinter import filedialogroot = Tk()def callback():# fileName = filedialog.askopenfilename(defaultextension=".gif")fileName = filedialog.askopenfilename(filetypes=[("GIF", ".gif"), ("Python", ".py")])print(fileName)Button(root, text="打开文件", command=callback).pack()mainloop()

示例3 - colorchooser 颜色选择对话框

colorchooser 颜色选择对话框

提供了让用户选择需要的颜色

返回值,

用户选择颜色:返回一个二元组:(RGB, 十六进制)用户点取消:(None, None)

# colorchooser 颜色选择对话框from tkinter import *from tkinter import colorchooserroot = Tk()def callback():fileName = colorchooser.askcolor()print(fileName)Button(root, text="选择颜色", command=callback).pack()mainloop()

🔰pygame(OLD:P79~P97)

P79 Pygame:初次见面,请大家多多关照

pygame官网: / 安装 pip install pygame检测时候安装成功:

import pygame

print(pygame.ver) 功能 绘制图形显示图片动画效果键鼠交互声音特效碰撞检测

示例1 - 小甲鱼到处跑

# 小甲鱼到处跑 示例import pygameimport sys# 初始化Pygame模块pygame.init()size = width, height = 900, 600speed = [-2, 1]bg = (255, 255, 255)# 创建指定大小的窗口screen = pygame.display.set_mode(size) # 返回surface对象# 设置窗口标题pygame.display.set_caption("初次见面,请大家多多关照!")# 加载图片turtle = pygame.image.load(r"image/turtle.png")# pygame支持多种图片格式;返回surface对象# 获得图像的位置矩形position = turtle.get_rect()while True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()# 移动图像position = position.move(speed)if position.left < 0 or position.right > width:# 翻转图像turtle = pygame.transform.flip(turtle, True, False)# 反方向移动speed[0] = -speed[0]if position.top < 0 or position.bottom > height:speed[1] = -speed[1]# 填充背景screen.fill(bg)# 更新图像screen.blit(turtle, position)# 更新界面pygame.display.flip()# 延迟10毫秒pygame.time.delay(10)

P80 Pygame:解惑

surface对象 用来表示图像的对象 将一个图像绘制到另一个图像上 原理是移动图片上的像素颜色 图像移动 例如 小甲鱼跑来跑去实现方法: 获取图像位置的矩形范围position = turtle.get_rect()调用move方法,修改矩形范围的位置position = position.move(speed)填充白色背景screen.fill(bg)重新填充新的位置的图像screen.blit(turtle, position)更新页面pygame.display.flip()帧率设置 可以达到演示效果帧率不高于200帧

clock = pygame.time.Clock() # 实例化clock对象

clock.tick(200)帮助文档 /docs

示例1

import pygameimport syspygame.init()size = width, height = 600, 400screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")f = open("record.txt", 'w')while True:for event in pygame.event.get():f.write(str(event) + '\n')if event.type == pygame.QUIT:f.close()sys.exit()

P81 Pygame:事件

示例 - 将产生的事件记录保存在文件中

1将产生的事件记录保存在文件中

import pygameimport syspygame.init()size = width, height = 600, 400screen = pygame.display.set_mode(size)pygame.display.set_caption("初次见面,请大家多多关照!")f = open("record.txt", 'w')while True:for event in pygame.event.get():f.write(str(event) + '\n')if event.type == pygame.QUIT:f.close()sys.exit()

示例 - 将产生的事件显示在窗口内

原理:

由于pycharme不能直接显示文字

因此,先将文字渲染成图片,在以图片形式显示,并不断刷新

pagame事件对照表如图:

import pygameimport syspygame.init()size = width, height = 600, 800bg = (0, 0, 0)screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")event_texts = []# 要在Pygame中使用文本,必须创建Font对象# 第一个参数指定字体,第二个参数指定字体的尺寸font = pygame.font.Font(None, 20) # 实例化font对象# 调用get_linesize()方法获得每行文本的高度line_height = font.get_linesize()position = 0screen.fill(bg)while True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()# render()方法将文本渲染成Surface对象# 第一个参数是待渲染的文本# 第二个参数指定是否消除锯齿# 第三个参数指定文本的颜色screen.blit(font.render(str(event), True, (0, 255, 0)), (0, position))position += line_heightif position > height:# 满屏时清屏position = 0screen.fill(bg)pygame.display.flip()

示例 - 方向键控制小乌龟

方向键控制小乌龟

按键对照表 /docs/ref/key.html

import pygameimport sysfrom pygame.locals import *# 将 pygame 的所有常量名导入# 初始化Pygamepygame.init()size = width, height = 600, 400bg = (255, 255, 255)speed = [0, 0]clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("初次见面,请大家多多关照!")turtle = pygame.image.load(r"image/turtle.png")position = turtle.get_rect()# 指定龟头的左右朝向l_head = turtler_head = pygame.transform.flip(turtle, True, False)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == KEYDOWN:if event.key == K_LEFT:# 按下键盘左键speed = [-1, 0]turtle = l_headif event.key == K_RIGHT: # 按下键盘右键speed = [1, 0]turtle = r_headif event.key == K_UP: # 按下键盘上键speed = [0, -1]if event.key == K_DOWN:# 按下键盘下键speed = [0, 1]position = position.move(speed)if position.left < 0 or position.right > width:# 翻转图像turtle = pygame.transform.flip(turtle, True, False)# 反方向移动speed[0] = -speed[0]if position.top < 0 or position.bottom > height:speed[1] = -speed[1]screen.fill(bg)screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

P82 Pygame:提高游戏颜值1

示例 - 界面设置

界面设置

set_mode(resolution=(0,0),flags=0,depth=0) -> Surface

resolution参数:设置界面大小;flags此参数:扩展选项FULLSCREEN:全屏,需要关联退出全屏的快捷键!DOUBLEBUF:双缓冲HWSURFACCE:硬件加速支持,仅在犬奴平模式下可用OPENGL:使用OpenGL渲染RESIZABLE:使得窗口大小可调整NOFRAME:使得窗口没有边框和控制按钮depth参数:指定颜色位数。默认情况下自动处理,不用设置它32位、64位

获取系统支持的分辨率

ipmort pygame

pagame.init()

pygame.display.list_modes()

import pygameimport sys# 将 pygame 的所有常量名导入from pygame.locals import *# 初始化Pygamepygame.init()fullscreen = False# 全屏标志size = width, height = 600, 400bg = (255, 255, 255)speed = [0, 0]clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("初次见面,请大家多多关照!")turtle = pygame.image.load(r"image/turtle.png")position = turtle.get_rect()# 指定龟头的左右朝向l_head = turtler_head = pygame.transform.flip(turtle, True, False)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == KEYDOWN:if event.key == K_LEFT:speed = [-1, 0]turtle = l_headif event.key == K_RIGHT:speed = [1, 0]turtle = r_headif event.key == K_UP:speed = [0, -1]if event.key == K_DOWN:speed = [0, 1]# 全屏(F11)快捷键if event.key == K_F11:fullscreen = not fullscreenif fullscreen:screen = pygame.display.set_mode((1920, 1080), FULLSCREEN | HWSURFACE)else:screen = pygame.display.set_mode(size)position = position.move(speed)if position.left < 0 or position.right > width:# 翻转图像turtle = pygame.transform.flip(turtle, True, False)# 反方向移动speed[0] = -speed[0]if position.top < 0 or position.bottom > height:speed[1] = -speed[1]screen.fill(bg)screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

示例 - 让界面支持拖拽

让界面支持拖拽

首先设置 RESIZABLE 参数:使得窗口大小可调整第二 检测事件:event.type == VIDEORESIZE

import pygameimport sys# 将 pygame 的所有常量名导入from pygame.locals import *# 初始化Pygamepygame.init()fullscreen = Falsesize = width, height = 600, 400bg = (255, 255, 255)speed = [0, 0]clock = pygame.time.Clock()screen = pygame.display.set_mode(size, RESIZABLE)pygame.display.set_caption("初次见面,请大家多多关照!")turtle = pygame.image.load(r"image/turtle.png")position = turtle.get_rect()# 指定龟头的左右朝向l_head = turtler_head = pygame.transform.flip(turtle, True, False)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == KEYDOWN:if event.key == K_LEFT:speed = [-1, 0]turtle = l_headif event.key == K_RIGHT:speed = [1, 0]turtle = r_headif event.key == K_UP:speed = [0, -1]if event.key == K_DOWN:speed = [0, 1]# 全屏(F11)if event.key == K_F11:fullscreen = not fullscreenif fullscreen:screen = pygame.display.set_mode((1920, 1080), FULLSCREEN | HWSURFACE)else:screen = pygame.display.set_mode(size)# 用户调整窗口尺寸if event.type == VIDEORESIZE:size = event.sizewidth, height = sizeprint(size)screen = pygame.display.set_mode(size, RESIZABLE)position = position.move(speed)if position.left < 0 or position.right > width:# 翻转图像turtle = pygame.transform.flip(turtle, True, False)# 反方向移动speed[0] = -speed[0]if position.top < 0 or position.bottom > height:speed[1] = -speed[1]screen.fill(bg)screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

示例 - 使得图像可以缩放

使得图像可以缩放

图像变换的方法:

filp 上下、左右翻转图像scale 缩放图像(快速)rotate 旋转图像rotozoom 缩放并旋转图像scale2x 快速放大一倍图像smoothscale 平滑缩放图像(精准)

chop 剪裁图像

import pygameimport sys# 将 pygame 的所有常量名导入from pygame.locals import *# 初始化Pygamepygame.init()fullscreen = Falsesize = width, height = 600, 400bg = (255, 255, 255)speed = [0, 0]clock = pygame.time.Clock()screen = pygame.display.set_mode(size, RESIZABLE)pygame.display.set_caption("初次见面,请大家多多关照!")# 设置放大缩小比率ratio = 1.0oturtle = pygame.image.load(r"image/turtle.png")turtle = oturtleoturtle_rect = oturtle.get_rect()position = turtle_rect = oturtle_rect# 指定龟头的左右朝向l_head = turtler_head = pygame.transform.flip(turtle, True, False)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == KEYDOWN:if event.key == K_LEFT:speed = [-1, 0]turtle = l_headif event.key == K_RIGHT:speed = [1, 0]turtle = r_headif event.key == K_UP:speed = [0, -1]if event.key == K_DOWN:speed = [0, 1]# 全屏(F11)if event.key == K_F11:fullscreen = not fullscreenif fullscreen:screen = pygame.display.set_mode((1920, 1080), FULLSCREEN | HWSURFACE)else:screen = pygame.display.set_mode(size)# 放大、缩小小乌龟(=、-),空格恢复原始尺寸if event.key == K_EQUALS or event.key == K_MINUS or event.key == K_SPACE:# 最大只能放大一倍,缩小50%if event.key == K_EQUALS and ratio < 2:ratio += 0.1if event.key == K_MINUS and ratio > 0.5:ratio -= 0.1if event.key == K_SPACE:ratio = 1turtle = pygame.transform.smoothscale(oturtle, (int(oturtle_rect.width * ratio), int(oturtle_rect.height * ratio)))# 相应修改龟头两个朝向的Surface对象,否则一点击移动就打回原形l_head = turtler_head = pygame.transform.flip(turtle, True, False)# 获得小乌龟缩放后的新尺寸turtle_rect = turtle.get_rect()position.width, position.height = turtle_rect.width, turtle_rect.height# 用户调整窗口尺寸if event.type == VIDEORESIZE:size = event.sizewidth, height = sizeprint(size)screen = pygame.display.set_mode(size, RESIZABLE)position = position.move(speed)if position.left < 0 or position.right > width:# 翻转图像turtle = pygame.transform.flip(turtle, True, False)# 反方向移动speed[0] = -speed[0]if position.top < 0 or position.bottom > height:speed[1] = -speed[1]screen.fill(bg)screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

示例 - 使用- rotate 旋转图像 实现贴边爬行

使用- rotate 旋转图像 实现贴边爬行

import pygameimport sysfrom pygame.locals import *pygame.init()fullscreen = Falsesize = width, height = 640, 480bg = (255, 255, 255)clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")turtle = pygame.image.load(r"image/turtle.png")position = turtle_rect = turtle.get_rect()# 小乌龟顺时针行走speed = [5, 0]turtle_right = pygame.transform.rotate(turtle, 90)# 旋转90度turtle_top = pygame.transform.rotate(turtle, 180)turtle_left = pygame.transform.rotate(turtle, 270)turtle_bottom = turtle# 刚开始走顶部turtle = turtle_topwhile True:for event in pygame.event.get():if event.type == QUIT:sys.exit()# 全屏(F11)if event.type == KEYDOWN:if event.key == K_F11:fullscreen = not fullscreenif fullscreen:screen = pygame.display.set_mode((1920, 1080), FULLSCREEN | HWSURFACE)else:screen = pygame.display.set_mode(size)# 移动图像position = position.move(speed)if position.right > width:turtle = turtle_right# 变换后矩形的尺寸发生改变position = turtle_rect = turtle.get_rect()# 矩形尺寸的改变导致位置也有变化position.left = width - turtle_rect.widthspeed = [0, 5]if position.bottom > height:turtle = turtle_bottomposition = turtle_rect = turtle.get_rect()position.left = width - turtle_rect.widthposition.top = height - turtle_rect.heightspeed = [-5, 0]if position.left < 0:turtle = turtle_leftposition = turtle_rect = turtle.get_rect()position.top = height - turtle_rect.heightspeed = [0, -5]if position.top < 0:turtle = turtle_topposition = turtle_rect = turtle.get_rect()speed = [5, 0]screen.fill(bg)screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

P83 Pygame:提高游戏颜值2

示例 - 实现裁剪

实现裁剪

rect方法rect(Surface, color, Rect, width=0)
Surface参数color参数Rect参数width=0

import pygameimport sysfrom pygame.locals import *pygame.init()size = width, height = 800, 600bg = (255, 255, 255)clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")turtle = pygame.image.load(r"image/turtle.png")# 0 -> 未选择,1 -> 选择中,2 -> 完成选择select = 0select_rect = pygame.Rect(0, 0, 0, 0)# 0 -> 未拖拽,1 -> 拖拽中,2 -> 完成拖拽drag = 0position = turtle.get_rect()position.center = width // 2, height // 2while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == MOUSEBUTTONDOWN:if event.button == 1:# 第一次点击,选择范围if select == 0 and drag == 0:pos_start = event.posselect = 1# 第二次点击,推拽图像elif select == 2 and drag == 0:capture = screen.subsurface(select_rect).copy()cap_rect = capture.get_rect()drag = 1# 第三次点击,初始化elif select == 2 and drag == 2:select = 0drag = 0elif event.type == MOUSEBUTTONUP:if event.button == 1:# 第一次释放,结束选择if select == 1 and drag == 0:pos_stop = event.posselect = 2# 第二次释放,结束拖拽if select == 2 and drag == 1:drag = 2screen.fill(bg)screen.blit(turtle, position)# 实时绘制选择框if select:mouse_pos = pygame.mouse.get_pos()if select == 1:pos_stop = mouse_posselect_rect.left, select_rect.top = pos_startselect_rect.width, select_rect.height = pos_stop[0] - pos_start[0], pos_stop[1] - pos_start[1]pygame.draw.rect(screen, (0, 0, 0), select_rect,1)# 拖拽裁剪的图像if drag:if drag == 1:cap_rect.center = mouse_posscreen.blit(capture, cap_rect)pygame.display.flip()clock.tick(30)

P84 Pygame:提高游戏颜值3

示例 - 高效载入图片的方法

高效载入图片的方法 调用.convert()方法转换

bg = pygame.image.load(“bg.jpg”).convert()
转换指的是像素格式的转换
bg = pygame.image.load(“bg.jpg”).convert_alpha()

图片格式

png 无损压缩
jpg 不支持透明,载入时用.convert()
png gif支持透明,载入时用.convert_alpha()

import pygameimport sysfrom pygame.locals import *pygame.init()size = width, height = 640, 480bg = (0, 0, 0)clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")turtle = pygame.image.load("./小甲鱼源代码/p18/image/turtle.jpg").convert()background = pygame.image.load("./小甲鱼源代码/p18/image/background.jpg").convert()position = turtle.get_rect()position.center = width // 2, height // 2turtle.set_colorkey((255, 255, 255))turtle.set_alpha(200)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.blit(background, (0, 0))screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

示例 - 将白色区域设置成透明

# 将白色区域设置成透明import pygameimport sysfrom pygame.locals import *pygame.init()size = width, height = 640, 480bg = (0, 0, 0)clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")turtle = pygame.image.load("./小甲鱼源代码/p18/image/turtle.png").convert_alpha()background = pygame.image.load("./小甲鱼源代码/p18/image/background.jpg").convert()position = turtle.get_rect()position.center = width // 2, height // 2# 将白色区域设置成透明for i in range(position.width):for j in range(position.height):temp = turtle.get_at((i, j))if temp[3] != 0:temp[3] = 200turtle.set_at((i, j), temp)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.blit(background, (0, 0))screen.blit(turtle, position)pygame.display.flip()clock.tick(30)

示例

import pygameimport sysfrom pygame.locals import *pygame.init()size = width, height = 640, 480bg = (0, 0, 0)clock = pygame.time.Clock()screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")turtle = pygame.image.load("./小甲鱼源代码/p18/image/turtle.png").convert_alpha()background = pygame.image.load("./小甲鱼源代码/p18/image/background.jpg").convert()position = turtle.get_rect()position.center = width // 2, height // 2def blit_alpha(target, source, location, opacity):x = location[0]y = location[1]temp = pygame.Surface((source.get_width(), source.get_height())).convert()temp.blit(target, (-x, -y))temp.blit(source, (0, 0))temp.set_alpha(opacity)target.blit(temp, location)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.blit(background, (0, 0))blit_alpha(screen, turtle, position, 200)pygame.display.flip()clock.tick(30)

P85 Pygame:基本图像绘制

示例 - rect方法绘制矩形

rect方法绘制矩形rect(Surface, color, Rect, width=0)
Surface参数:绘制在surface对象上color参数:矩形颜色Rect参数:矩形范围width=0:边框大小。0表示填充矩形,1以上表示 使用color指定的颜色绘制边框

import pygameimport sysfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)size = width, height = 640, 480screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.fill(WHITE)pygame.draw.rect(screen, BLACK, (50, 50, 150, 50), 0)pygame.draw.rect(screen, BLACK, (250, 50, 150, 50), 1)pygame.draw.rect(screen, BLACK, (450, 50, 150, 50), 10)pygame.display.flip() # 把内存中的画面反转到窗口中 <- 双缓冲关系clock.tick(10)

示例 - polygon方法绘制多边形

polygon方法绘制多边形polygon(Surface, color, pointlist, width=0)
Surface参数:绘制在surface对象上color参数:颜色pointlist参数:多边形范围width=0:边框大小。0表示填充矩形,1以上表示 使用color指定的颜色绘制边框

import pygameimport sysfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)GREEN = (0, 255, 0)points = [(200, 75), (300, 25), (400, 75), (450, 25), (450, 125), (400, 75), (300, 125)]size = width, height = 640, 200screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.fill(WHITE)pygame.draw.polygon(screen, GREEN, points, 0)pygame.display.flip()clock.tick(10)

示例 - circle方法绘制圆形

circle方法绘制圆形circle(Surface, color, pos, radius, width=0)
Surface参数:绘制在surface对象上color参数:颜色pos参数:圆心位置radius参数:半径大小width=0:边框大小。0表示填充矩形,1以上表示 使用color指定的颜色绘制边框

# 跟随鼠标的圆形import pygameimport sysfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)GREEN = (0, 255, 0)RED = (255, 0, 0)BLUE = (0, 0, 255)size = width, height = 640, 480screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")position = size[0] // 2, size[1] // 2moving = Falseclock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == MOUSEBUTTONDOWN:if event.button == 1:moving = Trueif event.type == MOUSEBUTTONUP:if event.button == 1:moving = Falseif moving:position = pygame.mouse.get_pos()screen.fill(WHITE)pygame.draw.circle(screen, RED, position, 25, 1)pygame.draw.circle(screen, GREEN, position, 75, 1)pygame.draw.circle(screen, BLUE, position, 125, 1)pygame.display.flip()clock.tick(120)

示例 - ellipse方法绘制椭圆

ellipse方法绘制椭圆ellipse(Surface, color, Rect, width=0)
Surface参数:绘制在surface对象上color参数:颜色Rect参数:限定矩形width=0:边框大小。0表示填充矩形,1以上表示 使用color指定的颜色绘制边框

import pygameimport sysfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)GREEN = (0, 255, 0)RED = (255, 0, 0)BLUE = (0, 0, 255)size = width, height = 640, 300screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.fill(WHITE)pygame.draw.ellipse(screen, BLACK, (100, 100, 440, 100), 1)pygame.draw.ellipse(screen, BLACK, (220, 50, 200, 200), 1)pygame.display.flip()clock.tick(120)

示例 - arc方法绘制弧线

arc方法绘制弧线arc(Surface, color, Rect, start_angle, stop_angle, width=1)
Surface参数:绘制在surface对象上color参数:颜色Rect参数:限定矩形start_angle参数:起始角度stop_angle参数:结束角度width=0:边框大小。0表示填充矩形,1以上表示 使用color指定的颜色绘制边框

import pygameimport sysimport mathfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)GREEN = (0, 255, 0)RED = (255, 0, 0)BLUE = (0, 0, 255)size = width, height = 640, 300screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.fill(WHITE)pygame.draw.arc(screen, BLACK, (100, 100, 440, 100), 0, math.pi, 1)pygame.draw.arc(screen, BLACK, (220, 50, 200, 200), math.pi, math.pi * 2, 1)pygame.display.flip()clock.tick(120)

示例 - line、lines、aaline、aalines方法绘制线条

line、lines、aaline、aalines方法绘制线条line(Surface, color, start_pos, end_pos, width=1)lines(Surface, color, closed, pointlist, width=1)
closed参数:=1则首尾相连
aaline(Surface, color, startpos, endpos, blend=1)aalines(Surface, color, closed, pointlist, blend=1)

import pygameimport sysfrom pygame.locals import *pygame.init()WHITE = (255, 255, 255)BLACK = (0, 0, 0)GREEN = (0, 255, 0)points = [(200, 75), (300, 25), (400, 75), (450, 25), (450, 125), (400, 75), (300, 125)]size = width, height = 640, 480screen = pygame.display.set_mode(size)pygame.display.set_caption("FishC Demo")clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()screen.fill(WHITE)pygame.draw.lines(screen, GREEN, 1, points, 1)pygame.draw.line(screen, BLACK, (100, 200), (540, 250), 1)pygame.draw.aaline(screen, BLACK, (100, 250), (540, 300), 1)pygame.draw.aaline(screen, BLACK, (100, 300), (540, 350), 0)pygame.display.flip()clock.tick(10)

了解的差不多了,以下内容暂不学习了,估计也用不到

P86 Pygame:动画精灵

1

P87 Pygame:碰撞检测

1

P88 Pygame:播放声音和音效

1

P89 Pygame:摩擦摩擦

1

P90 Pygame:游戏胜利

1

P91 Pygame:飞机大战1

1

P92 Pygame:飞机大战2

1

P93 Pygame:飞机大战3

1

P94 Pygame:飞机大战4

1

P95 Pygame:飞机大战5

1

P96 Pygame:飞机大战

1

P97 Pygame:飞机大战

1

【python教程】-- 入门 | 小甲鱼《零基础入门学Python》教程笔记(知识点详细 源码可复制)全

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。