300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > python入门学习[看漫画学Python:有趣 有料 好玩 好用读书笔记]

python入门学习[看漫画学Python:有趣 有料 好玩 好用读书笔记]

时间:2023-04-17 17:56:37

相关推荐

python入门学习[看漫画学Python:有趣 有料 好玩 好用读书笔记]

写在前面:本文中绝大多数图片来源于图书:看漫画学Python:有趣、有料、好玩、好用,本文仅供个人学习使用,如有侵权,请联系删除。

学习编程语言最好的方式就是多写,多写,多写!!!哪有什么快速掌握,能快速的只有入门。看起来的轻松都是付出的结果。

文章目录

01编程基础那点儿事02数字类型的数据03运算符运算符的优先级⭐⭐⭐04程序流程控制05容器类型的数据序列元组集合字典06字符串07函数08类与对象封装性继承性多态性09异常处理10常用的内置模块11文件读写13网络通信参考资料

01编程基础那点儿事

标识符

python标识符的规则

区分大小写首字符可以是下划线或字母,但是不能是数字除首字符外的其他字符必须是下划线、字母和数字关键字不能作为标识符不要使用Python 的内置函数作为自己的标识符

关键字

定义:关键字是由语言本身定义好的、有特殊含义的代码元素。

python只有33个关键字,而且只有FalseTrueNone的首字符大写,其他关键字全部小写。

来源:看漫画学Python:有趣、有料、好玩、好用

变量

为一个变量赋值的同时就声明了该变量,该变量的数据类型就是赋值数据所属的类型,该变量还可以接收其他类型的数据。

语句

python代码是由关键字、标识符、表达式和语句等构成的,语句是代码的重要组成部分。

在python中,一行代码表示一条语句,在一般情况下结束时不加分号。

来源:看漫画学Python:有趣、有料、好玩、好用

模块

在python中一个模块就是一个文件,模块是保存代码的最小单位,在模块中可以声明变量、函数、属性和类等python代码元素。

一个模块可以访问另一个模块吗?

当然可以,但是需要导入语句的帮忙,导入语句有以下三种形式。

import<模块名>

通过这种方式会导入m2模块的所有代码元素,在访问时需要加前缀“m2.”

from<模块名>import<代码元素>

通过这种方式会导入m2中的x变量,在访问时不需要加前缀“m2.”

from<模块名>import<代码元素>as<代码元素别名>

与②类似,在当前m1模块的代码元素(x变量)与要导入的m2模块的代码元素(x变量)名称有冲突时,可以给要导入的代码元素(m2中的x)一个别名x2

举例:

import worldfrom world import zfrom world import x as x2x =100y = 20print(y) # 访问当前模块变量print(world.y) # 访问world模块变量yprint(z) # 访问world模块变量zprint(x2) # x2是world模块x别名

总结:一个模块其实就是一个文件,在模块中封装了很多代码元素。在实际的项目开发中,我们避免不了要使用别人的模块,如果想导入所有内容,则使用import语句;如果只想导入一个元素,使用from import语句;如果名称有冲突,则使用from import as.

02数字类型的数据

来源:看漫画学Python:有趣、有料、好玩、好用,下同

在Python中所有的数据类型都是类,每个数据值都是类的“实例”。

在Python中有6种主要的内置数据类型:数字、字符串、列表、元组、集合和字典。列表、元组、集合和字典可以容纳多项数据,在本书中把它们统称为容器类型的数据。

Python中的数字类型有4种:整数类型、浮点类型、复数类型和布尔类型。需要注意的是,布尔类型也是数字类型,它事实上是整数类型的一种。

整数类型

Python中的整数类型为int类,整数类型的范围可以很大,表示很大的整数,只受所在计算机硬件的限制。

来源:看漫画学Python:有趣、有料、好玩、好用,下同

浮点类型

浮点类型主要用来存储小数数值,Python的浮点类型为float类。Python只支持双精度浮点类型,而且是与本机相关的。

复数类型

整数和浮点数(小数)在数学中被统称为实数。与实数对应的是复数,复数在数学中被表示为:a+bi,其中a被称为实部,b被称为虚部,i被称为虚数单位。复数在数学、理论物理学和电气工程等方面应用广泛,例如向量就可以使用复数表示。

布尔类型

Python中数据类型转换很灵活,任何类型的数据都可以通过bool()函数转换为布尔值,那么被认为是“空的”,“没有的”值被转换为False,反之,被转换为True。

数字类型的相互转换

Python中的很多数据类型都可以相互转换,但是具体情况比较复杂,本章重点介绍数字类型之间的相互转换。

在Python的数字类型中,除复数外,其他三种数字类型如整数、浮点和布尔都可以相互转换,分为隐式类型的转换和显式类型的转换。

隐式类型转换

数字之间可以进行数学计算,在进行数学计算时若数字类型不同,则会发生隐式类型的转换。

显示类型转换

但是请注意,复数不能和浮点数、整型相互转换

# 例如:TypeError: can't convert complex to float

03运算符

算术运算符

算术运算符用于组织整数类型和浮点类型的数据,有一元运算符和二元运算符之分。

一元算术运算符有两个:+(正号)和-(负号),例如:+a还是a,-a是对a的取反运算。

二元运算符如下图所示:

比较运算符

比较运算符用于比较两个表达式的大小,其结果是布尔类型的数据,即True或False。

比较运算符可用于任意类型的数据,但参与比较的两种类型的数据要相互兼容,即能够进行隐形转换。例如,整数、浮点和布尔这三种类型是相互兼容的。

位运算符

下面是关于按位取反运算的总结:

公式~a = - (a +1)

赋值运算符

运算符的优先级⭐⭐⭐

优先级:从上到下依次降低,同一行有相同的优先级

优先级:括号 》幂 》位反 》正负号 》乘除取余地板除 》加减 》位移 》位与 》位异或 》 位或 》 比较 》逻辑非 》逻辑与、逻辑或

总而言之:在位运算优先级中,优先级从高到低大体是:算术运算符 →位运算符→关系运算符→逻辑运算符→赋值运算符

04程序流程控制

分支语句

python中没有switch语句,多分支功能通过if-elif-else实现。

if结构

if结构的语法如下:

程序举例:

score= int( input("请输入一个0~100的整数:"))if score >= 85:print("您真优秀")if score < 60 :print("您需要加倍努力")if(score >= 60) and (score < 85) :print("您的成绩还可以,仍需继续努力")

if-else结构

程序举例:

score = int( input("请输入一个0~100之间的数"))if score >= 60 :if(score >= 85) :print("您真优秀")else :print("您的成绩还可以,仍需继续努力")else:print("您需要加倍努力! ")

if-elif-else结构

程序举例:

score = int( input("请输入0~100之间的数: "))if score >= 90 :grade ='A'elif score >= 80 :grade ='B'elif score >= 70 :grade = 'C'elif score >= 60 :grade = 'D'else:grade = 'E'print("Grade = " + grade)

循环语句

while语句

在python中只有while语句,没有do-while语句。while语句先判断循环条件,若条件为True则执行循环体。

测试代码

i = 0while i * i < 1000 :i +=1print("i = " + str(i))print("i * i =" + str(i * i))

测试结果

else子句的作用是什么呢?

else子句是在循环体正常结束时才执行,当中断时不执行。

程序测试:

i = 0while i * i < 10 :i +=1print(str(i) + '*' + str(i) + ' =' , i*i)else :print("While Over!")

修改代码之后:

i = 0while i * i < 10 :i +=1if i ==3:breakprint(str(i) + '*' + str(i) + ' =' , i*i)else :print("While Over!")

通过对比:由于后面break,所以else子句没有运行。

for语句

for语句的一般格式:

注 : 可迭代对象包括字符串、列表、元组、集合和字典等。

测试代码

print("-----字符串------")for item in 'Hello' :print( item)# 声明整数列表numbers = [43,32,55,74]print(" -----整数列表-----")for item in numbers :print(item)

测试结果

for循环中的else子句也是和while中功能相同,如果循环正常结束,没有break、return和异常发生时就执行。

程序测试:else子句不运行,因为break执行

for item in range(10) :if( item == 4):breakprint(item)else :print("For Overs!")

05容器类型的数据

若我们想将多个数据打包并且统一管理,应该怎么办?

Python内置的数据类型如序列(列表、元组等)、集合和字典等可以容纳多项数据,我们称它们为容器类型的数据。

序列

序列(sequence)是一种可迭代的、元素有序的容器类型的数据。

序列的索引操作

序列中的元素都是有序的,每一个元素都带有序号,这个序号叫作索引。索引有正值索引和负值索引之分。

我们是通过下标运算符访问序列中的元素的,下标运算符是跟在容器数据后的一对中括号([]),中括号带有参数,对于序列类型的数据,这个参数就是元素的索引序号。

加和 乘操作

加(+)和乘( *)运算符也可以用于序列中的元素操作。加(+)运算符可以将两个序列连接起来,乘( *)运算符可以将两个序列重复多次。

切片操作

序列的切片(Slicing)就是从序列中切分出小的子序列。

切片运算符的语法形式为[start:end:step]。其中,start是开始索引,end是结束索引,step是步长(切片时获取的元素的间隔,可以为正整数,也可以为负整数)。

注意:切下的小切片包括start位置的元素,但不包括end位置的元素,start和end都可以省略。

下面对字符串变量a进行切片操作[1:3],开始索引为1,结束索引为3,省略步长(默认值为1)。

下面对字符串变量a进行切片操作[0:3:2],开始索引为0,结束索引为3,步长为2。

成员测试

成员测试运算符有两个:in和not in,in用于测试是否包含某一个元素,not in用于测试是否不包含某一个元素。

列表

列表(list)是一种可变序列类型,我们可以追加、插入、删除和替换列表中的元素。

创建列表

1 list(iterable)函数:参数iterable是可迭代对象(字符串、列表、元组、集合和字典等)。

2 [元素1,元素2,元素3,⋯]:指定具体的列表元素,元素之间以逗号分隔,列表元素需要使用中括号括起来。

追加元素

列表是可变的序列对象,列表可以追加元素。

1 在列表中追加单个元素时,可以使用列表的append(x)方法。

2 在列表中追加多个元素时,可以使用加(+)运算符或列表的extend(t)方法

插入元素

想向列表中插入元素时,可以使用列表的list.insert(i,x)方法,其中,i指定索引位置,x是要插入的元素。

替换元素

想替换列表中的元素时,将列表下标索引元素放在赋值符号(=)的左边,进行赋值即可。

删除元素

想在列表中删除元素时,可使用列表的list.remove(x)方法,如果找到匹配的元素x,则删除该元素,如果找到多个匹配的元素,则只删除第一个匹配的元素。

元组

元组(tuple)是一种不可变序列类型。

创建元组

创建元组时有两种方法。

1 tuple(iterable)函数:参数iterable是可迭代对象(字符串、列表、元组、集合和字典等)。

2 (元素1,元素2,元素3,⋯):指定具体的元组元素,元素之间以逗号分隔。对于元组元素,可以使用小括号括起来,也可以省略小括号。

元组拆包

创建元组,并将多个数据放到元组中,这个过程被称为元组打包。

与元组打包相反的操作是拆包,就是将元组中的元素取出,分别赋值给不同的变量。

集合

集合(set)是一种可迭代的、无序的、不能包含重复元素的容器类型的数据。

创建集合

我们可以通过以下两种方式创建集合。

1 set(iterable)函数:参数iterable是可迭代对象(字符串、列表、元组、集合和字典等)。

2 {元素1,元素2,元素3,⋯}:指定具体的集合元素,元素之间以逗号分隔。对于集合元素,需要使用大括号括起来。

修改集合

修改集合类似于修改列表,可以向其中插入和删除元素。修改可变集合有如下所示的常用方法。

add(elem):添加元素,如果元素已经存在,则不能添加,不会抛出错误。

remove(elem):删除元素,如果元素不存在,则抛出错误。

clear():清除集合。

字典

字典(dict)是可迭代的、通过键(key)来访问元素的可变的容器类型的数据。

字典由两部分视图构成:键视图和值视图。键视图不能包含重复的元素,值视图能。在键视图中,键和值是成对出现的。

创建字典

我们可以通过以下两种方法创建字典。

1 dict()函数。

2 {key1:value1,key2:value2,…,key_n:value_n}:指定具体的字典键值对,键值对之间以逗号分隔,最后用大括号括起来。

修改字典

字典可以被修改,但都是针对键和值同时操作的,对字典的修改包括添加、替换和删除。

访问字典视图

我们可以通过字典中的三种方法访问字典视图。

items():返回字典的所有键值对视图。

keys():返回字典键视图。

values():返回字典值视图。

遍历字典

测试结果

s_dict ={1 :'lishizheng' ,2 : 'lili' ,3 : 'shenglong'}print('---遍历键---')for s_id in s_dict.keys() :print('学号: ' + str(s_id))print('---遍历值---')for s_name in s_dict.values():print("姓名:"+str(s_name))print('---遍历键值---')for s_id,s_name in s_dict.items():print('学号: {0} - 学生:{1}'.format(s_id,s_name))

06字符串

字符串的表示方式

字符串有三种表示方式:普通字符串、原始字符串和长字符串。

普通字符串

普通字符串指用单引号(’)或双引号(")括起来的字符串。

常见的转义字符

原始字符串

原始字符串中的特殊字符不需要被转义,按照字符串本来的样子呈现。在普通字符串前加r就是原始字符串了。

长字符串

如果要使用字符串表示一篇文章,其中包含了换行、缩进等排版字符,则可以使用长字符串表示。对于长字符串,要使用三个单引号(’’’)或三个双引号(""")括起来。

字符串与数字之间的相互转换

将字符串转换为数字

将字符串转换为数字,可以使用int()和float()实现,如果成功则返回数字,否则引发异常。

在默认情况下,int()函数都将字符串参数当作十进制数字进行转换,所以int(‘AB’)会失败。int()函数也可以指定基数(进制)。

将数字转换为字符串

将数字转换为字符串,可以使用str()函数,str()函数可以将很多类型的数据都转换为字符串。

格式化字符串

使用占位符

要想将表达式的计算结果插入字符串中,则需要用到占位符。对于占位符,使用一对大括号({})表示。

默认占位符

参数序号占位符

参数名占位符

格式化控制符

在占位符中还可以有格式化控制符,对字符串的格式进行更加精准的控制。

字符串的格式化控制符及其说明如下表所示。

格式化控制符位于占位符索引或占位符名字的后面,之间用冒号分隔,语法:{参数序号:格式控制符}或{参数名:格式控制符}。

操作字符串

字符串查找

字符串的find()方法用于查找子字符串。该方法的语法为str.find(sub[,start[,end]]),表示:在索引start到end之间查找子字符串sub,如果找到,则返回最左端位置的索引;如果没有找到,则返回-1。

字符串替换

若想进行字符串替换,则可以使用replace()方法替换匹配的子字符串,返回值是替换之后的字符串。该方法的语法为str.replace(old,new[,count]),表示:用new子字符串替换old子字符串。count参数指定了替换old子字符串的个数,如果count被省略,则替换所有old子字符串。

字符串分割

符串分割

若想进行字符串分割,则可以使用split()方法,按照子字符串来分割字符串,返回字符串列表对象。该方法的语法为str.split(sep=None,maxsplit=-1),表示:使用sep子字符串分割字符串str。maxsplit是最大分割次数,如果maxsplit被省略,则表示不限制分割次数。

统计英文文章中单词出现的频率

# 一篇文章文本wordstring = """it was the best of times it was the worst times.it was the age of wisdom it was the age of foolishness."""# 将标点符号替换wordstring = wordstring.replace('.' ,'')# 分割单词wordlist = wordstring.split()wordfreq = []for w in wordlist:wordfreq.append(wordlist.count(w))d =dict(zip(wordlist, wordfreq))print(d)

作业题

1 设有变量s=‘Pyhon’,则"{0:3}".format(s)表达式的输出结果是()。

A.‘hon’B.‘Pyhon’C.‘PYTHON’D.‘PYT’

解答:B

2 设有变量赋值s="Hello World",则以下选项中可以输出"World"子字符串的是()。

A.print(s[-5:-1])B.print(s[-5:0])C.print(s[-4:-1])D.print(s[-5:])

解答:D

3 在以下选项中可以倒置"World"字符串的是()。

A."World"[::-1]B."World"[::]C."World"[0::-1]D."World"[-1::-1]

解答:AD

语法规则是[start: end :step]

4 判断对错(请在括号内打√或×,√表示正确,×表示错误):。

1)原始字符串是在普通字符串前加r,使用它的优势是:在字符串中特殊字符不需要被转义。(yes)

2)长字符串是,使用三个单引号(’’’)或三个双引号(""")括起来的字符串,使用它的优势是:在字符串中特殊字符不需要被转义。(no)

3)将字符串转换为数字,可以使用int()和float()函数实现。(yes)

4)将数字转换为字符串,可以使用str()函数实现。(yes)

07函数

定义函数

自定义函数的语法格式如下:

以英文半角冒号结尾

def rect_area(width ,height) :area = width * heightreturn areadef print_area(width,height) :area = width *heightprint("{0} * {1} 长方形面积:{2}".format(width, height, area))print_area(100,40)

调用函数

使用位置参数调用函数

在调用函数时传递的实参与定义函数时的形参顺序一致,这是调用函数的基本形式。

使用关键字参数调用函数

在调用函数时可以采用“关键字=实参”的形式,其中,关键字的名称就是定义函数时形参的名称。

def rect_area(width ,height) :area = width * heightreturn areadef print_area(width,height) :area = width *heightprint("{0} * {1} 长方形面积:{2}".format(width, height, area))print_area(width = 100,height =40)

参数的默认值

python中没有函数重载的概念,而是为函数的参数提供默认值实现。

def make_coffee(name = '卡布奇诺') :return "制作一杯{0}咖啡。".format(name)coffee1= make_coffee("拿铁")coffee2 = make_coffee()print(coffee1)print(coffee2)

可变参数

可变参数在参数前加*或者**符号

基于元组的可变参数(*可变参数)

*可变参数在函数中被组装成一个元组。

def sum( * numbers) : # 可变参数total = 0for number in numbers:total += numberreturn totalprint(sum(100,100,20))print(sum(1,2,3,4,5))

基于字典的可变参数(**可变参数)

**可变参数在函数中被组装成一个字典。

def show_info( ** info) :print('---show_info---')for key,value in info.items():print('{0}- {1}'.format(key ,value))show_info(name = "Tony",age = 18, sex =True)show_info(student_name ="Tony", student_no = '1000')

函数中变量的作用域

变量可以在模块中创建,作用域(变量的有效范围)是整个模块,被称为全局变量。变量也可以在函数中创建,在默认情况下作用域是整个函数,被称为局部变量。

测试代码

x =20def print_value() :x =10print("函数中x ={0}".format(x))print_value()print("全局变量x = {0}".format(x))

测试结果

测试代码

x =20def print_value() :global xx =10print("函数中x ={0}".format(x))print_value()print("全局变量x = {0}".format(x))

测试结果:

函数类型

Python中的任意一个函数都有数据类型,这种数据类型是function,被称为函数类型。

函数类型的数据与其他类型的数据是一样的,任意类型的数据都可以作为函数返回值使用,还可以作为函数参数使用。因此,一个函数可以作为另一个函数返回值使用,也可以作为另一个函数参数使用。

def add(a, b) :return a +bdef sub(a, b):return a-bdef calc(opr) :if opr == '+':return addelse:return subf1 = calc('+')f2 = calc('-')print("10 + 5 ={0}".format(f1(10,5)))print("10 -5 ={0}".format(f2(10,5)))

测试结果

请看下面三个函数

add()和sub()函数有两个数字参数,具有相同的函数类型。square()函数只有一个数字参数,所以square()与add()、sub()函数的类型不同

def add(a, b) :return a +bdef sub(a, b):return a-bdef square(a):return a*a

过滤函数filter()

在Python中定义了一些用于数据处理的函数,如filter()和map()等。我们先介绍filter()函数。

filter()函数用于对容器中的元素进行过滤处理。

参数function是一个提供过滤条件的函数,返回布尔值。参数iterable是容器类型的数据。

测试代码

def f1(x):return x >50data1 = [66,15,91,28,98,50,7,80,89]filtered = filter(f1,data1)data2 = list(filtered)print(data2)

映射函数map()

map()函数用于对容器中的元素进行映射(或变换)。例如:我想将列表中的所有元素都乘以2,返回新的列表。

map函数的语法如下:

测试代码

def f1(x):return x*2data1 = [66,15,91,28,98,50,7,80,89]mapped = map(f1,data1)data2 = list(mapped)print(data2)

lambda()函数

我们之前学习的函数都是有名称的函数,例如在8.1节定义的rect_area()函数,rect_area就是其函数名。我们也可以定义匿名函数,匿名函数就是没有名称的函数。

在Python中使用lambda关键字定义匿名函数。lambda关键字定义的函数也被称为lambda()函数,定义lambda()函数的语法如下。

“参数列表”与函数的参数列表是一样的,但不需要用小括号括起来

lambda()函数与有名称的函数一样,都是函数类型,所以8.6.1节的add()和sub()函数可以被lambda()函数替代。修改8.6.1节的代码示例如下:

测试代码

def calc(opr):if opr == '+':return lambda a ,b:(a+b)else :return lambda a, b: (a -b)f1 = calc ('+')f2 = calc('-')print("10 + 5 = {0}".format(f1(10,5)))

测试代码

data1 = [66,14,91,28,98,50,7,80,99]filtered = filter(lambda x : (x > 50) ,data1)data2 = list(filtered)print(data2)mapped = map(lambda x :(x *2) ,data1)data3 = list(mapped)print(data3)

08类与对象

面向对象

类和对象都是面向对象中的重要概念。面向对象是一种编程思想,即按照真实世界的思维方式构建软件系统。

例如,在真实世界的校园里有学生和老师,学生有学号、姓名、所在班级等属性(数据),还有学习、提问、吃饭和走路等动作(方法)。如果我们要开发一个校园管理系统,那么在构建软件系统时,也会有学生和老师等“类”,张同学、李同学是学生类的个体,被称为“对象”,“对象”也被称为“实例”。

定义类

Python中的数据类型都是类,我们可以自定义类,即创建一种新的数据类型。Python中类的定义语法格式如右图所示。

定义小汽车(Car)类的代码如下:

小汽车(Car)类继承了object类,object类是所有类的根类,在Python中任何一个类(除object外)都直接或间接地继承了object,直接继承object时(object)部分的代码可以省略。

创建对象

类相当于一个模板,依据这样的模板来创建对象,就是类的实例化,所以对象也被称为“实例”。

类的成员

成员变量也被称为数据成员,保存了类或对象的数据。例如,学生的姓名和学号。

构造方法是一种特殊的函数,用于初始化类的成员变量。

成员方法是在类中定义的函数。

属性是对类进行封装而提供的特殊方法。

实例变量

实例变量就是对象个体特有的“数据”,例如狗狗的名称和年龄等。

测试代码

class Dog:def __init__(self, name, age):self.name = nameself.age = aged = Dog('球球', 2)print("我们家狗狗名叫{0},{1}岁了".format(d.name ,d.age))

测试结果

构造方法

类中的__init__()方法是一个非常特殊的方法,用来创建和初始化实例变量,这种方法就是“构造方法”。在定义__init__()方法时,它的第1个参数应该是self,之后的参数用来初始化实例变量。调用构造方法时不需要传入self参数。

测试代码

class Dog:def __init__(self, name, age):self.name = nameself.age = aged = Dog('球球', 2)d1 = Dog('花花',3)print("我们家狗狗名叫{0},{1}岁了".format(d.name ,d.age))print("我们家的狗狗名叫{0},{1}岁了".format(d1.name , d1.age))

实例方法

实例方法与实例变量一样,都是某个实例(或对象)个体特有的方法。

定义实例方法时,它的第1个参数也应该是self,这会将当前实例与该方法绑定起来,这也说明该方法属于实例。在调用方法时不需要传入self,类似于构造方法。

测试代码

class Dog:def __init__(self, name, age, sex='雌性'):self.name = nameself.age =ageself.sex = sexdef run(self):print("{}在跑...".format(self.name))def speak(self,sound):print("{}在叫,'{}'!".format(self.name,sound))dog = Dog("球球",2)dog.run()dog.speak("汪汪汪")

测试结果

类变量

类变量是属于类的变量,不属于单个对象。

例如,有一个Account(银行账户)类,它有三个成员变量:amount(账户金额)、interest_rate (利率)和owner(账户名)。amount和owner对于每一个账户都是不同的,而interest_rate对于所有账户都是相同的。amount和owners是实例变量,interest_rate是所有账户实例共享的变量,它属于类,被称为“类变量”。

测试代码

class Account:interest_rate = 0.0568def __init__(self, owner, amount):self.owner = ownerself.amount = amountaccount = Account('Tony',800000.0)print("账户名:{0}".format(account.owner))print("账户金额:{0}".format(account.amount))print("利率:{0}".format(Account.interest_rate))

测试结果

类方法

类方法与类变量类似,属于类,不属于个体实例。在定义类方法时,它的第1个参数不是self,而是类本身。

测试代码

class Account:interest_rate = 0.0568def __init__(self, owner, amount):self.owner = ownerself.amount = amount@classmethoddef interest_by(cls, amt):return cls.interest_rate *amtaccount = Account('Tony',800000.0)print("账户名:{0}".format(account.owner))print("账户金额:{0}".format(account.amount))print("利率:{0}".format(Account.interest_rate))interest = Account.interest_by(12000.0)print("计算利息:{0:.4f}".format(interest))

测试结果

封装性

封装性是面向对象重要的基本特性之一。封装隐藏了对象的内部细节,只保留有限的对外接口,外部调用者不用关心对象的内部细节,使得操作对象变得简单。

例如,一台计算机内部极其复杂,有主板、CPU、硬盘和内存等,而一般人不需要了解它的内部细节。计算机制造商用机箱把计算机封装起来,对外提供了一些接口,如鼠标、键盘和显示器等,使用计算机就变得非常简单。

私有变量

为了防止外部调用者随意存取类的内部数据(成员变量),内部数据(成员变量)会被封装为“私有变量”。外部调用者只能通过方法调用私有变量。

在默认情况下,Python中的变量是公有的,可以在类的外部访问它们。如果想让它们成为私有变量,则在变量前加上双下画线(__)即可。

由于在类的外部不可以访问私有变量,因此上述代码在运行时会发生错误,通过Python指令运行文件,输出结果。

测试代码

class Account:__interest_rate = 0.0568 #类变量利率def __init__(self, owner, amount):self.owner = ownerself.__amount = amountdef desc(self):print("{0} 金额:{1} 利率: {2}".format(self.owner,self.__amount,Account.__interest_rate))@classmethoddef interest_by(cls, amt):return cls.interest_rate *amtaccount = Account('Tony',800000.0)account.desc()print("账户名:{0}".format(account.owner))print("账户金额:{0}".format(account.__amount))print("利率:{0}".format(Account.__interest_rate))

测试结果

私有方法

私有方法与私有变量的封装是类似的,在方法前加上双下画线(__)就是私有方法了。示例代码如下:

测试代码

class Account:__interest_rate = 0.0568 #类变量利率def __init__(self, owner, amount):self.owner = ownerself.__amount = amountdef __get_info(self):return "{0} 金额: {1} 利率:{2}".format(self.owner,self.__amount,Account.__interest_rate)def desc(self):print(self.__get_info())@classmethoddef interest_by(cls, amt):return cls.interest_rate *amtaccount = Account('Tony',800000.0)account.desc()account.__get_info()

测试结果

使用属性

为了实现对象的封装,在一个类中不应该有公有的成员变量,这些成员变量应该被设计为私有的,然后通过公有的set(赋值)和get(取值)方法访问。

使用set和get方法进行封装,示例代码如下:

测试代码

class Dog:def __init__(self, name, age, sex = "雌性"):self.name = nameself.__age = agedef run(self):print("{}在跑...".format(self.name))def get_age(self):return self.__agedef set_age(self, age):self.__age = agedog = Dog("球球",2)print("狗狗年龄:{}".format(dog.get_age()))dog.set_age(3)print("狗狗年龄:{}".format(dog.get_age()))

测试结果

测试代码

class Dog:def __init__(self, name , age, sex = "雌性"):self.name = nameself.__age = age #创建和实例化私有实例变量__age# 实例方法def run(self):print("{}在跑".format(self.name))@propertydef age(self):return self.__age@age.setterdef age(self, age):self.__age =agedog = Dog("球球",2)print("狗狗年龄:{}".format(dog.age))dog.age = 3print("修改后的狗狗年龄:{}".format(dog.age))

测试结果

继承性

继承性也是面向对象重要的基本特性之一。

在现实世界中继承关系无处不在。例如猫与动物之间的关系:猫是一种特殊动物,具有动物的全部特征和行为,即数据和操作。在面向对象中动物是一般类,被称为“父类”;猫是特殊类,被称为“子类”。特殊类拥有一般类的全部数据和操作,可称之为子类继承父类。

在Python中声明子类继承父类,语法很简单,定义类时在类的后面使用一对小括号指定它的父类就可以了。

测试代码

class Animal:def __init__(self, name):self.name = namedef show_info(self):return "动物名字:{0}".format(self.name)def move(self) :print('动一动')class Cat(Animal) :def __init__(self, name , age):super().__init__(name)self.age = age cat =Cat('Tom',2)cat.move()print(cat.show_info())

测试结果

多继承

在Python中,当子类继承多个父类时,如果在多个父类中有相同的成员方法或成员变量,则子类优先继承左边父类中的成员方法或成员变量,从左到右继承级别从高到低。

方法重写

如果子类的方法名与父类的方法名相同,则在这种情况下,子类的方法会重写(Override)父类的同名方法

多态性

多态性也是面向对象重要的基本特性之一。“多态”指对象可以表现出多种形态。

例如,猫、狗、鸭子都属于动物,它们有“叫”和“动”等行为,但是叫的方式不同,动的方式也不同。

继承与多态

在多个子类继承父类,并重写父类方法后,这些子类所创建的对象之间就是多态的。这些对象采用不同的方式实现父类方法。

测试代码

class Animal:def speak(self):print('动物叫,但不知道是哪种动物叫')class Dog(Animal):def speak(self):print('小狗:汪汪叫')class Cat(Animal):def speak(self):print('小猫:喵喵叫')an1 = Dog()an2 = Cat()an1.speak()an2.speak()

测试结果

09异常处理

为增强程序的健壮性,我们也需要考虑异常处理方面的内容。例如,在读取文件时需要考虑文件不存在、文件格式不正确等异常情况。这就是本章要介绍的异常处理。

测试代码

i = input('请输入数字:')n = 8888result = n / int(i)print(result)print('{0}除以{1}等于{2}'.format(n,i,result))

测试结果

捕获异常

我们不能防止用户输入0,但在出现异常后我们能捕获并处理异常,不至于让程序发生终止并退出。亡羊补牢,为时未晚。

try-except语句

常捕获是通过try-except语句实现的,基本的try-except语句的语法如下。

在try代码块中包含在执行过程中可能引发异常的语句,如果发生异常,则跳到except代码块执行,这就是异常捕获。

测试代码

i = input('请输入数字:')n = 8888try :result = n / int(i)print(result)print('{0}除以{1}等于{2}'.format(n,i,result))except :e=0print('不能除以零,异常')

测试结果

测试代码

i = input('请输入数字:')n = 8888try :result = n / int(i)print(result)print('{0}除以{1}等于{2}'.format(n,i,result))except ZeroDivisionError as e:print('不能除以零,异常:{}'.format(e))

测试结果

从运行的结果可以看出,在输入数字0后,异常发生,跳到except代码块执行。

多个except代码块

多条语句可能会引发多种不同的异常,对每一种异常都会采用不同的处理方式。针对这种情况,我们可以在一个try后面跟多个except代码块,语法如下

测试代码

i = input('请输入数字:')n = 8888try :result = n / int(i)print(result)print('{0}除以{1}等于{2}'.format(n,i,result))except ZeroDivisionError as e:print('不能除以零,异常:{}'.format(e))except ValueError as e:print("输入的是无效数字,异常:{}".format(e))

测试结果

多重异常捕获

测试代码

i = input('请输入数字:')n = 8888try :result = n / int(i)print(result)print('{0}除以{1}等于{2}'.format(n,i,result))except ( ZeroDivisionError, ValueError ) as e:print('异常:{}'.format(e))

测试结果

try-except语句嵌套

测试代码

i = input('请输入数字:')n = 8888try :i2 = int(i)try:result = n /i2print('{0}除以{1}等于{2}'.format(n, i2, result))except ZeroDivisionError as e1:print("不能除以0,异常:{}".format(e1))except ValueError as e2:print('输入的是无效数字,异常:{}'.format(e2))

测试结果

使用finally代码块释放资源

有时在try-except语句中会占用一些资源,例如打开的文件、网络连接、打开的数据库及数据结果集等都会占用计算机资源,需要程序员释放这些资源。为了确保这些资源能够被释放,可以使用finally代码块。

在try-except语句后面还可以跟一个finally代码块,语法如下。

无论是try代码块正常结束还是except代码块异常结束,都会执行finally代码块。

自定义异常类

10常用的内置模块

在真正做项目时,我们会使用别人已经开发好的模块,这样就不必从零开发项目了,还可以加快开发速度。这些模块可能是Python官方提供的,也可能是第三方开发的。Python官方提供的模块,就叫作“内置模块”。

数学计算模块

在math模块中包含数学运算相关的函数等,例如指数、对数、平方根和三角函数等。

![在这里插入图片描述](https://img-/031010400379.png? ,size_16,color_FFFFFF,t_70)

日期时间模块

Python官方提供的日期和时间模块主要是datetime模块。在datetime模块中提供了右侧几个类。

datetime:包含时间和日期。date:只包含日期。time:只包含时间。timedelta:计算时间跨度。tzinfo:时区信息。

datetime类

datetime类表示日期和时间等信息,我们可以使用如下构造方法创建datetime对象:

对这些参数的说明如下表所示

datetime类的常用方法如下。

datetime.today():返回当前的本地日期和时间。

datetime.now(tz=None):返回指定时区的当前日期和时间,参数tz用于设置时区,如果参数tz为None或省略,则等同于today()。

datetime.fromtimestamp(timestamp,tz=None):返回与UNIX时间戳对应的本地日期和时间。UNIX时间戳是从1970年1月1日00:00:00开始到现在为止的总秒数。

date类

date类表示日期信息,我们可以使用如下构造方法创建date对象:

这些参数的含义和取值范围与datetime类一样,这里不再赘述。

date类的常用方法如下。

date.today():返回当前的本地日期。

date.fromtimestamp(timestamp):返回与UNIX时间戳对应的本地日期。

time类

time类表示一天中的时间信息,我们可以使用如下构造方法创建time对象:

计算时间跨度类(timedelta)

参数说明

timedelta可以表示正数或负数时间的间隔,如下代码是等效的

将日期时间与字符串相互转换

我们经常会遇到将日期时间与字符串相互转换的情况。

1 将日期时间对象转换为字符串时,称之为日期时间格式化。

在Python中使用strftime()方法进行日期时间的格式化,在datetime、date和time三个类中都有一个实例方法strftime(format)。

2 将字符串转换为日期时间对象的过程,叫作日期时间解析。

在Python中使用datetime.strptime(date_string,format)类方法进行日期时间解析。

在strftime()和strptime()方法中都有一个格式化参数format,用来控制日期时间的格式,常用的日期和时间格式控制符如下表所示。

正则表达式模块(re)

正则表达式指预先定义好一个“字符串模板”,通过这个“字符串模板”可以匹配、查找和替换那些匹配“字符串模板”的字符串。

字符串匹配

字符串匹配指验证一个字符串是否符合指定的“字符串模板”,常用于用户输入验证。例如,用户在注册时要输入邮箱,所以需要验证邮箱是否有效,这就要用到字符串匹配验证。

我们使用match(p,text)函数进行字符串匹配,其中的参数p是正则表达式,即字符串模板,text是要验证的字符串。如果匹配成功,则返回一个Match对象(匹配对象),否则返回None。

字符串查找

字符串查找指从一个字符串中查找匹配正则表达式的子字符串,常用于数据分析、网络爬虫等数据处理中。

常用的字符串查找函数如下。

search(p,text):在text字符串中查找匹配的内容,如果找到,则返回第1个匹配的Match对象,否则返回None。p是正则表达式。

findall(p,text):在text字符串中查找所有匹配的内容,如果找到,则返回所有匹配的字符串列表;如果一个都没有匹配,则返回None。p是正则表达式。

测试代码

字符串替换

正则表达式的字符串替换函数是sub(),该函数替换匹配的子字符串,返回值是替换之后的字符串,其语法格式如下:

其中,参数pattern是正则表达式;参数repl是用于替换的新字符串;参数string是即将被替换的旧字符串;参数count是要替换的最大数量,默认值为零,表示不限制替换数量。

字符串分割

在Python中使用re模块中的split()函数进行字符串分割,该函数按照匹配的子字符串进行字符串分割,返回字符串列表对象,其语法格式如下:

其中,参数pattern是正则表达式;参数string是要分割的字符串;参数maxsplit是最大分割次数;maxsplit的默认值为零,表示分割次数没有限制。

如何使用官方文档查找模块帮助信息?

打开官方帮助文档

11文件读写

文件是数据的载体,程序可以从文件中读取数据,也可以将数据写入文件中,本章重点介绍如何在Python中进行文件读写。

打开文件

我们在使用文件之前要先将文件打开,这通过open()函数实现。open()函数的语法如下:

open()函数中的参数还有很多,这里介绍4个常用参数,这些参数的含义如下。

1.file参数

file参数用于表示要打开的文件,可以是字符串或整数。如果file是字符串,则表示文件名,文件名既可以是当前目录的相对路径,也可以是绝对路径;如果file是整数,则表示一个已经打开的文件。

2.mode参数

mode参数用于设置文件打开模式,用字符串表示,例如rb表示以只读模式打开二进制文件。用于设置文件打开模式的字符串中的每一个字符都表示不同的含义,对这些字符的具体说明如下。

t:以文本文件模式打开文件。b:以二进制文件模式打开文件。r:以只读模式打开文件。w:以只写模式打开文件,不能读内容。如果文件不存在,则创建文件;如果文件存在,则覆盖文件的内容。x:以独占创建模式打开文件,如果文件不存在,则创建并以写入模式打开;如果文件已存在,则引发FileExistsError异常。a:以追加模式打开文件,不能读内容。如果文件不存在,则创建文件;如果文件存在,则在文件末尾追加。+:以更新(读写)模式打开文件,必须与r、w或a组合使用,才能设置文件为读写模式。

这些字符可以进行组合,以表示不同类型的文件的打开模式,如下表所示。

3.encoding参数

encoding用来指定打开文件时的文件编码,默认是UTF-8编码,主要用于打开文本文件。

4.errors参数

errors参数用来指定在文本文件发生编码错误时如何处理。推荐errors参数的取值为’ignore’,表示在遇到编码错误时忽略该错误,程序会继续执行,不会退出。

测试代码

f = open('test.txt','w+')f.write('World')print('创建test.txt文件,World写入文件')f = open('test.txt', 'r+')f.write('Hello')print('打开test.txt文件,Hello覆盖文件内容')f= open('test.txt','a')f.write(' ')print("打开test.txt文件,在文件尾部追加空格")fname =r'D:\user\文档\python\12文件读写\test.txt'f= open(fname, 'a+')f.write('World')print('打开test.txt文件,在文件尾部追加World')

测试结果

关闭文件

在打开文件后,如果不再使用该文件,则应该将其关闭,会用到close()方法。

在finally代码块中关闭文件

对文件的操作往往会抛出异常,为了保证对文件的操作无论是正常结束还异常结束,都能够关闭文件,我们应该将对close()方法的调用放在异常处理的finally代码块中。

测试代码

f_name = 'test.txt'f =Nonetry:f =open(f_name)print('打开文件成功')content = f.read()print(content)except FileNotFoundError as e:print('文件不存在,请先创建文件')except OSError as e:print('处理OSError异常')finally:if f is not None:f.close()print('关闭文件成功')

测试结果

在with as代码块中关闭文件

测试代码

f_name = 'test.txt'with open(f_name) as f:content = f.read()print(content)

测试结果

with as提供了一个代码块,在as后面声明一个资源变量,在with as代码块结束之后自动释放资源。

读写文本文件

读写文本文件的相关方法如下。

read(size=-1):

从文件中读取字符串,size限制读取的字符数,size=-1指对读取的字符数没有限制。readline(size=-1):

在读取到换行符或文件尾时返回单行字符串。如果已经到文件尾,则返回一个空字符串。size是限制读取的字符数,size=-1表示没有限制。readlines():

读取文件数据到一个字符串列表中,每一行数据都是列表的一个元素。write(s):

将字符串s写入文件中,并返回写入的字符数。writelines(lines):

向文件中写入一个字符串列表。不添加行分隔符,因此通常为每一行末尾都提供行分隔符。flush():

刷新写缓冲区,在文件没有关闭的情况下将数据写入文件中。

复制文本文件

测试代码

f_name ='src_file.txt'with open(f_name, 'r', encoding ='gbk' ) as f:lines = f.readlines()copy_f_name ='dest_file.txt'with open(copy_f_name, 'w',encoding ='utf-8') as copy_f:copy_f.writelines(lines)print('文件复制成功')

测试结果(不对)

原因是scr_file.txt文件需要设置成ANSI

正确的测试结果

读写二进制文件

二进制文件的读写单位是字节,不需要考虑编码问题。二进制文件的主要读写方法如下。

read(size=-1):从文件中读取字节,size限制读取的字节数,如果size=-1,则读取全部字节。readline(size=-1):从文件中读取并返回一行。size是限制读取的行数,如果size=-1,则没有限制。readlines():读取文件数据到一个字节列表中,每一行数据都是列表的一个元素。write(b):写入b字节,并返回写入的字节数。writelines(lines):向文件中写入一个字节列表。不添加行分隔符,因此通常为每一行末尾都提供行分隔符。flush():刷新写缓冲区,在文件没有关闭的情况下将数据写入文件中。

测试代码

f_name = '十三邀.png'with open(f_name ,'rb') as f:b =f.read()copy_f_name = 'logo2.png'with open(copy_f_name, 'wb') as copy_f:copy_f.write(b)print('文件复制成功')

测试结果

13网络通信

本章讲解如何通过Python访问互联网上的资源,这也是网络爬虫技术的基础。

基础的网络知识

TCP/IP

在网络通信中会用到一些相关协议,其中,TCP/IP是非常重要的协议,由IP和TCP两个协议构成。IP(Internet Protocol)是一种低级的路由协议,它将数据拆分在许多小的数据包中,并通过网络将它们发送到某一特定地址,但无法保证所有包都抵达目的地,也不能保证包按顺序抵达。

由于通过IP传输数据存在不安全性,所以还需要通过TCP(Transmission Control Protocol,传输控制协议)进行网络通信。TCP是一种高层次的协议,是面向连接的可靠数据传输协议,如果有些数据包没被收到,则会重发,对数据包的内容准确性进行检查并保证数据包按顺序抵达。所以,TCP能够保证数据包安全地按照发送时的顺序送达目的地。

IP地址

为了实现网络中不同计算机之间的通信,每台计算机都必须有一个与众不同的标识,这就是IP地址,TCP/IP使用IP地址来标识源地址和目的地址。

最初,所有的IP地址都是由32位数字构成的,由4个8位的二进制数组成,每8位之间用圆点隔开,例如192.168.1.1,这种类型的地址通过IPv4指定。现在有一种新的地址模式,叫作IPv6,IPv6使用128位数字表示一个地址。尽管IPv6比IPv4有很多优势,但是由于习惯的问题,很多设备还是采用IPv4。

另外,我们有时还会用到一个特殊的IP地址127.0.0.1,127.0.0.1叫作回送地址,指本机。回送地址主要用于网络软件测试及本机的进程间通信,只发送数据,只进行本机进程间通信,不进行任何网络传输。

端口

一个IP地址标识一台计算机,每一台计算机又有很多网络通信程序在运行,提供网络服务或进行通信,这就需要不同的端口进行通信。如果把IP地址比作电话号码,那么端口就是分机号码,在进行网络通信时不仅要指定IP地址,还要指定端口号

TCP/IP系统中的端口号是一个16位的数字,它的范围是 0~65535。将小于1024的端口号保留给预定义的服务,例如HTTP是80,FTP是21,Telnet是23,Email是25,等等。除非要和那些服务进行通信,否则不应该使用小于1024的端口。

HTTP/HTTPS

对互联网的访问大多基于HTTP/HTTPS,HTTP/HTTPS是TCP/IP的一种协议。

1 HTTP

HTTP(Hypertext Transfer Protocol,超文本传输协议)属于应用层协议,其简捷、快速的方式适用于分布式超文本信息传输。HTTP是无连接协议,即在每一次请求时都建立连接,服务器在处理完客户端的请求后,会先应答客户端,然后断开连接,不会一直占用网络资源。

HTTP/1.1共定义了8种请求方法:OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE和CONNECT。GET和POST方法最常用。

1) GET方法:用于向指定的资源发出请求,被发送的信息“显式”地跟在URL后面。它一般只用于读取数据,例如静态图片等。GET方法有点像使用明信片给别人写信,将“信的内容”写在外面,接触到的人都可以看到,因此是不安全的。

2) POST方法:用于向指定的资源提交数据,请求服务器进行处理,例如提交表单或者上传文件等。数据被包含在请求体中。POST方法像是把“信的内容”装入信封中,接触到该信封的人都看不到信的内容,因此是相对安全的。

2 HTTPS

HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议)是超文本传输协议和SSL的组合,用于提供加密通信及对网络服务器身份的鉴定。简单地说,HTTPS是加密的HTTP。

HTTPS与HTTP的区别是:HTTPS使用https://代替http://,HTTPS使用端口443,而HTTP使用端口80与TCP/IP通信。

urllib.request模块

我们要想在Python中访问互联网资源,则可以使用官方内置的urllib.request模块。

发送GET请求

如果要发送HTTP/HTTPS的GET请求,则可以使用urllib.request模块的Request对象。

发送POST请求

如果要发送HTTP/HTTPS的POST请求,则其发送流程与发送GET请求非常类似。

示例代码如下:

JSON数据

JSON文档的结构

构成JSON文档的两种结构为:JSON对象(object)和JSON数组(array)。

JSON数据的解码(decode)指将JSON数据转换为Python数据,当从网络中接收或从磁盘中读取JSON数据时,需要将其解码为Python数据。

在编码过程中,JSON数据被转换为Python数据

们使用json模块提供的loads(str)函数进行JSON数据的解码,参数str是JSON字符串,返回Python数据。

参考资料

参考资料

[1]/eBook/DLnMGAEG7gKLyYmkAbPaEXxD8BM4J0LM6AWROrpdZn19VNzv2o5e6lqjQQ1poxqy

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