TreeMind树图在线AI思维导图
当前位置:树图思维导图模板IT互联网产品结构python思维脑图思维导图

python思维脑图思维导图

  收藏
  分享
免费下载
免费使用文件
U463699873 浏览量:422024-04-20 17:40:43
已被使用5次
查看详情python思维导图

语言概述,语法知识,控制结构,序列等内容讲解

树图思维导图提供 python思维脑图 在线思维导图免费制作,点击“编辑”按钮,可对 python思维脑图  进行在线思维导图编辑,本思维导图属于思维导图模板主题,文件编号是:a0bddae97bad22c753cc657ebce5d661

思维导图大纲

python思维导图模板大纲

(一)Python语言概述

python语言的特点注释符、缩进

特点

优点

语言简单

开源、免费

面向对象

跨平台

强大的生态系统

缺点

速度慢

存在多线程性能瓶颈

代码不能加密

Python2.x和Python3.x不兼容

注释符

单行注释

使用“#”表示单行注释

可以作为单独的一行放在被注释代码行之上,或者也可以放在语句或表达式之后

多行注释

使用三个单引号或三个双引号表示多行注释

中文注释

主要是为了解决Python2.x中不支持直接写中文的问题

在文件第一行加上# -*- coding:utf-8 -*-

缩进

采用代码缩进和冒号来区分代码之间的层次

缩进可以使用空格或者Tab键来实现

当使用空格作为缩进时,建议使用4个空格作为一个缩进量

简单python程序的基本构成

python程序的开发环境与调试

开发环境

交互式环境

IDLE

第三方开发环境

PyCharm

Eclipse

Jupyter Notebook

调试

(二)基础语法知识

关键字和标识符

关键字

具有特定的含义,只能用于特定的位置

'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'

所有关键字是区分字母大小写的

标识符

类名、对象名、方法名和变量名等,统称为“标识符”

标识符由一个或多个字母(A~Z 和 a~z)、数字、下划线(_)构成,长度不限

第一个字符不能是数字

标识符不能是关键字

应该避免标识符的开头和结尾都使用下划线的情况

变量

在程序运行过程中值可以被改变的量

Python解释器会根据赋值语句来自动推断变量类型,且变量的类型是可以随时变化

在Python3.x中,允许变量名是中文字符

基本数据类型

数字

整数

八进制0o,十六进制0x

浮点数

浮点数也可以用科学计数法表示,比如1.3e4、-0.35e3、2.36e-3

布尔类型

空对象、值为零的任何数字或者对象None的布尔值都是False

True的值为1,False的值为0,可以进行数值运算

复数

复数由实数部分和虚数部分构成,可以用a + bj或者complex(a,b)表示

字符串

使用单引号(' ')、双引号(" ")或三引号(''' '''或""" """)进行界定

单引号和双引号中的字符序列必须在一行上,而三引号内的字符序列可以分布在连续的多行上

转义字符,即使用反斜杠“\”对一些特殊字符进行转义

\n 换行符

\t 制表符

\' 单引号

\r 回车

\\ 一个反斜杠\

\" 双引号

数据类型转换

int(x)

把x转换成整数类型

float(x)

把x转换成浮点数类型

str(x)

把x转换成字符串

chr(x)

将整数x转换成一个字符

ord(x)

将一个字符x转换成对应的整数值

基本输入输出

使用input()输入

x = input("提示文字")

在Python3.x中,无论输入的是数字还是字符串,input()函数返回的结果都是字符串

使用print()输出

print(输出的内容)

print()函数默认是换行的,如果要实现输出不换行的功能,那么可以设置end=''

使用%进行格式化输出

%f:保留小数点后6位有效数字,如果是%.3f则保留3位小数

%e:保留小数点后6位有效数字,按指数形式输出,如果是%.3e,则保留3位小数位,使用科学记数法

如果有6位有效数字,则使用小数方式,否则使用科学记数法,如果是%.3g,则保留3位有效数字,使用小数方式或科学记数法

字符串进行格式化输出

%s:字符串输出

%10s:右对齐,占位符10位

%-10s:左对齐,占位符10位

%.2s:截取2位字符串

%10.2s:10位占位符,截取两位字符串

使用“f-字符串”进行格式化输出

print(f'{表达式}'),例如:print(f'姓名:{name},年龄:{age}')

使用format进行格式化输出

例如:print('{1} {1} {0}'.format('hello','world')) ,结果是world world hello

运算符和表达式

算术运算符和表达式

+,-,*,/,%,**,//

赋值运算符和表达式

+=,-=,*=,/=,%=,**=,//=

比较运算符和表达式

>,<,==,!=,>=,<=

逻辑运算符和表达式

and,or,not

运算符的优先级与结合性

(三)程序控制结构

程序控制结构

顺序结构

从上而下,一条一条地顺序执行

选择结构

又称为“分支结构”,分支语句根据一定的条件决定执行哪一部分的语句序列

循环结构

使同一个语句组根据一定的条件执行若干次

选择语句

if

如果表达式的值为真,则执行语句块,如果表达式的值为假,则跳过语句块,继续执行后面的语句

if-else

else不能单独使用,必须和if一起使用

if-elif-else

elif不能单独使用,必须和if一起使用

if语句嵌套

判断某一年是否闰年。闰年的条件是:(1)能被4整除,但不能被100整除的年份都是闰年,如1996年、2004年是闰年;(2)能被100整除,又能被400整除的年份是闰年,如2000年是闰年。不符合这两个条件的年份不是闰年

循环语句

while

for

嵌套循环

打印出该菱形 * *** ***** ******* ********* ******* ***** *** *

数字回转方阵

跳转语句

break

break语句将跳出当前的循环体

continue

跳过当前循环的剩余语句,然后继续进行下一轮循环

pass

表示空语句,它不做任何事情,一般起到占位作用

编写一个程序,计算给定列表中所有奇数的平方和。如果列表中出现了负数,则停止计算并打印 "有负数,停止计算"。

(四)序列

列表

使用方括号

创建与删除

使用赋值运算符直接创建列表 :list = ['hadoop', '年度畅销书',[2020,12000]]

创建新的空列表的方法如下: empty_list = []

list()函数,它可以将range()对象、字符串、元组或其他可迭代类型的数据转换为列表,例如:num_list = list(range(1,10,2))

当列表不再使用时,可以使用del命令删除整个列表,例如motto = ['自强不息','止于至善'],del motto

访问列表

使用索引访问列表中的元素,例如 list = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] >>> print(list[1]) Tuesday

用for循环访问:for i in list

添加,删除,修改列表元素

添加元素

append(),用于在列表的末尾追加元素,例如books.append("flink"),id不变

insert(),用于将元素添加至列表的指定位置,id不变

extend(),可以将另一个迭代对象的所有元素添加至该列表对象尾部, >>> num_list = [1,1,2] >>> num_list.extend([3,4]) >>> num_list [1, 1, 2, 3, 4] id不变

“+”运算符来把元素添加到列表中, >>> num_list = [1,2,3] >>> num_list = num_list + [4] >>> num_list [1, 2, 3, 4] id变化,由于添加新元素时,创建了一个新的列表,并把原列表中的元素和新元素依次复制到新列表的内存空间

list=list1+list2和list+=list2不一样

“*”运算符扩展列表对象。可以将列表与整数相乘,生成一个新列表,新列表是原列表中元素的重复,例如num_list = num_list*3,id变化

删除元素

使用del语句删除指定位置的元素

del demo_list[0]

使用pop()删除列表末尾的元素

demo_list.pop()

使用remove()方法删除首次出现的指定元素

>>> num_list = [1,2,3,4,5,6,7] >>> num_list.remove(4) >>> num_list [1, 2, 3, 5, 6, 7]

修改元素

按下标重新赋值的形式修改 >>> books = ["hadoop","spark","flink"] >>> books[2] = "storm" >>> books ['hadoop', 'spark', 'storm']

统计计算列表

获取指定元素出现的次数,count()

>>> books= ["hadoop","spark","flink","spark"] >>> num = books.count("spark") >>> print(num) 2

获取指定元素首次出现的下标, index(value,[start,[stop]]),其中,start和stop用来指定搜索范围,start默认为0,stop默认为列表长度

>>> books = ["hadoop","spark","flink","spark"]>>> position = books.index("spark") >>> print(position) 1

统计数值列表的元素和,sum(aList[,start]),其中,aList表示要统计的列表,start表示统计结果是从哪个数开始累加,如果没有指定,默认值为0

>>> score = [84,82,95,77,65] >>> total = sum(score) #从0开始累加 >>> print("总分数是:",total) 总分数是: 403 >>> totalplus = sum(score,100) #从100开始累加 >>> print("增加100分后的总分数是:",totalplus) 增加100分后的总分数是: 503

列表排序

使用列表对象的sort()方法排序 aList.sort(key=None,reverse=False),其中,aList表示要排序的列表,key参数来指定一个函数,此函数将在每个元素比较前被调用,例如,可以设置“key=str.lower”来忽略字符串的大小写;reverse是一个可选参数,如果值为True,则表示降序排序,如果值为False,则表示升序排序,默认为升序排序。

使用内置的sorted()函数排序,sorted(aList,key=None,reverse=False),其中,aList表示要排序的列表,key参数来指定一个函数,此函数将在每个元素比较前被调用,例如,可以设置“key=str.lower”来忽略字符串的大小写;reverse是一个可选参数,如果值为True,则表示降序排序,如果值为False,则表示升序排序,默认为升序排序

成员资格判断

使用in操作符判断一个值是否存在于列表中

>>> books = ["hadoop","spark","flink","spark"]>>> "hadoop" in books True

使用not in操作符判断一个值是否不在列表中

>>> books = ["hadoop","spark","flink","spark"]>>> "storm" not in books True

使用列表对象的count()方法,如果指定的值存在,则返回大于0的数,如果返回0,则表示不存在

使用index()方法查看指定值在列表中的位置,如果列表中存在指定值,则会返回该值第一次出现的位置,否则会抛出错误

切片操作

通过切片操作可以生成一个新的列表(不会改变原列表),listname[start : end : step]

可以结合使用del命令与切片操作来删除列表中的部分元素,实例如下: >>> num_list = [13,54,38,93,28,74,59,92,85,66]>>> del num_list[:4] >>> num_list [28, 74, 59, 92, 85, 66]

列表推导式

[表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] ]

b_list = [x * x for x in a_range if x % 2 == 0]

二维列表

是指列表中的每个元素仍然是列表

元组

创建元组

创建空元组:tuple1 = ()

当元组中只包含一个元素时,需要在元素后面添加逗号,tuple1 = (50,)

tuple1 = tuple(range(1,10,2))

访问元组

可以使用下标索引来访问元组中的元素

也可以象列表一样,采用切片的方式来获取指定的元素

可以使用for循环实现元组的遍历

修改元组

元组中的元素值是不允许修改

连接生成新元组tuple3 = tuple1 + tuple2

重新赋值得到新元组 >>> tuple1 = (1,2,3) >>> tuple1 = (4,5,6)

删除元组

del tuplename

元组推导式

(表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] )

使用元组推导式生成的结果并不是一个元组,而是一个生成器对象,这一点和列表推导式是不同的

可以使用__next__()方法遍历生成器对象来获得各个元素,获得一个就少一个

常用内置函数

len(tuple):计算元组大小,即元组中的元素个数; max(tuple) :返回元组中的元素最大值; min(tuple) :返回元组中元素最小值;

与列表区别

列表属于可变序列,元组属于不可变序列

元组和列表都支持切片操作,但是,列表可以使用切片方式来修改其中的元素,而元组则不支持使用切片方式来修改其中的元素

元组的访问和处理速度比列表快

元组可以作为字典的键,而列表则不可以

序列封包和解包

把多个值赋给一个变量时,Python会自动将多个值封装成元组

>>> values = 1, 2, 3 >>> values (1, 2, 3)

将序列(元组或列表等)直接赋值给多个变量,此时序列的各元素会被依次赋值给每个变量(要求序列的元素个数和变量的个数相等),这种功能被称为“序列解包”

a, b, c, d, e = a_tuple

字典

特性

字典的元素是“键值对”,字典中的键不允许重复,必须是唯一值,而且键必须不可变

字典不支持索引和切片,但可以通过“键”查询“值”

字典是无序的对象集合

字典是可变的,并且可以任意嵌套

创建与删除

创建空字典:empty_dict = {}

zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组

>>> x = [1,2,3] >>> y = ["a","b","c"] >>> zipped = zip(x,y) >>> list(zipped) [(1, 'a'), (2, 'b'), (3, 'c')] >>> tuple(zipped) ((1, 'a'), (2, 'b'), (3, 'c'))

删除字典:del grade

clear()方法清空字典中的所有元素,让字典变成一个空字典

grade.clear()

访问字典

通过键来访问值

使用字典对象的items()方法获取“键值对”列表,使用字典对象的keys()方法获取“键”列表,使用字典对象的values()方法获取“值”列表

items = grade.items()

keys = grade.keys()

values = grade.values()

通过for循环对items()方法返回的结果进行遍历

for item in grade.items():

pop()方法用于获取指定键对应的值,并删除这个键值对

>>> grade = {"语文":67, "数学":91, "英语":78} >>> grade.pop("英语") 78 >>> grade {'语文': 67, '数学': 91}

添加,修改,删除字典元素

当需要添加或修改字典对象某个元素的值时,可以直接为该元素赋予新值

删除字典的某个元素:del grade["英语"]

使用字典对象的update()方法,用一个字典所包含的键值对来更新己有的字典。在执行update()方法时,如果被更新的字典中己包含对应的键值对,那么原值会被覆盖;如果被更新的字典中不包含对应的键值对,则该键值对被添加进去

>>> grade = {"语文":67, "数学":91, "英语":78} >>> grade.update({"语文":59,"数学":91,"英语":78,"计算机":98}) >>> grade {'语文': 59, '数学': 91, '英语': 78, '计算机': 98}

字典推导式

{表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]}

newdict = {v: k for k, v in olddict.items() if v>5}

集合

集合用{}表示

无序的不重复元素序列,且集合中的元素必须是不可变类型

创建与删除

创建空集合:empty_set = set()

{表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]}

删除集合:del numset

集合元素添加与删除

add()方法向集合中添加元素,被添加的元素只能是字符串、数字及布尔类型的True或者False等,不能是列表、元组等可迭代对象

使用pop()、remove()方法删除集合中的一个元素,使用clear()方法清空集合中的所有元素

numset.pop()

>>> numset{2, 3, 4, 5} >>> numset.remove(4)

numset.clear()

交并差

a & b #交集| a.intersection(b) #交集

a | b #并集

a - b #差集 a.difference(b) #差集

(五)字符串

基本概念

不可变类型

使用单引号或者双引号包裹起来,不能以双引号开始、单引号结束,可以使用三重引号来表示一个多行字符串

如果不希望在输出时将换行符也输出,就需要在行尾增加一个“\”

索引与切片

索引

>>> aString = "你好!世界" >>> aString[3] '世'

切片

使用aString[m:n]这种写法,这里的m必须小于n,返回的值包含m而不包含n

aString[m::n],从字符串的索引值为m(即第m+1个字符)开始,每n个字符取出一次的情况,其中n为正数,则查询方向为正向索引的方向,n为负数,则查询的方向为反向索引的方向

如果使用了错误的索引值,那么系统将返回一个空字符串,而不会提示一个错误或者异常

>>> aString[-1:-3] ''

拼接

+

result = prefix + "thon"

%

result = "%sthon" % prefix

join函数

需要将列表[“Hello”, “World”, “Python”]用逗号拼接,可以采用如下方式: >>> ",".join(["Hello", "World", "Python"]) 'Hello,World,Python'

可以直接将多个字符串字面量连续书写,从而将其自动连接

特殊字符与字符转义

在Python 3.x中,缩进推荐使用“空格符”,并且不允许混合使用“制表符”和“空格符”。如果打开的是Python 2.x的代码,那么就需要将混合使用的缩进统一转换为“空格符”

原始字符串和格式化字符串

原始字符串

指在字符串前加入先导符“r”(也可以是大写的“R”),之后,字符串里的所有内容都不会被转义

>>> aString = r"c:\desktop\python\homework.py" >>> print(aString) c:\desktop\python\homework.py

格式化字符串

[填充文本][对齐方式][符号显示规则][#][0][填充宽度][千分位分隔符][.<小数精度>][显示类型]

默认情况下,填充字符是空格符

“<”表示左对齐,“>”表示右对齐,“^”表示居中对齐,“=”比较特殊,它只能用在数字上,表示填充时把填充文本放在正负号的右边

符号显示规则”的取值在默认情况下是“-”,即表示只有负数才显示符号,正数不显示。取值为“+”时,表示无论正数还是负数都显示符号。为“空格符”时,表示正数在符号位显示一个空格,负数显示负号。

在格式化规则中,“#”后面的0(比如上面实例中的{0:<+#08x}),其含义等价于将填充字符修改为0

千分位分隔符只有两种取值,即“,”和“_”,实例如下: >>> "{0:10,}{0:10_}".format(1000000)' 1,000,000 1_000_000'

在千分位分隔符之后的是小数精度,也就是显示的小数位数,不足的部分会用0补齐

显示类型

字符串类型

整数类型

小数类型

在字符串前加入前导符“f”或者“F”。在使用时,将格式规格迷你语言的第一部分换成变量名或者表达式就可以了

>>> price = 10 >>> amount = 5 >>> f"价格:{price * amount:.2f}" '价格:50.00'

(六)函数

普通函数

基本定义及调用

圆括号内可以定义参数列表(可以为0个、1个或多个参数),即使参数个数为0,圆括号也必须有;函数形参不需要声明其类型

写四个函数,分别实现求两个列表的交集、并集、差集、补集的功能

自己写一个reverse函数,将输入的数字逆序输出,例如5431,输出1345

有一个nXn的整数矩阵,其值放在二维数组a中。编程求出其中的最大值并放于max 中,输出最大值及其所在的行号row和列号col

def 函数名(参数列表): 函数体

文档字符串

函数的第一行语句可以选择性地使用文档字符串用于存放函数说明,可以用内置函数help()查看函数的说明或者函数名.__doc__来查看函数的注释

第一行应为对象目的的简要描述; 如果有多行,则第二行应为空白。其目的是将摘要与其他描述有个视觉上的分隔。后面几行应该是一个或多个段落,描述对象的调用约定、副作用等

函数标注

函数及函数的形参都可以不用指定类型,,但是这往往会导致在阅读程序或函数调用时无法知道参数的类型

Python提供“函数标注”的手段为形参标注类型。函数标注是关于用户自定义函数中使用的类型的元数据信息,它以字典的形式存放在函数的“ __annotations__ ”属性中

形参标注的方式是在形参后加冒号和数据类型,函数返回值类型的标注方式是在形参列表和def语句结尾的冒号之间加上复合符号“->”和数据类型

def anno_demo(p1:str,p2:str = "is my favorite!")->str : s = p1 + " " + p2 print("函数标注:",anno_demo.__annotations__) print("传递的参数:",p1,p2) return s

函数标注仅仅是标注了参数或返回值的类型,但并不会限定参数或返回值的类型,在函数定义和调用时,参数和返回值的类型是可以改变的

return语句

“return [表达式]”语句用于退出函数,选择性地向调用方返回一个表达式。特别地,不带表达式的return返回None

变量作用域

变量(包括局部变量和全局变量)的作用域都是从定义的位置开始,在定义之前访问则会报错

函数内定义的局部变量,其作用域仅在函数内;一旦函数运行结束,则局部变量都被删除而不可访问

在函数内部可以通过global定义的方式来定义全局变量,该全局变量在函数运行结束后依然存在并可访问

如果局部变量和全局变量名字相同,则局部变量在函数内部会“屏蔽”同名的全局变量

函数的递归调用

函数在定义时直接或间接调用自身的一种方法

构成递归需要具备以下条件: 子问题须与原来的问题为同样的问题,但规模较小或更为简单; 调用本身须有出口,不能无限制调用,即有边界条件。

阶乘

斐波那契数列

汉诺塔

折半查找

匿名函数

匿名函数没有函数名,其lambda表达式只可以包含一个表达式,常用于不想定义函数但又需要函数的代码复用功能的场合

1.lambda表达式中只包含一个表达式,函数体比 def 简单很多,所以匿名函数更加简洁2.lambda表达式的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去; 3.lambda函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。

匿名函数名 = lambda [arg1 [,arg2,.....argn]]:expression

参数传递

给函数传递不可变对象

不可变对象在传递给函数时,实参和形参是同一个对象(值和地址都相同),但在函数内部,不可变对象类型的变量重新赋值后,形参变成一个新的对象(地址发生改变),函数外部的实参在函数调用前后并未发生改变。可见,对于不可变对象的实参,传递给函数的仅仅是值,函数不会影响其引用(存放地址)

给函数传递可变对象

传递可变对象的实参,事实上是把值和引用都传递给形参。函数内部对于形参的改变,也同时改变了实参

参数类型

位置参数

在函数调用时是必须有的,而且顺序和数量都要保持一致

关键字参数

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。所以,在函数调用中,多个关键字参数的顺序可以随意,但是关键字参数必须跟随在位置参数的后面

默认参数

在函数定义时,某个参数使用了默认值,则该参数是默认参数;如果函数调用时没有传递该参数,则使用默认值

不定长参数

*parameter

接收多个实参并将其放在一个元组中

**parameter

接收键值对并将其放在字典中

特殊形式

参数传递的序列解包

可以用列表、元组、集合、字典或其他可迭代的对象作为实参来进行参数传递,这需要在实参名称前加一个星号(*),此时Python解释器会将实参进行所谓的解包操作,将序列中的值分别传递给多个单变量的形参

两个星号(**)则是针对字典的值进行解包的,需要注意的是,字典的键须要与形参的名称保持一致,否则会报错

(七)面向对象程序设计

面向对象编程概述

对象与类

对象

面向对象编程的核心概念是对象

对象是建立在数据和基于数据的操作之上的实体

不同的对象之间相互依存但边界清晰

对象之间逻辑边界清晰,在对象之外,整个程序就是各种对象的生成、调用、交互与销毁的过程

通过对象的概念,将数据和业务逻辑细节进行合适的隐藏,只对外提供一些访问接口,用户无需知道对象内部实现的细节,但可以通过该对象对外提供的接口与对象进行安全有效的交互,这个过程称为“封装”,它使得程序的组织更加清晰,可读性更强,同时可扩展性更好

类是对不同对象的共同属性和共同行为特征的抽象

作为一种抽象的数据类型,类定义了对象所具有的静态特征和动态行为,将静态特征称为“属性”,将动态行为称为“方法”

类是用来创建对象的蓝图或模板,通过类这个模板,可以制造出一个个具体的对象,这些对象称为“类的实例”,这个过程称为“实例化“

从同一个类实例化出的对象具有相同的属性和方法,但属性的取值可能不同,方法的执行结果也可能不同

继承与多态

继承

为了提高代码的复用性,可以将两个类型所共有的功能抽象为一个上层类型,而将扩展的功能抽象为一个下层类型,用继承来表示这种类型之间的层级关系

继承是通过已存在的类来建立新类的技术,已存在的类称为“父类”或“基类”,新类称为“子类”或“派生类”

新类不仅继承了父类的属性和方法,还可以增加新的属性和方

继承所表示的从属关系具有传递性,如果B继承A,C继承B,那么也可以说C继承A

子类在继承父类时,除了可以原封不动地继承父类的方法,还可以修改父类的方法,这个过程称为“重写”

基于这一原则,经常将一些具有类似功能但实现细节不是完全一致的方法抽象到父类中,父类只描述这种方法的对外输入输出功能,而不给出具体的实现,这种方法称为“抽象方法”,包含这种方法的类称为“抽象类”

当从抽象类派生子类时,子类需要根据具体的场景实现父类中定义的抽象方法,不同的子类给出的具体实现可能不一样

多态

同一个方法具有不同实现的特征,称为“多态”

多态使得程序的灵活性或可扩展性更好

Python中的面向对象

对象

每个对象可以有多个变量名,但只有一个唯一的整数值身份号(identity),可以使用内置函数id()来查看对象的身份号

一个对象一旦被创建,身份号就保持不变

Python采用引用计数技术自动管理对象所占用内存的回收,一般来说,用户不需要关注该过程

如果对象所包含的值不能改变,则称为“不可变对象”,反之,如果所包含的值可以改变,则称为“可变对象”

Python用关键字None表示空对象。没有显式返回值的函数都默认返回None对象

对于一个给定的对象,可以用“.”运算符调用其属性或方法,使用内置函数dir()可以查看对象所支持的所有属性与方法,该函数将对象的所有属性名和方法名以一个列表的形式返回

Python将所有对象分成了不同的类别,这个类别就称为对象所属的“类”,或称为“类型”

可以使用内置函数type()来查看一个对象所属的类型

Python里一切都是对象,那么对象所属的类型本身也是对象,例如int、str、list及function等,都是对象 >>> type(int) <class 'type'>

Python的官方文档中关于“类型”有两个对应的词,分别是“class”和“type”,表示类型这个概念时,这两个词之间可以互换使用;当分别作为自定义类的关键字和类型对象所属的类名时,不能互换

Python具有丰富的内建类型系统

第一类是用于表示数据的内建类型,例如int、str等基本数据类型以及诸如list及set等序列类型

第二类是用于表示程序结构的内建类型,例如函数对象的类型、type类型,还有后文将提到的object类型(表示所有类型的默认父类型)

第三类是用于表示Python解释器内部相关操作的类型,例如,types.TracebackType表示的是异常出现时的回溯对象的类型,它记录了异常发生时的堆栈调用等信息

自定义类

类的定义与实例化

class 类名: """类文档字符串""" 类的实现

类的文档字符串是位于类体最前面的、一个由三引号包括起来的字符串,作为类的帮助文档。定义好后可以使用类的__doc__属性来获取该字符串

类名必须是一个合法的Python标识符,且按照Python的编码规范,类名的首字母要求大写

类的实现部分包括属性和方法的定义,属性和方法统称为类的成员

类方法的第一个参数都是指向调用者实例的引用,在定义时一般都习惯用self作为参数名

在类的内部,成员之间的相互访问也需要使用“.”操作符,而不能直接用成员名进行访问

构造器

当实例化一个类时,Python会自动调用一个名为“__new__”的方法,创建一个最原始的对象,该方法继承自父类object

有了这个原始对象后,再使用该对象调用一个名为“__init__”的特殊方法进行对象的初始化

这些方法并不需要由用户显式调用,而是在实例化类时自动被调用,称为“类的构造器(constructor)方法”

在实际应用中,用户一般不需要重写“__new__”方法,只需要重新实现“__init__”方法来执行一些具体的初始化操作

“__init__”方法可以有参数,这些参数将在实例化时被提供,当然也可以像普通函数一样,给这些参数提供默认值

类属性与实例属性

类属性

类属性在类内部的所有方法之外进行定义

类属性是由类及类的所有实例共用的,可以通过类名或实例名进行访问

类可以通过“.”运算符读取或修改类属性

类实例可以读取类属性,但不能直接修改类属性

当类实例企图用“.”运算符直接修改类属性时,实际发生的是,为实例对象动态地添加了一个与类属性同名的实例属性,这时如果还需要访问同名的类属性,就需要用到名为“__class__”的特殊类属性,该属性将返回实例所属的类对象,这样,可以使用“__class__”的返回值间接修改类属性

实例属性

与类属性不同的是,实例属性是由一个具体的实例所独有的,不同实例的实例属性之间是完全独立的。

实例属性一般在构造器“__init__”方法里面初始化

得益于Python的动态类型特性,除了在类的内部进行定义,类属性和实例属性都可以在使用时动态添加

使用“类名.新的类属性名 = 初始值”来动态添加类属性,添加成功后,类的所有实例都拥有这个新增加的类属性

使用“类的实例.新的实例属性名 = 初始值”来动态添加实例属性,添加成功后,该实例属性只属于相应的实例,类的其它实例并没有相应的实例属性

在创建一个类时,Python会自动创建一个名为“__dict__”的特殊实例属性,该属性是一个字典对象,它保存了实例的所有其它实例属性名及其相应的值。另外,还可以使用del关键词删除类属性或者实例属性

实例属性会覆盖同名的类属性,这种使用会增加调试困难,同时可能会带来潜在的漏洞,因此要尽量避免

方法

类方法

在调用实例方法之前,必须有一个相应类型的实例。但在有些场景下,我们可能需要在没有实例的情况下通过类本身来调用一些方法

Python提供了名为“类方法(classmethod)”的概念来实现这一功能

与实例方法类似,类方法的第一个参数也是自动传入的,但该参数是对类本身的引用,按照惯例,在定义时一般将该参数命名为cls

类方法可以通过类或者类的实例进行调用,Python会自动将相应的类对象作为第一参数传入

类方法最常见的作用是充当辅助构造器的角色来创建实例

静态方法

仅仅是将一个普通函数的定义移到了类的内部,因此需要用类或者类的实例进行调用,但是调用时不会隐式传入调用者信息

这类方法称为“静态方法”,定义时需在方法前加上内置的“@staticmethod”装饰器

魔法方法

采用双下划线开头和双下划线结尾,Python将其视为一种特殊方法,具有特定的调用约定

这类方法一般不是被用户直接调用,而是按照某种约定被自动地间接调用。Python官方文档中将这类自动被调用的方法称为“魔法方法

魔法方法主要用于对象的构造、运算符重写及访问控制等

类的继承

继承

为了实现类的继承,只需要在自定义类名后添加一个括号,并将需要继承的父类名放在括号里。除了拥有自定义的属性和方法外,子类将自动继承父类的所有成员

子类可以直接访问父类的公有成员和保护类型成员,也可以重写父类的公有和保护类型成员

子类不能直接访问父类的私有成员,但可以通过父类名前缀间接访问,由于私有成员的命名改写(name mangling)规则,子类不会重写父类的私有成员

如果子类没有实现构造器方法,则实例化子类时将自动调用父类的构造器方法,如果子类重写了构造器方法,则必须显式调用父类的构造器方法,这将用到内建的super()函数,该函数返回一个临时的父类对象

当对一个对象调用某个成员时,如果该对象所属的类没有定义该成员,Python将自动在对象的父类中依次查找,直到找到该成员,如果一直都没有找到,则会提示AttributeError异常

Python允许多重继承,即一个类可以有多个直接父类,定义时只需将不同的父类名放在类名后的括号内,并用逗号隔开。如果每个类都只有一个直接父类,当对一个对象调用某个成员时,Python将自动在对象所属的类及其父类中依次查找,直到找到该成员。

Python提供了一个名为object的类。如果一个类在定义时没有指明父类,则其直接父类为object类,也就是说,Python的任何一个类都直接或间接派生自object类

一旦一个类直接或间接继承了另外一个类,子类的实例也是父类的实例,可以通过内建的isinstance()函数和issubclass()函数来查看这种对象及类之间的继承关系,前者用于查看一个实例对象是否属于某个类的实例,后者用于查看一个类是否属于另一个类的直接或间接子类

需要强调的是,继承虽然可以有效地减少重复的代码,但继承已经破坏了对象的封装性,父类的实现细节对于子类来说都是透明的

多态

多态一般指的是用一个父类的方法在不同的子类中有不同的具体实现

Python完全支持多态行为,不同子类只需要重写父类的同名方法,实例在调用被重写的方法时,将根据实际的子类类型选择相应子类的方法

不仅在类的继承上可以表现多态,在普通的函数定义上也可以表现多态行为,只要传入函数的对象具有相应的属性和方法,则在函数内部这些对象就会表现出相应的多态行为

(八)模块

创建与使用

创建

python模块类型

系统内置模块

例如sys、time、json模块等等

自定义模块

第三方开源模块

这部分模块可以通过“pip install”命令进行安装,有开源的代码

新建一个rectangle.py文件,这个文件就可以看作是一个模块

可以在程序中使用import语句导入已经创建的模块

import modulename [as alias]

在导入模块以后,如果要调用模块里面的变量、函数或者类时,需要在变量名、函数名或者类名前带上模块名作为前缀

如果我们不想在每次导入模块时都创建一个新的命名空间,而是将具体的定义导入到当前的命名空间中,这时可以使用from…import语句

在这种情况下,在调用模块里的变量、函数时,就不再需要使用模块名作为前缀

from modulename import member

如果要导入全部定义,可以使用通配符“*”

python自带的标准模块

使用pip管理python扩展模块

为了便于用于安装和管理第三方库和软件,Python提供了一个扩展模块(或扩展库)管理工具pip,Python3.8.7在安装的时候会默认安装pip

pip优点

pip提供了丰富的功能,包括扩展模块的安装和卸载,以及显示已经安装的扩展模块

pip能够很好地支持虚拟环境

pip可以集中管理依赖

pip能够处理二进制格式

pip是先下载后安装,如果安装失败,也会清理干净,不会留下一个中间状态

pip命令

安装模块

pip install SomePackage

列出当前已经安装的所有模块

pip list

升级模块

pip install --upgrade SomePackage

卸载模块

pip uninstall SomePackage

(九)异常处理

异常的概念

异常是程序运行过程中产生的错误。在程序解析时没有出现错误,语法正确但在运行期间出现错误的情况即为异常

引发异常的原因有很多,除以零、溢出异常、下标越界、不同类型的变量运算、内存错误等都会产生异常

异常处理结构

try/except

首先执行try子句代码块(在关键字try和except之间的语句)。如果没有产生异常,则忽略except子句,try子句执行后正常结束

如果try子句代码块在执行过程中产生异常,则立即被捕获,同时跳出try子句代码块,进入except子句代码块,进行异常处理。在except子句的代码块中,可以根据try子句抛出的异常的不同类型,进行相应的处理。如果异常的类型与except之后的名称相同,则对应的except子句被执行

如果一个异常没有与except匹配,则该异常会传递给上层的try中(如果有的话)

try/except...else...

如果try子句代码块产生异常,则执行其后的一个或多个except子句,进行相应的异常处理,而不去执行else子句代码块;如果try子句代码块没有产生异常,则执行else子句代码块

这种结构的好处是不需要把过多的代码放在try子句中,而是放那些真的有可能产生异常的代码

try/except...finally...

不管try子句代码块是否产生异常,也不管异常是否被except子句所捕获,都将执行finally子句代码块

如果try子句中产生的异常没有被except子句捕捉到,或者except子句或else子句中又产生新的异常,则这些异常会在finally子句执行后再次抛出

try/except...else...finally...

抛出异常

Python中使用raise语句强制抛出指定的异常

>>> raise AttributeError('false attribute') Traceback (most recent call last): AttributeError: false attribute   >>> raise Exception Traceback (most recent call last): Exception   >>> raise Exception("AException") Traceback (most recent call last): Exception: AException

raise只有唯一的参数,就是要抛出的指定的异常。参数必须是一个异常的实例或者是派生自Exception的异常类

相关思维导图模板

线尚线思维脑图思维导图

树图思维导图提供 线尚线思维脑图 在线思维导图免费制作,点击“编辑”按钮,可对 线尚线思维脑图  进行在线思维导图编辑,本思维导图属于思维导图模板主题,文件编号是:b18ab228102bb24c74e3227330b6849e

工程项目文档思维导图思维导图

树图思维导图提供 工程项目文档思维导图 在线思维导图免费制作,点击“编辑”按钮,可对 工程项目文档思维导图  进行在线思维导图编辑,本思维导图属于思维导图模板主题,文件编号是:718a88d0c4fb7156de16d684c08f2d78