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

小甲鱼老师零基础入门学习Python全套资料百度云(包括小甲鱼零基础入门学习Python全套视频+全套源码+全套PPT课件+全套课后题及Python常用工具包链接、电子书籍等)请往我的资源(https://download.csdn.net/download/qq_32809093/13099592查看

目录:

000 愉快的开始
001 我和Python的第一次亲密接触
002 用Python设计第一个游戏
003 小插曲之变量和字符串
004 改进我们的小游戏
005 闲聊之Python的数据类型
006 Pyhon之常用操作符
007 了不起的分支和循环
008 了不起的分支和循环2
009 了不起的分支和循环3
010 列表:一个打了激素的数组
011列表:一个打了激素的数组2
012列表:一个打了激素的数组3
013元组:戴上了枷锁的列表
014字符串:各种奇葩的内置方法
015字符串:格式化
016 序列!序列!
017函数:Python的乐高积木
018 函数:灵活即强大
019函数:我的地盘听我的(局部变量与全局变量)
020函数:内嵌函数和闭包
021函数:lambda表达式
022 函数:递归是神马
023 递归:这帮小兔崽子
024 递归:汉诺塔
025 字典:当索引不好用时
026 字典:当索引不好用时2
027 集合:在我的世界里,你就是唯一
028 文件:因为懂你,所以永恒
029 文件:一个任务
030 文件系统:介绍一个高大上的东西
031 永久存储:腌制一缸美味的泡菜(pickle)
032 异常处理:你不可能总是对的
033 异常处理:你不可能总是对的2
034 丰富的else语句及简洁的with语句
035 图形用户界面入门:EasyGui
036 类和对象:给大家介绍对象
037 类和对象:面向对象编程
038 类和对象:继承
039 类和对象:拾遗
040 类和对象:一些相关的BIF
041 魔法方法:构造和析构
042 魔法方法:算术运算
043 魔法方法:算术运算2
044 魔法方法:简单定制
045 魔法方法:属性访问
046 魔法方法:描述符(Property的原理)
047 魔法方法:定制序列
048 魔法方法:迭代器
049 乱入:生成器
050 模块:模块就是程序
051 模块:__name__='__main__'、搜索路径和包
052 模块:像个极客一样去思考
053 论一只爬虫的自我修养
054 论一只爬虫的自我修养2:实战
055 论一只爬虫的自我修养3:隐藏

064 GUI的终极选择:Tkinter
065 GUI的终极选择:Tkinter2
066 GUI的终极选择:Tkinter3
067 GUI的终极选择:Tkinter4
068 GUI的终极选择:Tkinter5
069 GUI的终极选择:Tkinter6
070 GUI的终极选择:Tkinter7
071 GUI的终极选择:Tkinter8
073 GUI的终极选择:Tkinter10
074  GUI的终极选择:Tkinter11
075 GUI的终极选择:Tkinter12
076 GUI的终极选择:Tkinter13
077 GUI的终极选择:Tkinter14

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

 

000 愉快的开始

python跨平台。
应用范围:操作系统、WEB、3D动画、企业应用、云计算
大家可以学到什么Python3的所有常用语法、面向对象编程思维、运用模块进行编程、游戏编程、计算机仿真

Python 是脚本语言
脚本语言(Scripting language)是电脑编程语言,因此也能让开发者藉以编写出让电脑听命行事的程序。以简单的方式快速完成某些复杂的事情通常是创造脚本语言的重要原则,基于这项原则,使得脚本语言通常比 C 语言、C++语言 或 Java 之类的系统编程语言要简单容易。也让脚本语言另有一些属于脚本语言的特性:
•  语法和结构通常比较简单
•  学习和使用通常比较简单
•  通常以容易修改程序的“解释”作为运行方式,而不需要“编译”
•  程序的开发产能优于运行性能
一个脚本可以使得本来要用键盘进行的相互式操作自动化。一个 Shell 脚本主要由原本需要在命令行输入的命令组成,或在一个文本编辑器中,用户可以使用脚本来把一些常用的操作组合成一组串行。主要用来书写这种脚本的语言叫做脚本语言。很多脚本
语言实际上已经超过简单的用户命令串行的指令,还可以编写更复杂的程序。

IDLE 是一个 Python Shell,shell 的意思就是“外壳”,基本上来说,就是一个通过键入文本与程序交互的途径!像我们 Windows 那个 cmd 窗口,像 Linux 那个黑乎乎的命令窗口,他们都是 shell,利用他们,我们就可以给操作系统下达命令。同样的,我们可以利用 IDLE 这个 shell 与 Python 进行互动。

注:在 Python 中不能把两个完全不同的东西加在一起,比如说数字和文本

如果我需要在一个字符串中嵌入一个双引号,正确的做法是:你可以利用反斜杠(\)对双引号转义:\",或者用单引号引起这个字符串

001 我和Python的第一次亲密接触

IDLE启动Python

IDLE是一个Python Shellshell的意思就是“外壳”,基本上来说,就是一个通过键入文本与程序交互的途径

我们看到>>>这个提示符,Ta的含义是告诉你,Python已经准备好了,在等着你键入Python指令呢

好了,大家试试在IDLE里输入:

>>>print (“I love fishc.com”)

我们尝试点儿新的东西,我们输入

>>>print(5+3)

或者直接输入

>>>5+3

不妨在试试计算

>>>1234567890987654321*987654321012345678

还有我们可以将两个字符串“相加”在一起,这种做法叫做拼接字符串

>>>print("well water"+"river")

先试试

>>> print("I love fishc.com"*2)

>>> print("I love fishc.com\n"* 2)

002 用Python设计第一个游戏

实例1:

print("---------我爱鱼C工作室----------")
temp = input("不妨猜一下小甲鱼现在心里想的是哪个数字:")
guess = int(temp)
if guess == 8:
    print("我草,你是小甲鱼心里的蛔虫嘛?!")
    print("哼,猜中了也没有奖励!")
else:
    print("猜错了,小甲鱼现在心里想的是8!")
    print("游戏结束,不玩啦")

BIF 就是 Built-in Functions,内置函数。为了方便程序员快速编写脚本程序(脚本就是要编程速度快快快!!!),Python 提供了非常丰富的内置函数,我们只需要直接调用即可,例如 print() 的功能是“打印到屏幕”,input() 的作用是接收用户输入。

在 Python 或 IDLE 中,输入 dir(__builtins__) 可以看到 Python 提供的内置方法列表(注意,builtins 前后是两个下划线哦)其中小写的就是 BIF。如果想具体查看某个BIF 的功能,比如 input(),可以在 shell 中输入 help(input),就会得到这个 BIF 的功能描述。哦,答案应该是 68 个

>>> dir(__builtins__)  查看 Python 提供的内置方法列表

>>> help(input)  查看input的具体使用说明 

注:

只有当标识符已经赋值后( Python 的变量是不用先声明的)才能在代码中使用,未赋值的标识符直接使用会导致运行时错误

缩进是 Python 的灵魂

Python 不允许 if 条件中赋值,所以 if c = 1: 会报错!

 

003 小插曲之变量和字符串

插曲之变量

变量名就像我们现实社会的名字,把一个值赋值给一个名字时,Ta会存储在内存中,称之为变量(variable),在大多数语言中,都把这种行为称为“给变量赋值”或“把值存储在变量中”。

不过Python与大多数其他计算机语言的做法稍有不同,Ta并不是把值存储在变量中,而更像是把名字贴在值的上边。

所以有些Python程序员会说“Python”没有“变量”,只有“名字”。

需要注意的地方

在使用变量之前,需要对其先赋值。

变量名可以包括字母、数字、下划线,但变量名不能以数字开头

字母可以是大写或小写,但大小写是不同的。也就是说fishcFishC对于Python来说是完全不同的两个名字

等号(=)是赋值的意思,左边是名字,右边是值,不可写反咯。

插曲之字符串

到目前为止,我们所认知的字符串就是引号内的一切东西,我们也把字符串叫做文本,文本和数字是截然不同的,咱看例子:>>>5+8

>>> '5'+'8'

要告诉Python你在创建一个字符串,就要在字符两边加上引号,可以是单引号或者双引号Python女士表示不挑剔。但必须成对,你不能一边单引号,另一边却花心的用上双引号结尾。

如果字符串中需要出现单引号或双引号怎么办

例如我想打印字符串:Let’s go!

有两种方法,第一种比较常用,就是使用我们的转义符号(\)对字符串中的引号进行转义:

>>> 'Let\'s go!'

原始字符串

好像反斜杠是一个好东西,但不妨试试打印:

>>> str = 'C:\now'

我们可以用反斜杠对自身进行转义:

>>> str = 'C:\\now'

原始字符串的使用非常简单,只需要在字符串前边加一个英文字母r即可(则都会以原始字符串输出):

>>>str = r'C:\now'

长字符串

如果希望得到一个跨越多行的字符串,例如:

我爱鱼C

正如我爱小甲鱼,

久久不肯散去……

这我们就需要使用到三重引号字符串!

 

004 改进我们的小游戏

第一个改进要求:猜错的时候程序提示用户当前的输入比答案大了还是小了

与操作and

第二个改进要求:程序应该提供多次机会给用户猜测,专业点来讲就是程序需要重复运行某些代码。

条件分支

while循环

实例1:找8

temp = input("请输入一个数据:")
guess = int(temp)
i=0
while guess != 8 and i < 3:
    i = i + 1
    temp = input("哎呀,猜错了,请重新输入吧:")
    guess = int(temp)
    if guess == 8:
        print("我草,你是小甲鱼心里的蛔虫嘛?")
        print("哼,猜对了也没有奖励")
    else:
        if guess > 8:
            print("哥,大了大了~~")
        else:
            print("嘿,小了!小了!!")
print("游戏结束,不玩啦~~")

random模块里边有一个函数叫做:randint()Ta会返回一个随机的整数。

实例2:找随机数

import random#导入随机数函数
secret = random.randint(1,5)#随机生成1到5的一个随机数
temp = input("请输入一个1-5的数据:")
guess = int(temp)
i=0
while guess != secret and i < 6:
    i = i + 1
    guess = int(temp)
    if guess == secret:
        print("我草,你是小甲鱼心里的蛔虫嘛?")
        print("哼,猜对了也没有奖励")
    else:
        if guess > secret:
            print("哥,大了大了~~")
        else:
            print("嘿,小了!小了!!")      
        temp = input("请重新输入吧:")
print("游戏结束,不玩啦~~")

 

005 闲聊之Python的数据类型

Python的一些数值类型:整型、布尔类型(True与False)、浮点型、e记法、复数类型等

e记法(e4相当于10的四次方,e-10相当于10的-10次方)

类型转换

字符型转换为整型

其它同上

type()函数(可查看变量类型)

isinstance()函数(用来判断两个输入参数类型是否一致)

 

006 Pyhon之常用操作符

算术操作符

注:python中 \ 为除法, \\ 为整除 ,% 为取余

幂运算(3的二次方)

3的二次方后取负

注:先幂运算、然后乘除、后加减、后逻辑

3的负二次方

比较操作符

逻辑操作符

优先级问题

007 了不起的分支和循环

打飞机游戏框架:

加载背景音乐

播放背景音乐(设置单曲循环)

我方飞机诞生

while True:
    if 用户是否点击了关闭按钮:
       推出程序
       
    interval += 1;
    if interval == 50:
       interval = 0;
       小飞机诞生
    小飞机移动一个位置
    屏幕刷新
    
    if 用户鼠标产生移动:
       我方飞机中心位置 = 用户鼠标位置
       屏幕刷新
       
    if 我方飞机与小飞机发生肢体冲突:
       我方挂,播放撞机音乐
       修改我方飞机图案
       打印“Game over"
       停止背景音乐,最好淡出

 

008 了不起的分支和循环2

现在小甲鱼来考考大家:

按照100分制,90分以上成绩为A8090B6080C60以下为D,写一个程序,当用户输入分数,自动转换为ABCD的形式打印。

score = int(input('请输入一个分数:'))
if 100 >= score >= 90:
    print('A')
elif 90 > score >= 80:
    print('B')
elif 80 > score >= 60:
    print('C')
elif 60 > score >= 0:
    print('D')
else:
    print('输入错误!')

条件表达式(三元操作符)

有了这个三元操作符的条件表达式,你可以使用一条语句来完成以下的条件判断和赋值操作:

x, y = 4, 5

if x < y:

  small = x

else:

  small = y

例子可以改进为

small = x if x < y else y    #如果x小于y,则small等于x,否则等于y

断言(assert)

assert这个关键字我们称之为“断言”,当这个关键字后边的条件为假的时候,程序自动崩溃并抛出AssertionError的异常。

举个例子:

>>> assert 3 > 4

一般来说我们可以用Ta再程序中置入检查点,当需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert关键字就非常有用了

 

009 了不起的分支和循环3

while循环

while 条件:

                  循环体

for循环

虽然说Python是由C语言编写而来的,但是Tafor循环跟C语言的for循环不太一样,Pythonfor循环显得更为智能和强大!

语法:

for 目标 in 表达式:

     循环体

每次取FishC中一个字符及空格输出

range()函数

语法:range( [strat],[stop],[step] )

这个BIF有三个参数,其中用中括号括起来的两个表示这两个参数是可选的。

step=1表示第三个参数的值默认值是1setp为每步距离

range这个BIF的作用是生成一个从start参数的值开始到stop参数的值结束的数字序列

 

break语句(结束本层循环)

实例:

bingo = '小甲鱼是帅哥'
answer = input('请输入小甲鱼最想听的一句话:')

while True:
    if answer == bingo:
        break
    answer = input('抱歉,错了,请重新输入(答案正确才能退出游戏):')

print('哎哟,帅哦~')
print('您真是小甲鱼肚子里的蛔虫啊^_^')

continue语句(当前位置结束本次循环,重新开始下次循环)

实例:

for i in range(10):
    if i%2 != 0:
        print(i)
        continue
    i += 2
    print(i)

010 列表:一个打了激素的数组

列表一个打了激素的数组

创建列表

创建一个普通列表

创建一个混合列表

创建一个空列表

向列表添加元素

append()函数向列表末尾添加一个元素

extend()函数向列表末尾添加多个元素

insert(n,xxx)函数向列表中第n个元素前插入一个元素

注:0表示第一个元素

011列表:一个打了激素的数组2

从列表中获取元素

跟数组一样,我们可以通过元素的索引值(index)从列表获取单个元素,注意,列表索引值是从 0 开始的。

从列表删除元素

remove()函数表示从列表中删除某个元素

del()函数也表示从列表中删除某个元素

pop()函数从列表中取出最后一个元素

列表分片(Slice

利用索引值,每次我们可以从列表获取一个元素,但是我们总是贪心的,如果一次性需要获取多个元素,有没有办法实现呢?利用列表分片,我们可以简单的实现这个要求。

member[0:2]表示从第1个元素开始拷贝,一共拷贝两个元素,即member[0]和member[1]

列表的拷贝

012列表:一个打了激素的数组3

列表的一些常用操作符

比较操作符

逻辑操作符

连接操作符

重复操作符

成员关系操作符

关于分片“拷贝”概念的补充

>>> dir(list)可查看所有列表的操作函数

count()函数可计算列表中相同元素个数

index()函数可索引列表元素

reverse()将列表中元素倒序

sort()将列表中元素从小到大排序

关于分片“拷贝”概念的补充

注:list13=list11相当于多了个指向列表的标签,list12 = list[:]是实实在在的拷贝

013元组:戴上了枷锁的列表

由于和列表是近亲关系,所以元组和列表在实际使用上是非常相似的。

我们这节课主要通过讨论元组和列表到底有什么不同来学习元组,酱紫大家就不会觉得老是重复一样的内容

我们主要从以下几个点来讨论学习:

创键和访问一个元组

创建元组(括号可以没有,但逗号一定要有)

访问元组前两个元素

更新和删除一个元组

更新一个元组

注:其并未对原元组进行修改,而是生成了一个新的元组,并贴上temp名字标签而已。原元组由于标签没有了,则会被自动回收。

删除一个元组

元组相关的操作符

注:元组不允许修改和删除。

014字符串:各种奇葩的内置方法

 

015字符串:格式化

由于花括号被解释掉,所以不打印后面中文

字符串格式化符号含义

将ASCII码97对应的字符输出

格式化整数

格式化操作符辅助命令

5表示输出为五位数

Python 的转义字符及其含义

 

016 序列!序列!

列表、元组和字符串的共同点

都可以通过索引得到每一个元素

默认索引值总是从0开始

可以通过分片的方法得到一个范围内的元素的集合

有很多共同的操作符(重复操作符、拼接操作符、成员关系操作符)

使用list方法

元组转换为列表

注:元组为小括号,列表为中括号。

max() 返回序列或者参数集合中的最大值

min() 返回序列或者参数集合中的最小值

sum(iterable[,start=0]) 返回序列iterable和可选参数start的总和

sorted()将元素从小到大重新排列

reversed()将元素倒序排列

注:元组是不可以修改和删除的,所以不可以直接对元组使用sorted与reversed命令

enumerate()将每个元素插入枚举

zip()返回由各个参数的序列组成的元组

 

017函数:Python的乐高积木

定义一个函数和调用

 

018 函数:灵活即强大

形参和实参

>>> def MyFirstFunction(name):

  '函数定义过程中的name是叫形参'

  #因为Ta只是一个形式,表示占据一个参数位置

  print('传递进来的' + name + '叫做实参,因为Ta是具体的参数值!')

>>> MyFirstFunction('小甲鱼')

传递进来的小甲鱼叫做实参,因为Ta是具体的参数值!

关键字参数

默认参数(即形参中给定默认值,则在未给实参时会以默认值输出)

收集参数

 

019函数:我的地盘听我的

函数与过程

再谈谈返回值

如果有返回值,函数则返回对应值;如果没有,则返回None

可以返回多个值

019函数:我的地盘听我的(局部变量与全局变量)

def discounts(price, rate):
    final_price = price * rate
    old_price = 88 #这里试图修改全局变量
    print('修改后old_price的值是:', old_price)
    return final_price

old_price = float(input('请输入原价:'))
rate = float(input('请输入折扣率:'))
new_price = discounts(old_price, rate)
print('修改后old_price的值是:', old_price)
print('打折后价格是:', new_price)

global可将局部变量声明为全局变量

020函数:内嵌函数和闭包

内嵌函数

闭包(closure

注:使用nonlocal语句将x强制为不是局部变量

021函数:lambda表达式

lambda表达式的作用

Python写一些执行脚本时,使用lambda就可以省下定义函数过程,比如说我们只是需要写个简单的脚本来管理服务器时间,我们就不需要专门定义一个函数然后再写调用,使用lambda就可以使得代码更加精简

对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数起个名字也是比较头疼的问题,使用lambda就不需要考虑命名的问题了

简化代码的可读性,由于普通的屌丝函数阅读经常要跳到开头def定义部分,使用lambda函数可以省去这样的步骤。

过滤函数filter可筛选出非零元素

筛选出奇数

注:lambda x:x%2用来判断是否为奇,x为奇则输出1,否则输出0;range(10)可生成0-9的10个整数,filter用来筛选非零元素;如果为偶数,则被筛选掉;如果为奇数,则保留,但输出的是rang(10)产生的原始数,因为lambda只是用来判断是否为奇偶

range生成的0-9给了x,x经过2倍运算后再赋值给x

022 函数:递归是神马

汉诺塔游戏

树结构的定义

谢尔宾斯基三角形

递归求阶乘

写一个求阶乘的函数

正整数阶乘指从1乘以2乘以3乘以4一直乘到所要求的数。

例如所给的数是5,则阶乘式是1×2×3×4×5,得到的积是120,所以120就是4的阶乘。

假设我们n的值传入是5,那么:

实例:求阶乘

def factorial(n):
    result = n
    for i in range(1, n):
        result *= i

    return result

number = int(input('请输入一个正整数:'))
result = factorial(number)
print("%d 的阶乘是:%d"  % (number, result))#格式化为整数类型

实例2:递归求阶乘

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

number = int(input('请输入一个正整数:'))
result = factorial(number)
print("%d 的阶乘是:%d" % (number, result))

023 递归:这帮小兔崽子

坑爹的兔子

斐波那契数列的迭代实现

我们都知道兔子繁殖能力是惊人的,如下图:

我们可以用数学函数来定义:

课间练习:假设我们需要求出经历了20个月后,总共有多少对小兔崽子?(迭代 vs 递归

def fab(n):
    n1 = 1
    n2 = 1
    n3 = 1

    if n < 1:
        print('输入有误!')
        return -1

    while (n-2) > 0:
        n3 = n2 + n1
        n1 = n2
        n2 = n3
        n -= 1
    
    return n3

result = fab(20)
if result != -1:
    print('总共有%d对小兔崽子诞生!' % result)

斐波那契数列的递归实现

递归实现(递归计算时间将拉长)

def fab(n):
    if n < 1:
        print('输入有误!')
        return -1

    if n == 1 or n == 2:
        return 1
    else:
        return fab(n-1) + fab(n-2)

result = fab(35)
if result != -1:
    print('总共有%d对小兔崽子诞生!' % result)

注:迭代计算时间远比递归少,因为递归要循环出入栈

024 递归:汉诺塔

递归求解汉诺塔

 

对于游戏的玩法,我们可以简单分解为三个步骤

将前63个盘子从X移动到Y上。

将最底下的第64个盘子从X移动到Z上。

Y上的63个盘子移动到Z上。

问题一:将X上的63个盘子借助Z移到Y上;

问题二:将Y上的63个盘子借助X移到Z上。

 

对于游戏的玩法,我们可以简单分解为三个步骤

将前63个盘子从X移动到Y上。

将最底下的第64个盘子从X移动到Z上。

Y上的63个盘子移动到Z上。

问题一:将X上的63个盘子借助Z移到Y上;

问题二:将Y上的63个盘子借助X移到Z上。

实例:

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')

025 字典:当索引不好用时

映射

创建和访问字典

>>> dict4 = dict(小甲鱼='让编程改变世界',李宁='一切皆有可能')
>>> dict4
{'小甲鱼': '让编程改变世界', '李宁': '一切皆有可能'}

>>> dict4['爱迪生'] = '天才是99%的汗水加1%的灵感'
>>> dict4
{'小甲鱼': '让编程改变世界', '李宁': '一切皆有可能', '爱迪生': '天才是99%的汗水加1%的灵感'}

026 字典:当索引不好用时2

fromkey()方法用于创建并返回一个新的字典它有两个参数,第一个参数是字典的键;第二个参数是可选的,是传入键的值。如果不提供,默认是None

>>> dict1 = {}
>>> dict1.fromkeys((1,2,3))
{1: None, 2: None, 3: None}
>>> dict2 = {}
>>> dict2.fromkeys((1,2,3),"Number")
{1: 'Number', 2: 'Number', 3: 'Number'}
>>> dict3 = {}
>>> dict3.fromkeys((1,2,3),('one','two','three'))
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}

访问字典的方法有key()、values()和items()

key()用于返回字典中的键,value()用于返回字典中所有的值,item()当然就是返回字典中所有的键值对(也就是项)

>>> dict1 = dict1.fromkeys(range(5),'赞')
>>> dict1.keys()
dict_keys([0, 1, 2, 3, 4])
>>> dict1.values()
dict_values(['赞', '赞', '赞', '赞', '赞'])
>>> dict1.items()
dict_items([(0, '赞'), (1, '赞'), (2, '赞'), (3, '赞'), (4, '赞')])

get()方法提供了更宽松的方式去访问字典项,当键不存在的时候,get()方法并不会报错,只是默默第返回一个None,表示啥都没找到:

>>> dict1.get(10)
>>> dict1.get(4)
'赞'

如果希望找不到数据时返回指定的值,可以在第二个参数设置对应的默认返回值:

>>> dict1.get(32,'木有')
'木有'

如果不知道一个键是否在字典中,可以使用成员资格操作符(in 或 not in)来判断
>>> 31 in dict1
False
>>> 4 in dict1

clear()可清空一个字典

>>> dict1
{0: '赞', 1: '赞', 2: '赞', 3: '赞', 4: '赞'}
>>> dict1.clear()
>>> dict1
{}

copy()方法是复制字典(全拷贝)

>>> a = {1:'one',2:'two',3:'three'}
>>> b = a.copy()
>>> id(a)
52448840
>>> id(b)
52503624
>>> a[1] = 'four'
>>> a
{1: 'four', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}

pop()是给定键弹出对应的值,popitem()是随机弹出一个项

>>> a.pop(2)
'two'
>>> a
{1: 'four', 3: 'three'}
>>> a.popitem()
(1, 'four')
>>> a
{3: 'three'}

setdefault()方法与get()方法相似,但setdefault()在字典中找不到相应的键值时会自动添加

>>> a = {1:'one',2:'two',3:'three'}
>>> a.setdefault(2)
'two'
>>> a.setdefault(4)
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: None}

update()方法可以更新字典

>>> a = {1:'one','小白':None}

>>> b = {'小白':'狗'}
>>> a.update(b)
>>> a
{1: 'one', '小白': '狗'}

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

字典的表亲--集合(在python3中,如果用大括号括起一堆数字但没有体现映射关系,那么就会认为这堆玩意儿就是个集合)

>>> num1 = {}
>>> type(num1)
<class 'dict'>
>>> num2 = {1,3,4}
>>> type(num2)
<class 'set'>

集合中的元素都是唯一的(集合会自动帮我们把重复的数据清理掉,集合是无序的,所以不能试图去索引集合中的某一个元素

>>> num = {1,2,3,4,5,5,4,3,2,1}
>>> num
{1, 2, 3, 4, 5}

如何创建一个集合有两种方法:1、直接把一堆元素用大括号括起来;2、用set()

一种是直接把一堆元素用花括号括起来

>>> set1 = {'小甲鱼','小鱿鱼','小甲鱼'}

一种是使用set()工厂函数

>>> set2 = set(['小甲鱼','小鱿鱼','小甲鱼'])
>>> set1 == set2
True

课堂搞搞看

要求:去掉列表中重复的元素

[0, 1, 2, 3, 4, 5, 5, 3, 1]

方法一、

>>> list1 = [1,2,3,4,5,5,3,1,0]

>>> temp = list1[:]
>>> list1.clear()
>>> list1
[]
>>> for each in temp:
    if each not in list1:
        list1.append(each) #append()表示向列表中添加元素

方法二、

>>> list1 = list(set(list1))
>>> list1
[0, 1, 2, 3, 4, 5]

#set(list1)先将list1列表转变为集合, list(set(list1))再讲集合转变为列表

如何访问集合中的值

由于集合中的元素是无序的,所以并不能像序列那样用下标来进行访问,但是可以使用迭代把集合中的数据一个个读取出来

可以使用for把集合中的数据一个个读取出来

>>> set1 = {1,2,3,4,5,4,3,2,1,0}
>>> for each in set1:
    print(each,end = ' ')

    
0 1 2 3 4 5 

•也可以通过innot in判断一个元素是否在集合中已经存在

>>> 0 in set1
True
>>> 8 in set1
False

使用add()方法可以为集合添加元素,使用remove()方法可以删除集合中已知的元素:

>>> set1.add(6)
>>> set1
{0, 1, 2, 3, 4, 5, 6}
>>> set1.remove(5)
>>> set1
{0, 1, 2, 3, 4, 6}

不可变集合(把元素给froze冰冻起来)(像元组一样不能随意地增加或删除集合中的元素)

028 文件:因为懂你,所以永恒

大多数u程序都是:首先接收输入数据,然后按照要求进行处理,最后输出数据

虽然当前数据放在内存中存取的速度要比硬盘中快,但一旦断电则会丢失,所以尽量ctrl+s保持到硬盘中


什么是文件

打开文件

open(file, mode='r', buffering=-1, encoding=None,errors=None, newline=None, closefd=True, opener=None)

open()的第一个参数是传入的文件名,第二个参数是指定文件的打开模式

文件对象方法

>>> f = open("D:\\python3.3.2\Hello.txt")
>>> f
<_io.TextIOWrapper name='D:\\python3.3.2\\Hello.txt' mode='r' encoding='cp936'>
>>> f.read()
"A. HISTORY OF THE SOFTWARE\n==========================\n\nPython was created in the early 1990s by Guido van Rossum at Stichting\nMathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands\nas a successor of a language called ABC.  Guido remains Python's\nprincipal author, although it includes many contributions from others.\n\nIn 1995, Guido continued his work on Python at the Corporation for\nNational Research Initiatives (CNRI, see http://www.cnri.reston.va.us)\nin Reston, Virginia where he released several versions of the\nsoftware."
>>> f.close()
>>> f = open("D:\\python3.3.2\Hello.txt")
>>> f.read(5)
'A. HI'
>>> f.tell()   #返回当前光标所在文件的位置
5
>>> f.readline()
'STORY OF THE SOFTWARE\n'
将f放入到列表

>>> f = open("D:\\python3.3.2\Hello.txt",'w')#w模式写入会覆盖已存在的文件(即原文件内容全部被删除),a模式则在末尾追加写入
>>> f.write('who are you')          #返回的是写入的字符数
11
>>> f.close()

029 文件:一个任务

任务:将文件(record.txt)中的数据进行分割并按照以下规律保存起来:

小甲鱼的对话单独保存为boy_*.txt的文件(去掉“小甲鱼:”)

小客服的对话单独保存为girl_*.txt的文件(去掉“小客服:”)

文件中总共有三段对话,分别保存为boy_1.txt, girl_1.txtboy_2.txt, girl_2.txt, boy_3.txt, gril_3.txt6个文件(提示:文件中不同的对话间已经使用“==========分割

test1:

f = open("record.txt")

boy = []
girl = []
count = 1

for each_line in f:
    if each_line[:6] != '======':#判断是否连续读到六个=
        (role,line_spoken) = each_line.split(':',1)#split以:进行字符切割,
        #将切得到的两部分内容依次存放在role与line_spoken中
        if role == '小甲鱼':
            boy.append(line_spoken)#将小甲鱼说的内容添加到列表boy中
        if role == '小客服':
            girl.append(line_spoken)#将小客服说的内容添加到列表girl中
    else:
        file_name_boy = 'boy_' + str(count) + '.txt'
        file_name_girl = 'girl_' + str(count) + '.txt'

        boy_file = open(file_name_boy,'w')#以w模式新建一个以file_name_boy命名的txt文件
        girl_file = open(file_name_girl,'w')#并贴上boy_file的标签

        boy_file.writelines(boy)#将列表boy中的内容写入到boy_file文件中
        girl_file.writelines(girl)

        boy_file.close()#关闭boy_file文件
        girl_file.close()

        boy = []#清空列表boy
        girl = []
        count += 1

file_name_boy = 'boy_' + str(count) + '.txt'
file_name_girl = 'girl_' + str(count) + '.txt'

boy_file = open(file_name_boy,'w')
girl_file = open(file_name_girl,'w')

boy_file.writelines(boy)
girl_file.writelines(girl)

boy_file.close()
girl_file.close()#记得关闭文件

test2:

 

def save_file(boy,girl,count):
    file_name_boy = 'boy_' + str(count) + '.txt'
    file_name_girl = 'girl_' + str(count) + '.txt'

    boy_file = open(file_name_boy,'w')
    girl_file = open(file_name_girl,'w')

    boy_file.writelines(boy)
    girl_file.writelines(girl)

    boy_file.close()
    girl_file.close()

def split_file(file_name):
    f = open(file_name)

    boy = []
    girl = []
    count = 1

    for each_line in f:
        if each_line[:6] != '======':
            (role,line_spoken) = each_line.split(':',1)#split以:进行字符切割,
            #将切得到的两部分内容依次存放在role与line_spoken中
            if role == '小甲鱼':
                boy.append(line_spoken)
            if role == '小客服':
                girl.append(line_spoken)
        else:
            save_file(boy,girl,count)

            boy = []
            girl = []
            count += 1


    save_file(boy,girl,count)
    f.close()

split_file('record.txt')

030 文件系统:介绍一个高大上的东西

os模块中关于文件/目录常用的函数使用方法

>>> import os
>>> os.getcwd()
'D:\\python3.3.2\\小甲鱼python\\python程序\\第二十九课'

>>> os.listdir('D:\\python3.3.2\\小甲鱼python\\python程序\\第二十九课')
['boy_1.txt', 'boy_2.txt', 'boy_3.txt', 'girl_1.txt', 'girl_2.txt', 'girl_3.txt', 'record.txt', 'test.py', 'test2.py']

os.path模块中关于路径常用的函数使用方法

 >>> os.path.getsize('python.exe')  #获取文件的尺寸,返回值以字节为单位


031 永久存储:腌制一缸美味的泡菜(pickle)

python提供了一个标准的模块pickle可以非常容易地将列表、字典这类复杂的数据类型存储为文件。它几乎可以把所有python的对象都转化为二进制的形式存放,这个过程称为pickling,从二进制转换回对象的过程称为unpickling

pickling过程

>>> import pickle
>>> my_list = [123,3,14,'小甲鱼',['another list']]

>>> pickle_file = open('D:\\python3.3.2\小甲鱼python\python程序\第三十节课\my_list.pkl','wb')  #二进制写形式打开文件
>>> pickle.dump(my_list,pickle_file)
>>> pickle_file.close()

unpickling过程       

>>> import pickle
>>> pickle_file = open('D:\\python3.3.2\小甲鱼python\python程序\第三十节课\my_list.pkl','rb')#以二进制读形式打开文件
>>> my_list = pickle.load(pickle_file)
>>> print(my_list)
[123, 3, 14, '小甲鱼', ['another list']]

实例:城市天气打包

>>> pickle_file = open('D:\\python3.3.2\小甲鱼python\python程序\第三十一节课\city_data.pkl','wb')
>>> pickle.dump(city,pickle_file)
>>> pickle_file.close()

032 异常处理:你不可能总是对的

实例1:

file_name = input('请输入需要打开的文件名:')
file = open(file_name)
print('文件的内容是:')
for each_line in file:
    print(each_line)
file.close()

注:py文件与要打开的文件在同一个文件下则不需要加路径

Python标准异常总结

以下是 Python 内置异常类的层次结构:

        

033 异常处理:你不可能总是对的2

try-except语句

try:

  检测范围

except Exception[as reason]:

  出现异常(Exception)后的处理代码

实例1:

try:
    f = open('TE.txt')
    print(f.read())
    f.close()
except OSError:
    print('文件打开过程中出错了!!!')

实例2:

try:
    f = open('TE.txt')
    print(f.read())
    f.close()
except OSError as reason:
    print('文件打开出错原因是:\n' + str(reason))

实例3:

try:
    sum = 1 + '1'
    f = open('TE.txt')
    print(f.read())
    f.close()
except OSError as reason:
    print('文件打开出错原因是:\n' + str(reason))
except TypeError as reason:
    print('类型出错原因是:\n' + str(reason))

实例4(多个异常统一处理):

try:
    sum = 1 + '1'
    f = open('TE.txt')
    print(f.read())
    f.close()
except(OSError, TypeError):
    print('出错了')

注:try语句一旦检测到异常,剩下的语句将不会被执行

try-finally语句

try:

  检测范围

except Exception[as reason]:

  出现异常(Exception)后的处理代码

finally:

  无论如何都会被执行的代码

实例5:

try:
    f = open('test.txt')
    print(f.read())
    sum = 1 + '1'
except (OSError,TypeError)as reason:
    print('出错了\n原因是:' + str(reason))
finally:
    f.close()

raise语句可以自己抛出一个异常

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

丰富的else语句

要么怎样,要么不怎样

if 条件:
    条件为真执行
else:
    条件为假执行
      

干完了能怎样,干不完就别想怎样

实例1:

def showMaxFactor(num):
    count = num // 2#//为整除,判断是素数,只需依次判断当前数num除以1到(num // 2)都不能整除即可
    while count > 1:
        if num % count == 0:#判断是否整除
            print('%d最大的约数是%d' % (num, count))
            break#跳出循环后else并不执行
        count -= 1
    else:#当while循环不成立时,或者理解为while循环完全被执行完了,没有给中途跳出(即break)
        print('%d是素数!' % num)

num = int(input('请输入一个数:'))
showMaxFactor(num)

注:else与for语句搭配与while语句相同

没有问题?那就干

只要try语句块里没有出现任何异常,那么就会执行else语句块里的内容啦

实例2:

try:#尝试运行以下程序
    print(int('abc'))
except ValueError as reason:#如果程序有异常时
    print('出错了:' + str(reason))
else:#程序无异常时
    print('没有任何异常!')

实例3:

try:
    print(int('123'))
except ValueError as reason:
    print('出错了:' + str(reason))
else:
    print('没有任何异常!')

简洁的with语句(with会自动帮你关闭文件)

实例4:

try:
    with open('test.txt','w') as f:
        for each_line in f:
            print(each_line)
except (OSError,TypeError) as reason:
    print('出错了\n原因是:' + str(reason))

035 图形用户界面入门:EasyGui

图形用户界面编程,也就是平时常说的GUI(Graphical User  Interface),python有一个非常简单的GUI工具包:EasyGui

GUI的安装

导入方法一:

>>> import easygui         #导入EasyGui
>>> easygui.msgbox('嗨,亦我飞也')

导入方法二:

>>> from easygui import *
>>> msgbox('嗨,亦我飞也')

导入方法三(推荐使用):

>>> import easygui as g
>>> g.msgbox('嗨,亦我飞也')

显示图片(注:图片需要为GIF格式,且存放在python.exe通目录

>>> easygui.buttonbox(msg='你喜欢以下哪种水果',title='亦我飞也',choices=('草莓','西瓜','芒果'),image='aa.gif')

实例1:

import easygui as g
import sys
 
while 1:
    g.msgbox("嗨,欢迎进入第一个界面小游戏")
    msg = "请问你希望在鱼C工作室学习到什么知识呢"
    title="小游戏互动"
    choices=["谈恋爱","编程","OOXX","琴棋书画"]
    choice=g.choicebox(msg,title,choices)
 
    #note that we convert choice to string,in case
    #the user cancelled the choice,and we got None
    g.msgbox("你的选择是:"+str(choice),"结果")
    msg="你希望重新开始小游戏吗?"
    title=" 请选择"
    if g.ccbox(msg,title):  #show a Contiue/Cancel dialog
        pass #user chose Contonue
    else:
        sys.exit(0)  #user chose Cancel

修改窗口大小(choicebox)

修改文字大小(PROPORTIONAL_FONT)

036 类和对象:给大家介绍对象

给大家介绍对象

把乱七八糟的数据扔进列表里,称数据层面的封装

把常用的代码段打包成一个函数,称语句层面的封装

把数据和代码都封装在一起,称对象层面的封装

对象 = 属性 + 方法

对象可以从静态(属性)动态(方法)两个特征来描述

OO(面向对象)的特征

继承

class Turtle: # Python 中的类名约定以大写字母开头
    """关于类的一个简单例子"""
    # 属性
    color = 'green'
    weight = 10
    legs = 4
    shell = True
    mouth = '大嘴'

    # 方法
    def climb(self):
        print("我正在很努力的向前爬......")

    def run(self):
        print("我正在飞快的向前跑......")

    def bite(self):
        print("咬死你咬死你!!")

    def eat(self):
        print("有得吃,真满足^_^")

    def sleep(self):
        print("困了,睡了,晚安,Zzzz")

调用类中的方法:

>>> tt = Turtle()     #声明tt对象继承Turtle()
>>> tt.climb()
我正在很努力的向前爬......
>>> tt.bite()
咬死你咬死你!!

定义一个带列表类MyList,将list2对象继承于它,则列表的功能继承它的对象都可以使用

>>> class MyList(list):
    pass

>>> list2 = MyList()

>>> list2.append(5)
>>> list2.append(6)

>>> list2.append(1)
>>> list2
[5, 6, 1]
>>> list2.sort()
>>> list2
[1, 5, 6]

多态(下例中都调用的名字相同的方法,但实现不一样)

>>> class A:
    def fun(self):
        print('我是小A。。。')

        
>>> class B:
    def fun(self):
        print('我是小B。。。')

        
>>> a = A()
>>> b = B()
>>> a.fun()
我是小A。。。
>>> b.fun()
我是小B。。。

037 类和对象:面向对象编程

self是什么?

Python的self其实就相当于C++的this指针。由同一个类可以生产无数对象,当一个对象的方法被调用的时候,对象会将自身的引用作为第一个参数传给该方法,那么python就知道需要操作哪个对象的方法了。

>>> class Ball:
    def setName(self,name):
        self.name = name
    def kick(self):
        print('我叫%s,该死的,谁踢我。。。' % self.name)

        
>>> a = Ball()

>>> a.setName('球A')
>>> b = Ball()

>>> b.setName('球B')

>>> a.kick()
我叫球A,该死的,谁踢我。。。
>>> b.kick()
我叫球B,该死的,谁踢我。。。

你听说过Python的魔法方法吗?

python的这些具有魔法的方法,总是被双下划线所包围,例如__init__(),即构造方法,也称构造函数,这个方法会在对象被创建时自动调用。其实,实例化对象时是可以传入参数的,这些参数会自动传入__init__()方法中,可以通过重写这个方法来自定义对象的初始化操作

实例:

>>> class Ball():
    def __init__(self,name):
        self.name = name
    def kick(self):
        print('我叫%s,该死的,谁踢我。。。' % self.name)

        
>>> b = Ball('小土豆')
>>> b.kick()
我叫小土豆,该死的,谁踢我。。。

公有和私有?python内部采用了一种叫 name mangling(名字改编)的技术

默认上对象的属性和方法都是公开的,可以直接通过点操作符(.)进行访问:

>>> class Person:
    name = '亦我飞也'

    
>>> p = Person()
>>> p.name
'亦我飞也'

为了实现定义私有变量,只需要在变量名或函数名前加上"__"两个下划线,那么这个函数或变量就会变成私有的了:

私有变量不可以直接由外部访问

>>> class Person:
    __name = '亦我飞也'

    
>>> p = Person()
>>> p.__name
Traceback (most recent call last):
  File "<pyshell#65>", line 1, in <module>
    p.__name
AttributeError: 'Person' object has no attribute '__name'

室友变量可以由内部(内部函数)进行访问

>>> class Person:
    __name = '亦我飞也'
    def getName(self):
        return self.__name

    
>>> p = Person()
>>> p.__name
Traceback (most recent call last):
  File "<pyshell#72>", line 1, in <module>
    p.__name
AttributeError: 'Person' object has no attribute '__name'

>>> p.getName()
'亦我飞也'

其实,name mangling(名字改编)技术,只是把双下划线开头的变量进行了改名而已。实际上在外部使用“_类名__变量名“即可访问双下划线开头的私有变量了

>>> p._Person__name
'亦我飞也'

038 类和对象:继承

继承

                  子类                              父类

class DerivedClassName(BaseClassName):

……

实例:一个子类可以继承它的父类的所有属性和方法

>>> class Parent:
    def hello(self):
        print('正在调用父类的方法。。。')

        

>>> class Child(Parent):    #子类继承父类
    pass     #直接往下执行

>>> p = Parent()
>>> p.hello()
正在调用父类的方法。。。
>>> c = Child()
>>> c.hello()
正在调用父类的方法。。。

如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法和属性(即子类方法属性改变,父类是不变的)

>>> class Child(Parent):
    def hello(self):
        print('正在调用子类的方法')

        
>>> c = Child()
>>> c.hello()
正在调用子类的方法
>>> p.hello()
正在调用父类的方法。。。

实例2:

import random as r
class Fish:
    def __init__(self):
        self.x = r.randint(0,10)
        self.y = r.randint(0,10)

    def move(self):
        self.x -= 1
        print('我的位置是:',self.x,self.y)


class Goldfish(Fish):
    pass

class Garp(Fish):
    pass

class Shark(Fish):
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print('吃货的梦想就是天天有的吃')
            self.hungry = False
        else:
            print('太撑了,吃不下了!')

>>> fish = Fish()
>>> fish.move()
我的位置是: -1 10
>>> fish.move()
我的位置是: -2 10
>>> goldfish = Goldfish()
>>> goldfish.move()
我的位置是: 2 3
>>> goldfish.move()
我的位置是: 1 3
>>> shark = Shark()
>>> shark.eat()
吃货的梦想就是天天有的吃
>>> shark.eat()
太撑了,吃不下了!
>>> shark.move()    #报错原因时因为子类重写构造函数,覆盖了父类D的构造函数
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    shark.move()
  File "D:\python3.3.2\小甲鱼python\python程序\第三十八节课\fish.py", line 8, in move
    self.x -= 1
AttributeError: 'Shark' object has no attribute 'x'

注:继承父类属性的子类,其变量值只属于当前子类,是子类的局部变量

报错修改部分解决方法一:调用未绑定的父类方法

>>> shark = Shark()
>>> shark.move()
我的位置是: 2 1
>>> shark.move()
我的位置是: 1 1

报错修改部分解决方法二:使用super函数super函数会帮我们自动找到基类的方法,而且还自动为我们传入self参数

>>> shark = Shark()
>>> shark.move()
我的位置是: 1 1
>>> shark.move()
我的位置是: 0 1

多重继承

class DerivedClassName(Base1, Base2, Base3):

……

实例:子类c同时继承基类Base1和基类Base2

>>> class Base1:
    def fool1(self):
        print('我是fool1,我为Base1代言。。。')

        
>>> class Base2:
    def fool2(self):
        print('我是fool2,我为Base2代言。。。')

        
>>> class C(Base1,Base2):
    pass

>>> c = C()
>>> c.fool1()
我是fool1,我为Base1代言。。。
>>> c.fool2()
我是fool2,我为Base2代言。。。

039 类和对象:拾遗

组合(将需要的类一起进行实例化并放入新的类中)

实例:

class Turtle:
    def __init__(self,x):
        self.num = x

class Fish:
    def __init__(self,x):
        self.num = x

class Pool:
    def __init__(self,x,y):
        self.turtle = Turtle(x)
        self.fish = Fish(y)

    def print_num(self):
        print('水池里一共有乌龟 %d 条,鱼 %d 条' % (self.turtle.num,self.fish.num))

>>> pool = Pool(5,2)
>>> pool.print_num()
水池里一共有乌龟 5 条,鱼 2 条

现在要求定义一个类,叫水池,水池里要有乌龟和鱼。

类、类对象和实例对象

以下例子可见,对实例对象c的count属性赋值后,就相当于覆盖了类对象C的count属性。如果没有赋值覆盖,那么引用的是类对象的count属性

>>> a = C()
>>> b = C()
>>> c = C()
>>> print(a.count,b.count,c.count)
0 0 0
>>> c.count += 10
>>> print(a.count,b.count,c.count)
0 0 10
>>> C.count += 100
>>> print(a.count,b.count,c.count)
100 100 10

另外,如果属性的名字跟方法名相同,属性会覆盖方法:

>>> class C:
    def x(self):
        print('X-man')

        
>>> c = C()
>>> c.x()
X-man
>>> c.x = 1              #新定义对象c的一个x属性,并赋值为1
>>> c.x
1
>>> c.x()     #可见,方法x()已经被属性x给覆盖了
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    c.x()
TypeError: 'int' object is not callable

结论:不要试图在一个类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展;用不同的词性命名,如属性名用名词、方法名用动词,并使用骆驼命名法等。

到底什么是绑定?

实例1:(python严格要求需要有实例才能被调用,即绑定概念)

>>> class BB:
    def printBB():        #缺少self,导致无法绑定具体对象
        print('no zuo no die')

        
>>> BB.printBB()
no zuo no die
>>> bb = BB()
>>> bb.printBB()        #出现错误原因是由于绑定机制,自动把bb对象作为第一个参数传入
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    bb.printBB()
TypeError: printBB() takes 0 positional arguments but 1 was given

 

Python严格要求方法需要有实例才能被调用,这种限制其实就是Python所谓的绑定概念。

040 类和对象:一些相关的BIF

一些相关的BIF

issubclass(class, classinfo)  如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False

>>> class A:
    pass

>>> class B(A):
    pass

>>> issubclass(B,A)
True
>>> issubclass(B,B)   #一个类被认为是其自身的子类
True
>>> issubclass(B,object)      # object是所有类的基类
True
>>> class C:
    pass

>>> issubclass(B,C)
False

isinstance(object, classinfo)  如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False

>>> issubclass(B,C)       注:第一个参数如果不是对象,则永远返回False
False
>>> b1 = B()
>>> isinstance(b1,B)
True
>>> isinstance(b1,C)
False
>>> isinstance(b1,A)
True
>>> isinstance(b1,(A,B,C))
True

hasattr(object, name)  用来测试一个对象里是否有指定的属性,第一个参数(object)是对象,第二个参数(name)是属性名(属性的字符串名字)

>>> class C:
    def __init__(self,x=0):
        self.x = x

        
>>> c1 = C()
>>> hasattr(c1,'x')    
#注意,属性名要用引号括起来
True

 

getattr(object, name[, default])  返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数);若没有设置default参数,则抛出异常

>>> getattr(c1,'x')
0
>>> getattr(c1,'y')

Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    getattr(c1,'y')
AttributeError: 'C' object has no attribute 'y'

setattr(object, name, value)  可以设置对象中指定属性的值,如果指定的属性不存在,则会新建属性并赋值
>>> setattr(c1,'y','FishC')
>>> getattr(c1,'y')
'FishC'

delattr(object, name)  用于删除对象中指定的属性,如果属性不存在,抛出异常。

>>> delattr(c1,'y')
>>> delattr(c1,'Z')

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    delattr(c1,'Z')
AttributeError: Z

property(fget=None, fset=None, fdel=None, doc=None)  用来通过属性设置属性,第一个参数是获取属性的方法名,第二个参数是设置属性的方法名,第三个参数是删除属性的方法名

>>> class C:
    def __init__(self,size =10):
        self.size = size
    def getSize(self):
        return self.size
    def setSize(self,value):
        self.size = value
    def delSize(self):
        del self.size
    x=property(getSize,setSize,delSize)

    

>>> c = C()
>>> c.x         #调用getSize()
10
>>> c.x = 12      #调用SetSize()
>>> c.x
12
>>> c.size
12
>>> del c.x      #调用DelSize()
>>> c.size
Traceback (most recent call last):
  File "<pyshell#53>", line 1, in <module>
    c.size
AttributeError: 'C' object has no attribute 'size'

041 魔法方法:构造和析构

__init__(self[, ...]) 方法是类在实例化成对象的时候首先会调用的一个方法

>>> class Rectangle:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def getPeri(self):
        return (self.x + self.y) * 2
    def getArea(self):
        return self.x * self.y

>>> rect = Rectangle(5,2)
>>> rect.getPeri()
14
>>> rect.getArea()
10

   注:__init__()方法的返回值一定是None 

其实,__new__()才是在一个对象实例化时候所调用的第一个方法,它的第一个参数是这个类(cla),而其他的参数会直接传递给__init__()方法

__new__(cls[, ...])

>>> class CapStr(str):
    def __new__(cls,string):
        string = string.upper()
        return str.__new__(cls,string)

    
>>> a = CapStr('hello world')
>>> a
'HELLO WORLD

__del__(self)  当对象将要被销毁的时候,这个方法就会被调用。但要注意,并非del x就相当于调用x.__del__(),__del__()方法是当垃圾回收机制回收这个对象的时候才调用的。

>>> class C:
    def __init__(self):
        print('我是__init__方法,我被调用了...')
    def __del__(self):
        print('我是__del__方法,我被调用l...')

        
>>> c1 = C()     #创建对象c1
我是__init__方法,我被调用了...
>>> c2 = c1
>>> c3 = c2
>>> del c1
>>> del c2
>>> del c3   #删除c3时,对象c1才会彻底被删除(即没有标签指向对象c1时,其才会被回收)
我是__del__方法,我被调用l...

042 魔法方法:算术运算

python2.2以后,对类和类型进行了统一,做法就是讲int()、float()、str()、list()、tuple()这些BIF转换为工厂函数(类对象):

>>> type(len)
<class 'builtin_function_or_method'>            #普通的BIF
>>> type(int)
<class 'type'>             #工厂函数(类对象),当调用它们的时候,其实就是创建了一个相应的实例对象
>>> type(dir)
<class 'builtin_function_or_method'>
>>> type(list)
<class 'type'>

>>> a = int('123')        #创建一个相应的实例对象a
>>> b = int('345')
>>> a + b              #python在两个对象进行相加操作
468

举个例子,下面定义一个比较特立独行的类:

>>> class New_int(int):
    def __add__(self,other):
        return int.__sub__(self,other)
    def __sub__(self,other):
        return int.__add__(self,other)

    
>>> a = New_int(3)
>>> b = New_int(5)
>>> a + b    #两个对象相加,触发 __add__(self,other)方法
-2
>>> a - b
8
>>>

实例2:

>>> class New_int(int):
    def __add__(self,other):
        return (int(self) + int(other))       #将self与other强制转换为整型,所以不会出现两个对象相加触发__add__()方法
    def __sub__(self,other):
        return (int(self) - int(other))

    
>>> a = New_int(3)
>>> b = New_int(5)
>>> a + b
8

043 魔法方法:算术运算2

实例1:

>>> class int(int):
    def __add__(self,other):
        return int.__sub__(self,other)

    
>>> a = int(3)
>>> b = int(2)
>>> a + b
1

反运算:

反运算与算术运算符的不同之处是,反运算多了一个'r',例如 __add__()的反运算对应为 __radd__()

>>> a + b

这里a是加数,b是被加数,如果a对象的__add__()方法没有实现或者不支持相应的操作,那么python就会自动调用b的__radd__()方法

实例:

>>> class Nint(int):
    def __radd__(self,other):
        return int.__sub__(self,other)

    
>>> a = Nint(5)
>>> b = Nint(3)
>>> a + b      #由于a对象默认有__add__()方法,所以b的__radd__()没有执行
8

实例2:

>>> class Nint(int):
    def __radd__(self,other):
        return int.__sub__(self,other)

    
>>> b = Nint(5)
>>> 3 + b         #由于3无__add__()方法,所以执行b的反运算__radd__(self,other)方法,其中self是b对象
2

注:在重写反运算魔法方法时,一定要注意顺序问题。

增量赋值运算:

比较操作符:

其它操作符:

044 魔法方法:简单定制

简单定制

基本要求:

定制一个计时器的类

startstop方法代表启动计时和停止计时

假设计时器对象t1print(t1)和直接调用t1均显示结果

当计时器未启动或已经停止计时,调用stop方法会给予温馨的提示

两个计时器对象可以进行相加:t1 + t2

只能使用提供的有限资源完成

你需要这些资源

使用time模块的localtime方法获取时间

扩展阅读:time 模块详解(时间获取和转换)

有关time模块的localtime方法获取时间(参考:

https://fishc.com.cn/forum.php?mod=viewthread&tid=51326&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403

time.localtime返回struct_time的时间格式

表现你的类:__str__ __repr__

实例:

import time as t   #导入时间模块,调用对象t

class Mytimer():
    def __init__(self):
        self.unit = ['年','月','天','小时','分钟','秒']
        self.prompt = "未开始计时"
        self.lasted = []
        self.begin = 0  #属性
        self.end = 0
    def __str__(self):
        return self.prompt

    __repr__ = __str__

    def __add__(self,other):   #重写加法操作符,运行时间相加
        prompt = "总共运行了"
        result = []
        for index in range(6):
            result.append(self.lasted[index] + other.lasted[index])
            if result[index]:
                prompt += (str(result[index]) + self.unit[index])
        return prompt
                           
    #开始计时
    def start(self):    #方法,属性名和方法名不能相同
        if not self.stop:
            self.prompt = ("提示:请先调用stop()停止计时!")
        else:
            self.begin = t.localtime()
            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 = 0
        self.end = 0

>>> t1 = Mytimer()
>>> t1.stop()
提示:请先调用start()进行计时!
>>> t1.start()
计时开始...
>>> t1.stop()
计时结束!
>>> t1
总共运行了4秒
>>> t2 = Mytimer()
>>> t2.start()
计时开始...
>>> t2.stop()
计时结束!
>>> t2
总共运行了4秒
>>> t1 + t2
'总共运行了8秒'        

进阶定制

如果开始计时的时间是202222216:30:30,停止时间是202512315:30:30,那按照我们用停止时间减开始时间的计算方式就会出现负数3-11-1小时)你应该对此做一些转换

现在的计算机速度都非常快,而我们这个程序最小的计算单位却只是秒,精度是远远不够的

045 魔法方法:属性访问

属性访问

__getattr__(self, name)

定义当用户试图获取一个不存在的属性时的行为

__getattribute__(self, name)

定义当该类的属性被访问时的行为

__setattr__(self, name, value)

定义当一个属性被设置时的行为

__delattr__(self, name)

定义当一个属性被删除时的行为

实例1:

class 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')

>>> c = C()
>>> c.x
getattribute
getattr
>>> c.x = 1
setattr
>>> c.x
getattribute
1
>>> del c.x
delattr
>>> setattr(c,'y','Yellow')
setattr

练习要求

写一个矩形类,默认宽和高两个属性

如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都应该等于边长。

实例2:

class Rectangle:
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

    def __setattr__(self, name, value):#一发生赋值操作,则会触发__setattr__()魔法方法
        if name == 'square':#判断name属性是否为正方形
            self.width = value
            self.height = value
        else:
            self.__dict__[name] = value

    def getArea(self):
        return self.width * self.height

>>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100

046 魔法方法:描述符(Property的原理)

描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。

__get__(self, instance, owner)

用于访问属性,它返回属性的值

__set__(self, instance, value)

将在属性分配操作中调用,不返回任何内容

__delete__(self, instance)

控制删除操作,不返回任何内容

实例:

>>> class MyDecriptor:
    def __get__(self,instance,owner):
        print("getting...",self,instance,owner)
    def __set__(self,instance,value):
        print("setting...",self,instance,value)
    def __delete__(self,instance):
        print("deleting...",self,instance)

 

>>> class Test:
    x = MyDecriptor()   #取Mydecriptor类的实例指派给Test类的属性x

>>> test = Test()
>>> test.x
getting... <__main__.MyDecriptor object at 0x00000000033467F0> <__main__.Test object at 0x000000000335EF98> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x000000000335EF98>
>>> test.x = "X-man"
setting... <__main__.MyDecriptor object at 0x00000000033467F0> <__main__.Test object at 0x000000000335EF98> X-man
>>> del test.x
deleting... <__main__.MyDecriptor object at 0x00000000033467F0> <__main__.Test object at 0x000000000335EF98>

 

实例2:

>>> class MyProperty:
    def __init__(self,fget = None,fset = None,fdel = None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
    def __get__(self,instance,owner):
        return self.fget(instance)
    def __set__(self,instance,value):
        self.fset(instance,value)
    def __delete__(self,instance):
        self.fdel(instance)

        
>>> class C:
    def __init__(self):
        self._x = None
    def getX(self):
        return self._x
    def setX(self,value):
        self._x = value
    def delX(self):
        del self._x
    x = MyProperty(getX,setX,delX)

    
>>> c = C()
>>> c.x = "HELLOW"
>>> c.x
'HELLOW'
>>> c._x
'HELLOW'
>>> del c.x
>>> c._x
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    c._x
AttributeError: 'C' object has no attribute '_x'

练习要求

先定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性

要求个属性会自动进行转换,也就是说你可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。

实例3:

ss Celsius:  #摄氏度描述符类
    def __init__(self,value = 26.0):#self为描述符类自身(此为摄氏度描述符类)的实例(此为cel)
        self.value = float(value)
    def __get__(self,instance,owner):#instance是这个描述符的拥有者所在的类的实例(此为temp)
        return self.value
    def __set__(self,instance,value):#owner是这个描述符的拥有者所在的类本身(此为温度类)
        self.value = float(value)

class Fahrenheit:   #华氏度描述符类
    def __get__(self,instance,owner):
        return instance.cel * 1.8 +32  #摄氏度转华氏度
    def __set__(self,instance,value):
        instance.cel = ((float)(value)- 32)/ 1.8   #华氏度转摄氏度
        
class Temperature:   #温度类
    cel = Celsius()   #设置摄氏度属性(描述符类的实例指派给了温度类的属性)
    fah = Fahrenheit()#设置华氏度属性

>>> temp = Temperature()
>>> temp.cel
26.0
>>> temp.fah
78.80000000000001
>>> temp.fah = 78.8
>>> temp.cel
25.999999999999996

047 魔法方法:定制序列

协议是什么?

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

容器类型的协议

如果说你希望定制的容器是不可变的话,你只需要定义__len__()__getitem__()方法。

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

练习要求

编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数。

class CountList:  #定义记录列表中每个元素访问次数类
    def __init__(self,*args): #参数是可变类型的
        self.values = [x for x in args]#将args的数据存入列表self.values中
        self.count = {}.fromkeys(range(len(self.values)),0)#创建字典,初试化为0

    def __len__(self):  #返回容器中元素的个数
        return len(self.values)#len方法用于返回参数的长度 
    def __getitem__(self,key):  #获取容器中指定元素的行为,key为访问对应的键
        self.count[key] += 1#每访问一次,字典键对应的键值加1
        return self.values[key]

>>> c1 = CountList(1,3,5,7,9)
>>> c2 = CountList(2,4,6,8,10)
>>> c1[1]  #c1[1]第一次访问
3
>>> c2[2]
6
>>> c1[1] + c2[2] #c1[1]第二次访问
9
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
>>> c2.count
{0: 0, 1: 0, 2: 2, 3: 0, 4: 0}

048 魔法方法:迭代器

迭代的意思类似于循环,每一次重复的过程被称为一次迭代的过程,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。提供迭代方法的容器称为迭代器(如序列(列表、元组、字符串)、字典等)。

对一个容器对象调用iter()就得到它的迭代器,调用next()迭代器就会返回下一个值。入托迭代器没有值可以返回了,就会抛出异常。

•iter()

–__iter__()

•next()

–__next__()

实例1:

>>> string = "FishC"
>>> it = iter(string)
>>> next(it)
'F'
>>> next(it)
'i'
>>> next(it)
's'
>>> next(it)
'h'
>>> next(it)
'C'
>>> next(it)
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    next(it)
StopIteration

一个容器如果是迭代器,那就必须实现__iter__()魔法方法,这个方法实际上就是返回迭代器本身。重点要实现的是__next__()魔法方法,因为它决定了迭代的规则。

实例2:

>>> class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def __iter__(self):
        return self
    def __next__(self):
        self.a,self.b = self.b,self.a + self.b
        return self.a

    
>>> fibs = Fibs()
>>> for each in fibs:
    if each < 20:
        print(each)
    else:
        break

    
1
1
2
3
5
8
13

实例3:

 

>>> class Fibs:
    def __init__(self,n =20):
        self.a = 0
        self.b = 1
        self.n = n
    def __iter__(self):
        return self
    
    def __next__(self):
        self.a,self.b = self.b,self.a + self.b
        if self.a > self.n:
            raise StopIteration
        return self.a

    
>>> fibs = Fibs()
>>> for each in fibs:
    print(each)

    
1
1
2
3
5
8
13

 

>>> fibs = Fibs(10)
>>> for each in fibs:
    print(each)

    
1
1
2
3
5
8

 

049 乱入:生成器

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

生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。

一个函数中如果有yield语句,则被定义为生成器。

实例1:

>>> def myGen():
    print("生成器被执行了!")
    yield 1   #暂停一次,相当于return,返回1
    yield 2     #暂停一次,相当于return,返回2

    
>>> myG = myGen()
>>> next(myG)
生成器被执行了!
1
>>> next(myG)
2

像前面介绍的斐波那契的例子,也可以用生成器来实现:

>>> def fibs():
    a = 0
    b = 1
    while True:
        a,b = b,a + b
        yield a

        
>>> for each in fibs():
    if each > 100:
        break
    print(each)

    
1
1
2
3
5
8
13
21
34
55
89

列表推导式表达:

100以内,能被2整除,但不能被3整除的所有整数

>>> a = [i for i in range(100) if not (i % 2) and (i % 3 )]
>>> a
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]

字典推导式:

10以内是否为偶数

>>> a = {i:i % 2 == 0 for i in range(10)}
>>> a
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}

集合推导式:

>>> a = {i for i in [1,2,3,3,4,5,5,5,6,7,7,8]}
>>> a
{1, 2, 3, 4, 5, 6, 7, 8}

元组生成器推导式:

>>> e = (i for i in range(5))
>>> next(e)
0
>>> next(e)
1
>>> next(e)
2

050 模块:模块就是程序

什么是模块

容器 -> 数据封装

函数 -> 语句封装

-> 方法和属性的封装

模块 -> 模块就是程序

命名空间

爱的宣言:世界上只有一个名字,使我这样牵肠挂肚,像有一根看不见的线,一头牢牢系在我心尖上,一头攥在你手中,这个名字就叫做鱼C工作室计算机一班的小花……

导入模块

第一种:import 模块名

实例1:import导入模块

实例2:import导入模块

第二种:from 模块名 import 函数名(不推荐使用)

第三种:import 模块名 as 名字(推荐使用)

TemperatureConversion文件:

def c2f(cal):
    return cal * 1.8 + 32
def f2c(fah):
    return (fah - 32)/1.8

calc文件:

import TemperatureConversion as tc  #tc为取得新名字

print("32摄氏度 = %.2f 华氏度\n" % tc.c2f(32))
print("99华氏度 = %.2f 摄氏度" % tc.f2c(99))

051 模块:__name__='__main__'、搜索路径和包

模块!模块!

实例1:为TemperatureConversion添加测试程序(TemperatureConversion被作为程序运行)

def c2f(cal):
    return cal * 1.8 + 32

def f2c(fah):
    return (fah - 32)/1.8

def test():
    print("0摄氏度 = %.2f 华氏度\n" % c2f(0))
    print("0华氏度 = %.2f 摄氏度" % f2c(0))

test()

运行calc文

当希望TemperatureConversion被调用时作为模块导入时

def c2f(cal):
    return cal * 1.8 + 32

def f2c(fah):
    return (fah - 32)/1.8

def test():
    print("0摄氏度 = %.2f 华氏度" % c2f(0))
    print("0华氏度 = %.2f 摄氏度" % f2c(0))

if __name__ == "__main__":#当此文件当做程序运行时,执行test(),否则不执行
    test()

运行calc文件

if __name__ == ‘__main__’

搜索路径(系统会首先搜索的路径)

>>> import sys
>>> sys.path
['D:\\python3.3.2\\小甲鱼python\\python程序\\第五十节课\\Temperature', 'D:\\python3.3.2\\Lib\\idlelib', 'C:\\windows\\system32\\python33.zip', 'D:\\python3.3.2\\DLLs', 'D:\\python3.3.2\\lib', 'D:\\python3.3.2', 'D:\\python3.3.2\\lib\\site-packages']

添加搜索路径:

>>> import TemperatureConversion
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import TemperatureConversion
ImportError: No module named 'TemperatureConversion'

>>> import sys
>>> sys.path.append("D:\\python3.3.2\WODE\Temperature")
>>> sys.path
['', 'D:\\python3.3.2\\Lib\\idlelib', 'C:\\windows\\system32\\python33.zip', 'D:\\python3.3.2\\DLLs', 'D:\\python3.3.2\\lib', 'D:\\python3.3.2', 'D:\\python3.3.2\\lib\\site-packages', 'D:\\python3.3.2\\WODE\\Temperature']
>>> import TemperatureConversion
>>> TemperatureConversion.f2c(59)
15.0

package

1.创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字;

2.文件夹中创建一个__init__.py的模块文件,内容可以为空;

3.相关的模块放入文件夹中

052 模块:像个极客一样去思考

使用print调用__doc__属性,可以带格式查看这个模块的简介

使用dir()可以查询到该模块定义了哪些变量、函数和类

053 论一只爬虫的自我修养

Python如何访问互联网?

 

URL的一般格式为(带方括号[]的为可选项)

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

URL由三部分组成:

第一部分是协议httphttpsftpfileed2k…

第二部分是存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口为80)。

第三部分是资源的具体地址,如目录文件名

054 论一只爬虫的自我修养2:实战

import urllib.request

response = urllib.request.urlopen('http://placekitten.com/g/500/600')#  返回文件对象response
cat_imag = response.read()

with open('cat_500_600.jpg','wb') as f:
    f.write(cat_imag)

>>> response.geturl()
'http://placekitten.com/g/500/600'
>>> response.info()
<http.client.HTTPMessage object at 0x00000000034EAA20>
>>> print(response.info())
Date: Sat, 27 Jul 2019 02:44:18 GMT
Content-Type: image/jpeg
Transfer-Encoding: chunked
Connection: close
Set-Cookie: __cfduid=d3cd08233581619b9ef8464ae93f7d5ff1564195458; expires=Sun, 26-Jul-20 02:44:18 GMT; path=/; domain=.placekitten.com; HttpOnly
Access-Control-Allow-Origin: *
Cache-Control: public, max-age=86400
Expires: Sun, 28 Jul 2019 02:44:18 GMT
CF-Cache-Status: HIT
Age: 66459
Vary: Accept-Encoding
Server: cloudflare
CF-RAY: 4fcb454ecc35ce6b-LHR


>>> response.getcode()
200

055 论一只爬虫的自我修养3:隐藏

修改 headers

通过Requestheaders参数修改

通过Request.add_header()方法修改

代理

步骤:

1. 参数是一个字典 {‘类型’:‘代理ip:端口号’}

proxy_support = urllib.request.ProxyHandler({})

 

2. 定制、创建一个 opener

opener = urllib.request.build_opener(proxy_support)

 

3a. 安装 opener

urllib.request.install_opener(opener)

3b. 调用 opener

opener.open(url)

 

064 GUI的终极选择:Tkinter

 

>>> import tkinter   #Tkinter是python默认的GUI库,导入Tkinter模块
>>> 

实例1:

import tkinter as tk

root = tk.Tk()#创建一个主窗口,用于容纳整个GUI程序
root.title("FishC Demo")#设置主窗口对象的标题栏

#添加一个Label组件,可以显示文本、图标或者图片(此处显示文本)
theLabel = tk.Label(root,text = "我的第二个窗口程序")
theLabel.pack()#调用Label组件的pack方法,用于自动调节组件自身尺寸

root.mainloop()#执行此语句后,窗口才会显示,程序进入主事件循环

实例2:

import tkinter as tk

class App:#创建类App
    def __init__(self,root):#self为指向App类的指针
        #创建一个框架,然后在里面添加一个Button按钮组件,框架用来将复杂布局中按钮分组
        frame = tk.Frame(root)
        frame.pack(side = tk.RIGHT,padx = 10,pady = 10)#调节框架自身尺寸,此处设置为右对齐(右上角为原点),偏移(10,10)
        
        #创建一个按钮组件,fg(foreground),设置前景色
        #创建一个Button按钮,属性为self.hi_there,属于frame框架,按钮按下时调用self.say_hi方法
        #设置前景色为黑色,背景色为白色
        self.hi_there = tk.Button(frame,text = "打招呼",bg = "black",fg = "white",command = self.say_hi)
        self.hi_there.pack()#自动调节自身尺寸
        
        #say_hi()方法定义实现   
    def say_hi(self):
        print("互联网广大朋友们好,我是亦我飞也!")
        
        
root = tk.Tk()#创建一个主窗口(toplever的根窗口),并把它作为参数实例化app对象,用于容纳整个GUI程序,
app = App(root)#创建类App的一个实例对象app,传入参数为root

app.mainloop()#执行此语句后,窗口才会显示,程序进入主事件循环
 

065 GUI的终极选择:Tkinter2

实例1:Label组件显示文字与gif图片

#导入tkinter模块的所有内容
from tkinter import *

#创建主窗口
root = Tk()
#创建一个文本Label对象,文字为左对齐,离左边边框距离为10
textLabel = Label(root,
                  text = "您下载的影片含有未成年人限制内容,\n请满18周岁后再点击观看!",
                  justify = LEFT,padx = 10)
#Label组件为左对齐
textLabel.pack(side = LEFT)

#创建一个图像Label对象
#用PhotoImage实例化一个图片对象(支持gif格式的图片)
photo = PhotoImage(file = "18.gif")
imgLabel = Label(root,image = photo)
imgLabel.pack(side = RIGHT)

mainloop()
 

实例2:

例2:文字显示在图片上

#导入tkinter模块的所有内容
from tkinter import *

#创建主窗口
root = Tk()

#创建一个图像Label对象
photo = PhotoImage(file = "bg.gif")
#创建一个文本Label对象
textLabel = Label(root,
                  text = "学Python\n到FishC!",
                  font = ("宋体",20),
                  fg = "white",
                  justify = LEFT,  #文字左对齐
                  image = photo,
                  compound = CENTER, #设置文本和图像的混合模式
                  )
#文本Label对象偏移,离左窗口与上窗口都为10
textLabel.pack(side = LEFT,padx =10,pady =10)

mainloop()
 

实例2:Button组件

#导入tkinter模块的所有内容
from tkinter import *

def callback():
    var.set("吹吧你,我才不信呢~")

#创建主窗口
root = Tk()
#设置主窗口对象的标题栏
root.title("TK")

frame1 = Frame(root)#框架1
frame2 = Frame(root)#框架2

#创建一个文本Label对象,文字为左对齐
var = StringVar()
var.set("您下载的影片含有未成年人限制内容,\n请满18周岁后再点击观看!")
textLabel = Label(frame1,
                  textvariable = var, #Button显示一个StringVar的变量
                  justify = LEFT)
#Label组件为左对齐
textLabel.pack(side = LEFT)

#创建一个图像Label对象
#用PhotoImage实例化一个图片对象(支持gif格式的图片)
photo = PhotoImage(file = "18.gif")
imgLabel = Label(root,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()

066 GUI的终极选择:Tkinter3

实例1:Checkbutton 组件

from tkinter import *

root = Tk()
#需要一个Tkinter变量,用于表示该按钮是否被选中
v = IntVar()
c = Checkbutton(root,text="测试一下",variable = v)

c.pack()
#如果被选中,那么变量v被赋值为1,否则为0
#可以用个Label标签动态地给大家展示:
lable = Label(root,textvariable = v)
lable.pack()

mainloop()

实例2:

from tkinter import *

root = Tk()

GIRLS = ["貂蝉","王昭君","西施","杨玉环"]
v = []
for girl in GIRLS:
    v.append(girl)
    c = Checkbutton(root,text = girl,variable = v[-1])#-1表示每次取v列表中最后一个元素,即刚加入的那个元素
    c.pack(anchor = W)#W(western)向左对齐

mainloop()

实例3:Radiobutton 组件

from tkinter import *

root = Tk()

v = IntVar()#如果被选中,v被赋值为1,否则为0
Radiobutton(root,text = "One",variable = v,value = 1).pack(anchor = W)
#value表示第一个按钮被选中时,v的值赋值给variable

Radiobutton(root,text = "Two",variable = v,value = 2).pack(anchor = W)

Radiobutton(root,text = "Three",variable = v,value = 3).pack(anchor = W)

Radiobutton(root,text = "Four",variable = v,value = 4).pack(anchor = W)

mainloop()

实例4:循环处理

from tkinter import *

root = Tk()

LANGS = [
    ("Python",1),
    ("Perl",2),
    ("Ruby",3),
    ("Lua",4)]
     

v = IntVar()#如果被选中,v被赋值为1,否则为0
v.set(1)#将1设置为默认值
for lang,num in LANGS:
    b= Radiobutton(root,text = lang,variable = v,value = num)
    b.pack(anchor = W)
#value表示第一个按钮被选中时,v的值赋值给variable

mainloop()

实例5:改成按钮形式

from tkinter import *

root = Tk()

LANGS = [
    ("Python",1),
    ("Perl",2),
    ("Ruby",3),
    ("Lua",4)]
     

v = IntVar()#如果被选中,v被赋值为1,否则为0
v.set(1)#将1设置为默认值
for lang,num in LANGS:
    b= Radiobutton(root,text = lang,variable = v,value = num,indicatoron = False)
    b.pack(fill = X)#表示横向填充
#value表示第一个按钮被选中时,v的值赋值给variable

mainloop()

实例6:LabelFrame 组件

from tkinter import *

root = Tk()

group = LabelFrame(root,text = "最好的脚本语言是?",padx = 10,pady = 10)#按钮相对边框的偏移
group.pack(padx = 10,pady = 10)#框架相对边框的偏移

LANGS = [
    ("Python",1),
    ("Perl",2),
    ("Ruby",3),
    ("Lua",4)]
     

v = IntVar()#如果被选中,v被赋值为1,否则为0
v.set(1)#将1设置为默认值
for lang,num in LANGS:
    b= Radiobutton(group,text = lang,variable = v,value = num,indicatoron = False)
    b.pack(fill = X)
#value表示第一个按钮被选中时,v的值赋值给variable

mainloop()

067 GUI的终极选择:Tkinter4

实例1:

from tkinter import *

root = Tk()#创建主窗口
e = Entry(root)#在主窗口中插入输入框
e.pack(padx = 20,pady = 20)

e.delete(0,END)#清空输入框
e.insert(0,"默认文本...")#设置输入框内容

mainloop()

实例2:

from tkinter import *

def button1_show():
    print("作品:《%s》" % e1.get())#将e1.get()中得到的输入框1的内容格式化为字符串
    print("作者:%s" % e2.get())

root = Tk()#创建主窗口

Label(root,text = "作品:",padx = 20,pady = 10).grid(row=0,column=0)#第1行第1列,偏移是相对于当前操作组件的相邻x轴或y轴的偏移距离
Label(root,text = "小甲鱼:").grid(row=1,column=0)#第1行第0列


e1 = Entry(root)#在主窗口中插入输入框,文本框的内容通过e1调用
e2 = Entry(root)#在主窗口中插入输入框
e1.grid(row=0,column=1,padx=10)#x方向偏移是相对于"作品"的x方向偏移的;y方向偏移表示此输入框与y方向相邻物体或边框之间偏移的距离(y方向偏移)
e2.grid(row=1,column=1,padx=10,pady=20)#x方向偏移是相对于"小甲鱼"的x方向偏移的;y方向偏移表示此输入框与y方向相邻上下物体或边框偏移的距离(y方向偏移)


#加两个按钮
Button1 = Button(root,text = "获取信息",command = button1_show)\
          .grid(row = 2,column = 0,sticky = W,padx = 10,pady=10)#加入反斜杠可实现分行编辑,方位设置为最西边(即靠左)
Button2 = Button(root,text = "退出",command = root.quit).grid(row = 2,column = 1,sticky = E,padx=10)#方位设置为最东边(即靠右)

#注:双击打开文件时退出才有效
e1.delete(0,END)#清空输入框
e1.insert(0,"零基础入门学习Python")#设置输入框内容

e2.delete(1,END)#清空输入框
e2.insert(1,"小甲鱼")#设置输入框内容

mainloop()

按下获取信息

更改输入框数据,然后按下获取信息

实例2:账号密码设置

from tkinter import *

def show():
    print("作品:《%s》" % e1.get())#将e1.get()中得到的输入框1的内容格式化为字符串
    print("作者:%s" % e2.get())
    e1.delete(0,END)#清空输入框1
    e2.delete(0,END)#清空输入框2

root = Tk()#创建主窗口
#Tkinter总共提供了三种布局组件的方法:pack()、grid()和place()
#grid()方法允许你用表格的形式来管理组件的位置
#row选项代表行,coulumn选项代表列
#row = 1,column = 2表示第二行第三列(0表示第一行)

Label(root,text = "账号:").grid(row=0)#第1行
Label(root,text = "密码:").grid(row=1)#第2行
v1 = StringVar()
v2 = StringVar()

e1 = Entry(root,textvariable = v1)#在主窗口中插入输入框,文本框的内容通过e1调用
e2 = Entry(root,textvariable = v2,show="*")#在主窗口中插入输入框
e1.grid(row=0,column=1,padx=10,pady=5)#x方向偏移是相对于"作品"的x方向偏移的;y方向偏移表示此输入框与y方向相邻物体或边框之间偏移的距离(y方向偏移)
e2.grid(row=1,column=1,padx=10,pady=5)#x方向偏移是相对于"小甲鱼"的x方向偏移的;y方向偏移表示此输入框与y方向相邻上下物体或边框偏移的距离(y方向偏移)


#可以使用sticky选项来设置组件的位置
#使用N、E、S、W以及他们的组合NE、SE、SW、NW来表示方位

#加两个按钮
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()

实例3:验证函数validatecommand

from tkinter import *

master = Tk()

def test():
    if e1.get() == "小甲鱼":
        print("正确!")
        return True
    else:
        print("错误!")
        e1.delete(0, END)
        return False

v = StringVar()

#focusout表示Entry组件失去焦点的时候验证,调用validatecommand的test函数

e1 = Entry(master, textvariable=v, validate="focusout", validatecommand=test)
e2 = Entry(master)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)

mainloop()
 

实例4:invalidcommand函数

from tkinter import *

master = Tk()

def test():
    if e1.get() == "小甲鱼":
        print("正确!")
        return True
    else:
        print("错误!")
        e1.delete(0, END)
        return False

def test2():
    print("我被调用了...")

v = StringVar()

#focusout表示Entry组件失去焦点的时候验证,调用validatecommand的test函数
#invalidcommand选项指定的函数只有在validatecommand的返回值为False的时候才被调用
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()
 

实例5:验证函数提供一些额外的选项

validatecommand(f,s1,s2,...)

其中,f是验证函数名,s1,s2,s3是额外的选项,这些选项会作为参数一次传给f函数。在此之前,需要调用register()方法将验证函数包装起来。

from tkinter import *

master = Tk()

v = StringVar()

def test(content, reason, name):
    if content == "小甲鱼":
        print("正确!")
        print(content, reason, name)
        return True
    else:
        print("错误!")
        print(content, reason, name)
        return False

testCMD = master.register(test)
e1 = Entry(master, textvariable=v, validate="focusout", \
           validat
           ecommand=(testCMD, '%P', '%v', '%W'))
e2 = Entry(master)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)

mainloop()
 

实例6:设计一个 计算器

from tkinter import *
#计算函数
def calc():
    result = int(v1.get())+int(v2.get())#强制转换为整型
    v3.set(result)#将result中的内容放到v3中

#创建窗口
root = Tk()
#创建窗口中的一个frame框架
frame = Frame(root)
#设置框架位置并显示
frame.pack(padx = 10,pady = 10)

v1 = StringVar()
v2 = StringVar()
v3 = StringVar()

#注意,这里不能使用e1.get()或者v1.get()来获取输入的内容,因为validate选项
#指定为“key"的时候,有任何输入操作都会被拦截到这个函数中
#也就是说先拦截,只有这个函数返回True,那么输入的内容才会到变量里去
#所以要用%P来获取最新的输入框内容
def test(content):
    if content.isdigit():
        return True
    else:
        return False

#创建三个Entry组件
testCMD = frame.register(test)
#创建2个输入组件,输入的数据赋值给v1、v2
e1 = Entry(frame, textvariable=v1,width=10, validate="key",\
           validatecommand=(testCMD, '%P'))
e2 = Entry(frame, textvariable=v2,width=10, validate="key",\
           validatecommand=(testCMD, '%P'))
#一个输出组件,设置为只读模式(readonly),v3的数据赋值给textvariable进行输出显示
e3 = Entry(frame, textvariable=v3,width=10, validate="key",\
           validatecommand=(testCMD, '%P'),state="readonly")
#位置设置
e1.grid(row=0,column=0,padx=10,pady=10)
e2.grid(row=0,column=2,padx=10)
e3.grid(row=0,column=4,padx=10)

#创建两个Label组件
Label(frame,text="+").grid(row=0,column=1)
Label(frame,text="=").grid(row=0,column=3)

#创建一个按钮,宽度为10
button=Button(frame,text="计算结果",width=10,command=calc)
button.grid(row=1,column=2,pady=10)

mainloop()

068 GUI的终极选择:Tkinter5

Listbox组件

如果需要提供选项给用户选择,单选可以用Radiobutton组件,多选可以用Checkbutton,如果提供的选项非常多,可以考虑使用Listbox组件。Listbox是以列表的形式显示出来,并支持滚动条操作。

实例1:

from tkinter import *

root = Tk()#创建主窗口

theLB = Listbox(root,setgrid = True,selectmode=EXTENDED)#创建一个空列表
theLB.pack()

#往列表里添加数据
for item in ["鸡蛋","鸭蛋","鹅蛋","李狗蛋"]:
    theLB.insert(END,item)#每次在列表最后插入一个数据

#创建一个按钮,ACTIVE表示当前选中的数据
theButton = Button(root,text="删除",command = lambda x = theLB:x.delete(ACTIVE))
theButton.pack()

#theLB.delete(0,END)删除所有列表数据

mainloop()

注:listbox.delete(0,END)可以删除列表中所有项目

实例2:添加height选项

from tkinter import *

root = Tk()#创建主窗口

#height=11表示可以显示11个项目
theLB = Listbox(root,setgrid = True,\
                selectmode=BROWSE,height=11)#创建一个空列表,选择模式为单选
theLB.pack()

#往列表里添加数据
for item in range(11):
    theLB.insert(END,item)#每次在列表最后插入一个数据

#创建一个按钮,ACTIVE表示当前选中的数据
theButton = Button(root,text="删除",command = lambda x = theLB:x.delete(ACTIVE))
theButton.pack()

#theLB.delete(0,END)删除所有列表数据

mainloop()

Scrollbar组件

实例1:

from tkinter import *

root = Tk()#创建主窗口

sb = Scrollbar(root)
sb.pack(side=RIGHT,fill=Y)

lb = Listbox(root,yscrollcommand=sb.set)#创建一个空列表
for i in range(1000):
    lb.insert(END,i)
lb.pack(side=LEFT,fill=BOTH)

sb.config(command = lb.yview)

mainloop()

事实上,这是一个互联互通的过程。当用户操作滚动条时,滚动条响应滚动并同时通过Listbox组件的yview()方法滚动列表框里的内容;同样,当列表框中可视范围发生改变的时候,Listbox组件通过调用Scrollbar组件的set()方法设置滚动条的最新位置。

Scale组件

Scale组件主要是通过滑块来表示某个范围内的一个数字,可以通过修改选项设置范围以及分辨率(精度)

实例1:

from tkinter import *

root = Tk()#创建主窗口
Scale(root,from_=0,to=42).pack()#创建铅锤方向滚动条
Scale(root,from_=0,to=200,orient=HORIZONTAL).pack()#创建水平方向滚动条

mainloop()

实例2:打印当前位置

from tkinter import *

def show():
    print(s1.get(),s2.get())#使用get()方法获取当前滑块的位置

root = Tk()#创建主窗口
s1 = Scale(root,from_=0,to=42)#创建铅锤方向滚动条
s1.pack()
s2 = Scale(root,from_=0,to=200,orient=HORIZONTAL)#创建水平方向滚动条
s2.pack()

#创建一个按钮
Button(root,text="获取位置",command=show).pack()

mainloop()

实例3:通过resolution选项控制分辨率(步长),通过tickinterval选项设置刻度

from tkinter import *

def show():
    print(s1.get(),s2.get())#使用get()方法获取当前滑块的位置

root = Tk()#创建主窗口
#tickinterval表示设置刻度,即每隔多少显示一个刻度
#length表示滚动条的长度所占的像素数
#resolution用来控制分辨率(步长)
s1 = Scale(root,from_=0,to=42,tickinterval=5,length=200,\
           resolution=5,orient=VERTICAL)#创建铅锤方向滚动条
s1.pack()
s2 = Scale(root,from_=0,to=200,tickinterval=10,\
           length=600,orient=HORIZONTAL)#创建水平方向滚动条
s2.pack()

#创建一个按钮
Button(root,text="获取位置",command=show).pack()

mainloop()

069 GUI的终极选择:Tkinter6

Text组件

Text(文本)组件用于显示和处理多种任务。虽然该组件的主要目的是显示多行文本,但它常常也被用于作为简单的文本编辑器和网页浏览器使用。

实例1:插入内容

from tkinter import *

root = Tk()
text = Text(root,width=30,height=2)
text.pack()
#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love\n")#光标当前的位置插入

#END,对应Text组件的文本缓存区最后一个字符的下一个位置
text.insert(END,"FishC.com!")

mainloop()

实例2:插入image对象windows组件

from tkinter import *

def show():
    print("哟,我被点了一下~")

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入

#创建一个按钮
b1=Button(root,text="点我点我",command=show)
text.window_create(INSERT,window=b1)

mainloop()
 

实例3:单击按钮显示一张图片

from tkinter import *

def show():
    text.image_create(INSERT,image=photo)

root = Tk()
text = Text(root,width=30,height=50)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入

photo = PhotoImage(file='fishc.gif')

#创建一个按钮
b1=Button(root,text="点我点我",command=show)
text.window_create(INSERT,window=b1)

mainloop()

Indexer用法

实例1:“line.column”

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
print(text.get(1.2,1.6))#获取第一行第2列到第一行第六列的数据

mainloop()

实例2:“line.end”

行号加上字符串".end"格式表示为该行最后一个字符的位置

实例:

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
print(text.get("1.2","1.end"))#获取第一行第2列到第一行第六列的数据

mainloop()

Mask用法

mask(标记)通常是嵌入到Text组件文本中的不可见对象。事实上,Marks是指定字符间的位置,并跟随相应的字符一起移动。

实例:Mark事实上就是索引,用于表示位置

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.mark_set("here","1.2")#设置光标位置为1.2
text.insert("here","插")

mainloop()

实例2:如果Mark前面的内容发生改变,Mark的位置也会跟着移动

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.mark_set("here","1.2")#设置当前光标位置为1.2
text.insert("here","插")#执行后当前光标位置(Mark位置)变成了1.3
text.insert("here","入")
#text.insert("1.3","入")

mainloop()

实例3:如果Mark周围的文本被删除了,Mark仍然存在

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.mark_set("here","1.2")#设置当前光标位置为1.2
text.insert("here","插")#执行后当前光标位置变成了1.3
text.delete("1.0",END)
text.insert("here","入")#here表示当前Mark的位置,如果Mark左边并没有数据则会插入到最左边

mainloop()

例4:只有mark_unset()方法可以解除Mark的封印

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.mark_set("here","1.2")#设置当前光标位置为1.2
text.insert("here","插")#执行后当前光标位置变成了1.3
text.mark_unset("here")

text.delete("1.0",END)
text.insert("here","入")#here表示当前Mark的位置

mainloop()

默认插入内容是插入到Mark左侧(就是说插入一个字符后,Mark向后移动了一个字符的位置)

实例5:插入内容到Mark的右侧

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.mark_set("here","1.2")#设置当前Mark位置为1.2
text.mark_gravity("here",LEFT)

text.insert("here","插")#执行后当前Mark位置变成了1.3
text.insert("here","入")#here表示当前Mark的位置

mainloop()

070 GUI的终极选择:Tkinter7

实例1:添加Tags

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.tag_add("tag1","1.7","1.12","1.14")#1.7(第一行第八列)到1.12,,与1.14设置Tag样式
text.tag_config("tag1",background ="yellow",foreground="red")

mainloop()

实例2:Tags覆盖

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.tag_add("tag1","1.7","1.12","1.14")#1.7(第一行第八列)到1.12,,与1.14设置Tag样式
text.tag_add("tag2","1.7","1.12","1.14")#1.7(第一行第八列)到1.12,,与1.14设置Tag样式

text.tag_config("tag1",background ="yellow",foreground="red")
text.tag_config("tag2",background ="blue")

mainloop()
 

实例2:降低Tag优先级

from tkinter import *

root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.tag_add("tag1","1.7","1.12","1.14")#1.7(第一行第八列)到1.12,,与1.14设置Tag样式
text.tag_add("tag2","1.7","1.12","1.14")#1.7(第一行第八列)到1.12,,与1.14设置Tag样式

text.tag_config("tag1",background ="yellow",foreground="red")
text.tag_config("tag2",background ="blue")

text.tag_lower("tag2")#降低tag2的优先级

mainloop()

实例3:Tags事件绑定

from tkinter import *
import webbrowser#导入网页模块

def show_hand_cursor(event):
    text.config(cursor="arrow")

def show_arrow_cursor(event):
    text.config(cursor="xterm")

def click(event):
    webbrowser.open("http://www.fishc.com")
    
root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
text.tag_add("link","1.7","1.16")#1.7(第一行第八列)到1.16
#设置蓝色前景色并底部划线
text.tag_config("link",foreground="blue",underline=True)

#当进入绑定文本段时,鼠标样式切换为“arrow"形态
text.tag_bind("link","<Enter>",show_hand_cursor)
#当离开绑定文本段时,鼠标样式切换为“xterm"形态
text.tag_bind("link","<Leave>",show_arrow_cursor)
#当触发鼠标“左键单击”时,使用默认浏览器打开鱼C网址
text.tag_bind("link","<Button-1>",click)

mainloop()

实例4:判断内容是否发生改变

from tkinter import *
import hashlib

def getSig(contents):
    m = hashlib.md5(contents.encode())
    return m.digest()

def check():#检查
    contents = text.get(1.0,END)
    if sig!=getSig(contents):
        print("警报,内容发生变动")
    else:
        print("风平浪静")
    
root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入
#注意,行号从1开始,列号则从0开始
#获取文本内容
contents=text.get(1.0,END)

sig = getSig(contents)

Button(root,text="检查",command=check).pack()

mainloop()

实例5:查找操作(使用search()方法可以搜索Text组件中的内容)

from tkinter import *
import hashlib

#将任何格式的索引号统一为元组(行,列)的格式输出
def getIndex(text,index):
    #split这里以"."拆分字符串,将1.3拆分为字符1和3,然后通过map将字符转换为整型
    return tuple(map(int,str.split(text.index(index),".")))
    
root = Tk()
text = Text(root,width=30,height=5)
text.pack()

#INSERT索引表示插入光标当前的位置
text.insert(INSERT,"I love FishC.com!")#光标当前的位置插入

#将任何格式的索引号统一为元组(行、列)的格式输出
start = 1.0
while True:
    pos = text.search("o",start,stopindex=END)#从开始到结束全文搜索
    if not pos:
        break
    print("找到了,位置是:",getIndex(text,pos))
    start = pos + "+1c"#将start指向找到的字符位置的下一个字符,以便进行下一次搜索

mainloop()

Text组件内部有一个栈专门用于记录内容的每次变动,所以每次“撤销”操作就是一次弹栈操作,“恢复”就是再次压栈。

实例6:撤销

from tkinter import *

#将任何格式的索引号统一为元组(行,列)的格式输出
def show():
    text.edit_undo()
    
root = Tk()
text = Text(root,width=30,height=5,undo=True)
text.pack()
text.insert(INSERT,"I love FishC")

Button(root,text="撤销",command=show).pack()

mainloop()


实例7:每次撤销一个字符

from tkinter import *

def callback(event):
    text.edit_separator()

def show():
    text.edit_undo()#执行撤回操作
    
root = Tk()

#autoseparators表示一次完整的操作结束后自动插入“分隔符”,此处设置为False
text = Text(root,width=30,height=5,autoseparators=False,undo=True,maxundo=10)
text.pack()

text.insert(INSERT,"I love FishC!")
text.bind('<Key>',callback)#每次有输入就插入一个“分隔符”

Button(root,text="撤销",command=show).pack()

mainloop()

071 GUI的终极选择:Tkinter8

Canvas(画布)组件

一个可以让你随心所欲绘制界面的组件。通常用于显示和编辑图形,可以用它来绘制直线、图形、多边形,甚至是绘制其他组件。

实例1:

from tkinter import *
root = Tk()
#创建canvas对象框,设置其宽度、高度与背景色
w = Canvas(root,width=200,height=100,background="black")
w.pack()

#画一条黄色的线
w.create_line(0,50,200,50,fill="yellow")
#画一条红色的竖线(虚线)
w.create_line(100,0,100,100,fill="red")
#中间画一个蓝色的矩形
w.create_rectangle(50,25,150,75,fill="blue")

mainloop()

实例2:

from tkinter import *
root = Tk()
#创建canvas对象框,设置其宽度、高度与背景色
w = Canvas(root,width=200,height=100,background="black")
w.pack()

#画一条黄色的线(参数为其x、y轴坐标)
line1 = w.create_line(0,50,200,50,fill="yellow")
#画一条红色的竖线(虚线)
line2 = w.create_line(100,0,100,100,fill="red")
#中间画一个蓝色的矩形
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)#删除线2

#创建一个按钮,按下时删除所有图形
Button(root,text="删除全部",command=(lambda x=ALL:w.delete(x))).pack()

mainloop()

实例3:在Canvas上显示文本

from tkinter import *
root = Tk()
#创建canvas对象框,设置其宽度、高度与背景色
w = Canvas(root,width=200,height=100,background="black")
w.pack()

#画一条绿色的斜线(参数为其x、y轴坐标),宽度为三个像素点
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,30,140,70,fill="yellow")
#在矩形正中(默认)显示文本,坐标为文本正中坐标
w.create_text(100,50,text="Hadley")

#创建一个按钮,按下时删除所有图形
Button(root,text="删除全部",command=(lambda x=ALL:w.delete(x))).pack()

mainloop()

实例4:绘制椭圆

from tkinter import *
root = Tk()
#创建canvas对象框,设置其宽度、高度与背景色
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_text(100,50,text="Hadley")

mainloop()
实例5:绘制圆形

from tkinter import *
root = Tk()
#创建canvas对象框,设置其宽度、高度与背景色
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="pink")
#在矩形正中(默认)显示文本,坐标为文本正中坐标
w.create_text(100,50,text="Hadley")

mainloop()

实例6:绘制多边形

from tkinter import *
import math as m

root = Tk()
w=Canvas(root,width=200,height=150,background="red")
w.pack()
center_x = 100
center_y = 80
r = 70
points = [
    #左上角A
    center_x - int(r*m.sin(2*m.pi/5)),
    center_y - int(r*m.cos(2*m.pi/5)),
    #右上角C
    center_x + int(r*m.sin(2*m.pi/5)),
    center_y - int(r*m.cos(2*m.pi/5)),
    #左下角E
    center_x - int(r*m.sin(m.pi/5)),
    center_y + int(r*m.cos(m.pi/5)),
    #顶点D
    center_x,
    center_y - r,
    #右下角B
    center_x + int(r*m.sin(m.pi/5)),
    center_y + int(r*m.cos(m.pi/5)),
    ]
#创建多边形方法,会自动按ACEDBA的形式连线,如果构成闭环,则会自动填充
w.create_polygon(points,outline="green",fill="yellow")

w.create_text(100,80,text="Hadley")

mainloop()

实例7:

from tkinter import *

root = Tk()
w=Canvas(root,width=400,height=200,background="white")
w.pack()

def paint(event):#画小圆
    x1,y1 = (event.x - 1),(event.y -1)
    x2,y2 = (event.x + 1),(event.y +1)
    w.create_oval(x1,y1,x2,y2,fill="red")

w.bind("<B1 - Motion>",paint)#画布与鼠标进行绑定
Label(root,text="按住鼠标左键并移动,开始绘制你的理想蓝图吧。。。").pack(side=BOTTOM)

mainloop()

073 GUI的终极选择:Tkinter10

Munu组件

Tkinter提供了一个Menu组件,用于实现顶级菜单、下拉菜单和弹出菜单。

实例1:创建一个顶级菜单(或称窗口主菜单

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()


menubar = Menu(root)#创建一个顶级菜单
menubar.add_command(label="Hello",command=callback)#创建一个顶级菜单对象
menubar.add_command(label="Quit",command=root.quit)

#显示菜单
root.config(menu=menubar)

mainloop()

实例2:创建添加到主菜单上的下拉菜单

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

#创建一个顶级菜单
menubar = Menu(root)

#创建下拉菜单filemenu包含内容
filemenu=Menu(menubar,tearoff=False)#创建一个从属于menubar的子菜单(下拉菜单)filemenu
filemenu.add_command(label="打开",command=callback)#创建一个下拉菜单对象
filemenu.add_command(label="保存",command=callback)
filemenu.add_separator()#插入分隔线
filemenu.add_command(label="退出",command=root.quit)
#创建一个顶级菜单对象“文件”,filemenu从属于这个对象(或称将filemenu添加到顶级菜单“文件”中)
menubar.add_cascade(label="文件",menu=filemenu)

#创建另一个下拉菜单editmenu包含内容
editmenu=Menu(menubar,tearoff=False)#创建一个从属于menubar的子菜单(下拉菜单)editmenu
editmenu.add_command(label="剪切",command=callback)
editmenu.add_command(label="拷贝",command=callback)
editmenu.add_separator()#插入分隔线
editmenu.add_command(label="粘贴",command=callback)
#创建一个顶级菜单对象“编辑”,editmenu从属于这个对象(或称将editmenu添加到顶级菜单“编辑”中)
menubar.add_cascade(label="编辑",menu=editmenu)

#显示菜单
root.config(menu=menubar)

mainloop()

实例3:创建一个弹出菜单方法

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

def popup(event):
    menu.post(event.x_root,event.y_root)#在此时鼠标位置弹出显示窗口
    
#创建一个顶级菜单menu
menu = Menu(root,tearoff=False)

#创建顶级菜单menu包含内容
menu.add_command(label="撤销",command=callback)#创建一个顶级菜单对象
menu.add_command(label="重做",command=callback)
#创建一个框架
frame = Frame(root,width=100,height=100)
frame.pack()

#将鼠标右键与popup方法绑定
frame.bind("<Button-3>",popup)

#显示菜单
#root.config(menu=menu)

mainloop()

实例4:菜单弹出

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

def popup(event):
    menu.post(event.x_root,event.y_root)#在此时鼠标位置弹出显示窗口
    
#创建一个顶级菜单menu
menu = Menu(root,tearoff=True)

#创建顶级菜单menu包含内容
menu.add_command(label="撤销",command=callback)#创建一个顶级菜单对象
menu.add_command(label="重做",command=callback)
#创建一个框架
frame = Frame(root,width=500,height=500)
frame.pack()

#将鼠标右键与popup方法绑定
frame.bind("<Button-3>",popup)

#显示菜单
#root.config(menu=menu)

mainloop()

实例5:添加单选组件radiobutton和多选按钮checkbutton

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

#创建一个顶级菜单
menubar = Menu(root)
#创建checkbutton关联变量
openVar = IntVar()
saveVar = IntVar()
exitVar = IntVar()
#创建下拉菜单filemenu包含内容
filemenu=Menu(menubar,tearoff=True)#创建一个从属于menubar的子菜单(下拉菜单)filemenu
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)
#创建一个顶级菜单对象“文件”,filemenu从属于这个对象(或称将filemenu添加到顶级菜单“文件”中)
menubar.add_cascade(label="文件",menu=filemenu)

#创建radiobutton关联变量
editVar = IntVar()
editVar.set(1)

#创建另一个下拉菜单editmenu包含内容
editmenu=Menu(menubar,tearoff=True)#创建一个从属于menubar的子菜单(下拉菜单)editmenu
editmenu.add_radiobutton(label="剪切",command=callback,variable=editVar,value=1)
editmenu.add_radiobutton(label="拷贝",command=callback,variable=editVar,value=2)
editmenu.add_separator()#插入分隔线
editmenu.add_radiobutton(label="粘贴",command=callback,variable=editVar,value=3)
#创建一个顶级菜单对象“编辑”,editmenu从属于这个对象(或称将editmenu添加到顶级菜单“编辑”中)
menubar.add_cascade(label="编辑",menu=editmenu)

#显示菜单
root.config(menu=menubar)

mainloop()

Menubutton组件(希望菜单按钮出现在其它位置时)

Menubutton组件是一个与Menu组件相关联的按钮,它可以放在窗口中的任意位置,并且在被按下时弹出下拉菜单

实例1:

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

#创建一个顶级菜单Menubutton按钮,设置为浮起显示(RAISED)
mb = Menubutton(root,text="点我",relief=RAISED)

mb.pack(side=RIGHT)#设置为右中显示

#创建下拉菜单filemenu包含内容
filemenu = Menu(mb,tearoff=False)#创建一个从属于mb的下拉菜单filemenu
filemenu.add_checkbutton(label="打开",command=callback,selectcolor="yellow")
filemenu.add_command(label="保存",command=callback)#创建一个下拉菜单对象"保存“
filemenu.add_separator()
filemenu.add_command(label="退出",command=root.quit)
#显示菜单
mb.config(menu=filemenu)

mainloop()

OptionMenu(选项菜单)组件

选项菜单的发明弥补了Listbox组件无法实现下拉列表框的遗憾

实例1:

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

variable = StringVar()#创建字符串变量variable
variable.set("one")#初始值设置为"one"
w = OptionMenu(root,variable,"one","two","three")
w.pack()

mainloop()

实例2:多个选项添加到选项菜单中

from tkinter import *

def callback():
    print("被调用了")
    
root = Tk()

OPTIONS = [
    "Hadley",
    "小土豆",
    "yiwofeiye",
    "RAN"
    ]

variable = StringVar()#创建字符串变量variable
variable.set(OPTIONS[0])#初始值设置为"one"
w = OptionMenu(root,variable,*OPTIONS)
w.pack()

def callback():
    print(variable.get())

Button(root,text="点我",command=callback).pack()

mainloop()
 

074  GUI的终极选择:Tkinter11

事件绑定

对于每个组件来说,可以通过bind()方法将函数或方法绑定到具体的事件上。当被触发的事件满足该组件绑定的事件时,Tkinter就会带着事件描述去调用handler()方法

实例1:捕获单击鼠标位置

from tkinter import*

root = Tk()

def callback(event):
    print("点击位置:",event.x,event.y)

frame = Frame(root,width=200,height=200)
#Button表示鼠标点击事件
#1代表左键 2代表中间滚轮点击 3代表右键
frame.bind("<Button-1>",callback)#按键按下时,调用callback方法
frame.pack()

mainloop()

实例2:捕获键盘事件

#捕获单击鼠标的位置
from tkinter import*

root = Tk()

def callback(event):
    print("敲击位置:",repr(event.char))#打印当前按下按键的字符
    print(event.char)

frame = Frame(root,width=200,height=200)
#Key为键盘事件
frame.bind("<Key>",callback)#按键按下时,调用callback方法
frame.focus_set()#获得焦点
frame.pack()

mainloop()

实例3:捕获鼠标在组件上的运动轨迹

#当鼠标在组件内移动的整个过程均触发该事件

from 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.pack()

mainloop()

事件序列

Tkinter使用一种称为事件序列的机制来允许用户定义事件,用户需要使用bind()方法将具体的事件序列与自定义的方法绑定

Event对象(按键名keysym和按键码keycode)

实例1:打印当前按下按键的按键名

from tkinter import*

root = Tk()

def callback(event):
    print(event.keysym)#打印当前按下按键的按键名
    print(event.char)

frame = Frame(root,width=200,height=200)
#Key为键盘事件
frame.bind("<Key>",callback)#按键按下时,调用callback方法
frame.focus_set()#获得焦点
frame.pack()

mainloop()

075 GUI的终极选择:Tkinter12

Message组件

Message(消息)组件是Label组件的变体,用于显示多行文本信息。Message组件能够自动换行,并调整文本的尺寸使其适应给定得尺寸。

实例1:

from tkinter import *

root = Tk()
w1 = Message(root,text="这是一则消息",width=100)
w1.pack()
w2 = Message(root,text="这是一条骇人听闻的长消息!",width=100)
w2.pack()

mainloop()

Spinbox组件

Entry组件的变体,用于从一些固定的值中选取一个。使用Spinbox组件,可以通过返回或者元组指定允许用户输入的内容。

实例1:

from tkinter import *

root = Tk()

#w = Spinbox(root,from_=0,to=10)#指定输入值为0-10
w = Spinbox(root,value=("Hadley","小土豆","雅馨"))#指定输入
w.pack()

mainloop()

PanedWindow组件

与Frame类似,都是为组件提供一个框架,但其还允许让用户调整应用程序的空间划分

实例1:两窗格

from tkinter import *

root = Tk()

m = PanedWindow(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()

实例2:三窗格

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()

实例3:显示“分割线”

from tkinter import *

root = Tk()

#showhandle=True表示显示“手柄”
#sashrelief=SUNKEN表示分隔线的样式设置为向下凹
m1 = PanedWindow(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()

Toplevel组件

Topleve(顶级窗口)l组件类似于Frame组件,但其是一个独立的顶级窗口,通常拥有标题栏、边框等部件。通常用在显示额外的窗口、对话框和其他弹出窗口中。

实例1:按钮按下创建一个顶级窗口

from tkinter import *

def create():
    top = Toplevel()#创建一个独立的顶级窗口
    top.title("FishC Demo")
    msg = Message(top,text="I love FishC.com")
    msg.pack()
    
root = Tk()
Button(root,text="创建顶级窗口",command=create).pack()

mainloop()

实例2:Toplevel的窗口设置为50%透明

from tkinter import *

def create():
    top = Toplevel()
    top.title("FishC Demo")
    top.attributes("-alpha",0.5)#设置为50%透明度
    msg = Message(top,text="I love FishC.com")
    msg.pack()
    
root = Tk()
Button(root,text="创建顶级窗口",command=create).pack()

mainloop()

076 GUI的终极选择:Tkinter13

布局管理器

布局管理器就是管理你的那些组件如何排列的家伙。Tkinter有三个布局管理器,分别是pack、grid和place

pack:按添加顺序排列组件

grid:按行/列形式排列组件

place:允许程序员指定组件的大小和位置

pack

实例1:生成一个Listbox组件并将它填充到root窗口

from tkinter import *

root = Tk()
listbox = Listbox(root)
#fill选项是告诉窗口管理器该组件将怎样填充整个分配给它的空间
#BOTH表示同时横向和纵向扩展;X表示横向;Y表示纵向
#expand选项是告诉窗口管理器是否将父组件的额外空间也填满(任意拉伸窗口依旧会填满)

#默认情况下pack是将添加的组件依次纵向排列
listbox.pack(fill=BOTH,expand=True)
for i in range(10):
    listbox.insert(END,str(i))

mainloop()

实例2:纵向排列,横向填充

from tkinter import *

root = Tk()
#fill选项是告诉窗口管理器该组件将怎样填充整个分配给它的空间
#BOTH表示同时横向和纵向扩展;X表示横向;Y表示纵向
#expand选项是告诉窗口管理器是否将父组件的额外空间也填满

#默认情况下pack的side属性是将添加的组件依次纵向排列
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:横向排列,纵向填充

from tkinter import *

root = Tk()
#fill选项是告诉窗口管理器该组件将怎样填充整个分配给它的空间
#BOTH表示同时横向和纵向扩展;X表示横向;Y表示纵向
#expand选项是告诉窗口管理器是否将父组件的额外空间也填满

#将pack设置为横向排列
Label(root, text="red", bg="red", fg="white").pack(side=LEFT)
Label(root, text="green", bg="green", fg="black").pack(side=LEFT)
Label(root, text="blue", bg="blue", fg="white").pack(side=LEFT)

mainloop()

grid

使用一个grid就可以简单地实现你用很多个框架和pack搭建起来的效果。使用grid排列组件,只需告诉它你想要将组件放置的位置(行row/列column)。

实例1:

from tkinter import *

root = Tk()

#column默认值是0
#默认情况下组件会居中显示在对应的网格里
#Label(root,text="用户名").grid(row=0)
#Label(root,text="密码").grid(row=1)
#设置sticky=W使Label左对齐
Label(root,text="用户名").grid(row=0,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()

实例2:设置rowspan与columnspan实现跨行和跨列功能

from tkinter import *

root = Tk()

#column默认值是0
#默认情况下组件会居中显示在对应的网格里
#Label(root,text="用户名").grid(row=0)
#Label(root,text="密码").grid(row=1)
#设置sticky=W使Label左对齐
#创建Label文本
Label(root,text="用户名").grid(row=0,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)
#插入Label图像
photo = PhotoImage(file="logo.gif")
#rowspan=2跨两行,边距5
Label(root,image=photo).grid(row=0,column=2,rowspan=2,padx=5,pady=5)
#columnspan=3跨三列(默认为居中显示),边距5
Button(text="提交",width=10).grid(row=2,columnspan=3,pady=5)

mainloop()

place

通常情况下不建议使用place布局管理器

实例1:将子组件显示在父组件的正中间

from tkinter import *

def callback():
    print("正中靶心")
root = Tk()
#relx和rely指定的是子组件相对于父组件的位置,范围是(00`1.0),0.5则表示一半,正中间
#anchor=CENTER表示正中显示
Button(root,text="点我",command=callback).place(relx=0.5,rely=0.5,anchor=CENTER)

mainloop()

实例2:Button组件覆盖Label组件

from tkinter import *

def callback():
    print("正中靶心")
root = Tk()

photo = PhotoImage(file="logo_big.gif")
Label(root,image=photo).pack()
#relx和rely指定的是子组件相对于父组件的位置,范围是(00`1.0),0.5则表示一半,正中间
Button(root,text="点我",command=callback).place(relx=0.5,rely=0.5,anchor=CENTER)

mainloop()

实例3:

from tkinter import *

root = Tk()

#relx和rely指定的是子组件相对于父组件的位置,范围是(00`1.0),0.5则表示一半,正中间
#relwidth和relheight选项指定相对父组件的尺寸
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()

077 GUI的终极选择:Tkinter14

Tkinter提供了三种标准对话框模块,分别是:messagebox、filedialog、colorchooser

messagebox(消息对话框)

实例1:askokcancel函数

from tkinter import *

print(messagebox.askokcancel("FishC Demo","发射核弹?"))

mainloop()

实例2:askquestion函数

实例3:asiretrycancel函数

实例4:askyesno函数

实例5:showerror函数

from tkinter import *

#print(messagebox.askokcancel("FishC Demo","发射核弹?"))
#print(messagebox.askquestion("FishC Demo","买个U盘?"))
#print(messagebox.askretrycancel("FishC Demo","启动失败,重启?"))
#print(messagebox.askyesno("FishC Demo","你确定要格式化硬盘吗?"))
print(messagebox.showerror("FishC Demo","Error!!!"))

mainloop()

实例6:showinfo函数

from tkinter import *

#options参数可设置为default、icon与parent
#print(messagebox.askokcancel("FishC Demo","发射核弹?"))
#print(messagebox.askquestion("FishC Demo","买个U盘?"))
#print(messagebox.askretrycancel("FishC Demo","启动失败,重启?"))
#print(messagebox.askyesno("FishC Demo","你确定要格式化硬盘吗?"))
#print(messagebox.showerror("FishC Demo","Error!!!"))
messagebox.showinfo("Hadley","Great!!!",icon="info")

mainloop()

实例7:showwarning函数

from tkinter import *

#options参数可设置为default、icon与parent
#print(messagebox.askokcancel("FishC Demo","发射核弹?"))
#print(messagebox.askquestion("FishC Demo","买个U盘?"))
#print(messagebox.askretrycancel("FishC Demo","启动失败,重启?"))
#print(messagebox.askyesno("FishC Demo","你确定要格式化硬盘吗?"))
#print(messagebox.showerror("FishC Demo","Error!!!"))
#messagebox.showinfo("Hadley","Great!!!",icon="info")
messagebox.showwarning("Hadley","Warning!!!",icon="warning")

mainloop()

filedialog(文本对话框)

当应用程序需要使用打开文件或保存文件的功能时

实例1:

from tkinter import *

root = Tk()

def callback():
    #askopenfilename函数用来打开文件
    #asksaveasfilename函数用来保存文件
    fileName = filedialog.askopenfilename()
    print(fileName)

Button(root,text="打开文件夹",command=callback).pack()

mainloop()

实例2:限制打开文件类型

from tkinter import *

root = Tk()

def callback():
    #askopenfilename函数用来打开文件
    #asksaveasfilename函数用来保存文件
    #fileName = filedialog.askopenfilename()
    #限制打开文件类型
    fileName = filedialog.askopenfilename(filetypes=[("PNG",".png"),("GIF",".gif")])
    print(fileName)

Button(root,text="打开文件夹",command=callback).pack()

mainloop()

colorchooser(颜色选择对话框)

颜色对话框提供一个让用户选择颜色的界面

实例1:

from tkinter import *

root = Tk()

def callback():
    #colorchooser函数用于打开颜色选择对话框
    fileName = colorchooser.askcolor()
    print(fileName)

Button(root,text="打开文件夹",command=callback).pack()

mainloop()

对应的RGB值及其对应的16进制值

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

 

评论 69
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦我飞也

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值