Python学习笔记

一、Python基础

01 注释

注释是为了提高程序可读性,它不参与代码的运行,仅起到辅助代码阅读的作用;开发过程中,核心代码一般要给上注释,便于代码的阅读

  • 单行注释:#

单行注释只能注释掉一行的内容,因此一般的简单说明用单行注释

# 注释内容
  • 多行注释:''' '''

Python中 ’ 和 " 并不影响代码的运行,但是要成对出现,即不可出现' " 或者 " ' 的组合

'''
多行注释
'''

多行注释一般单独占一块区域,用来解释一个区域的代码或者一个函数块的功能

补充:选中多行后,在pycharm中使用快捷键Crtl + / 可以快捷将选中行改为注释

02 变量

变量即存储临时数据的空间(数据的容器);

变量定义的语法:

变量名 = 变量值

注意=不代表任何相等的意思,仅代表赋值

变量命名的规则:

  1. 必须以字母或下划线开头

  2. 变量名由字母、数字、下划线组成;

  3. 变量名不能由数字开头

  4. 变量名严格区分大小写

  5. 不能包含空格、连字符、标点符号或其他特殊字符。

变量命名的规范:

  1. 变量取名应做到见名知意;

  2. 变量名采用下划线命名法且单词首字母全都小写,下划线命名法即两个单词之间用_连接,python中一般不使用小驼峰命名法;

  3. 不能使用Python的内置关键字。

补充:在Python中,变量、函数、文件名、包名、模块名等都用下划线命名法

Python中的数据类型

  1. 数值型:int(整型),float(浮点型);

  2. 布尔型:True,False;

  3. str(字符串);

  4. list(列表);

  5. set(集合);

  6. tuple(元组);

  7. dict(字典)

type() 函数可以直接查看变量的数据类型


#整型  
int1 = 12  
print(type(int1)) # <class 'int'>  
  
#浮点型  
float1 = 12.12  
print(type(float1)) # <class 'float'>  
  
#布尔型  
boole1 = True  
print(type(boole1)) # <class 'bool'>  
  
#字符串  
name = "name"  
print(type(name)) # <class 'str'>  
  
#列表  
list1 = [1,2,3,4]  
print(type(list1)) # <class 'list'>  
  
#元组  
tuple1 = (1,2,3,4)  
print(type(tuple1)) # <class 'tuple'>  
  
#集合  
set1 = {1,2,3,4}  
print(type(set1)) # <class 'set'>  
  
#字典  
dict1 = {'name' : "xiaoming",'age' : 12}  
print(type(dict1)) # <class 'dict'>

数据类型转换

(1)float型转化为int型

注意

  • float型转化为int型时,会直接去掉小数点及其后面的小数部分,仅仅保留整数部分,不是四舍五入
num = 12.945  

print(int(num)) #12
(2)int型转化为float型

注意

  • int型转化为float型时,会直接在整数部分后面添上.0仅添上一个0
num1 = 12

print(float(num1)) # 12.0
(3)int类型、float型转化为str
num1 = 100  

num2 = 12.945  

print(type(str(num1)))  

print(type(str(num2)))

#<class 'str'>
#<class 'str'>

int类型和float型转化为str后,可以使用有关字符串的函数,但是无法进行数学运算

03 格式化输出

字符串格式化:格式化是字符串所具有的功能,字符串的格式化跟输出函数没有任何关系

方式一:占位符实现格式化输出

格式:" 字符串 占位符 " % 变量

重点掌握

  • 字符串占位符为: %s

    • 浮点型占位符为: %f,其中 %.nf 表示保留到小数点后n位,如%.2f表示保留到小数点后两位(也可以使用round(数字,保留的位数))
  • 整型占位符为: %d,其中 %0nd 表示,该数据一共输出n位,不足的位数在前方补0

  • 字符占位符为:%c

name = "小明"  
  
age = 19  
  
score = 90.5  
  
print("学生姓名为:%s,年龄为:%03d,成绩为:%.2f" % (name,age,score)) 
# 学生姓名为:小明,年龄为:019,成绩为:90.50

方式二:f-string字符串格式化

格式:f"字符串 {需要填充的内容}"

注意

  • f{整型变量名:0nd}表示占据n位,不足的用0补齐(和整型占位符为: %d,其中 %0nd 语法一致)

  • f{浮点型变量名:.nf}表示保留到小数点后n位,如%.2f表示保留到小数点后两位

name = "小明"  
  
age = 19  
  
score = 90.5  

print(f"学生姓名为:{name},年龄为:{age:03d},成绩为:{score:.2f}") #学生姓名为:小明,年龄为:019,成绩为:90.50

方式三:format函数

格式:"字符串 {索引}".format(索引位置的值)

注意

  1. 如果没有写索引值,则默认从索引0的值开始填充;

  2. 一个索引值所代表的数据,可以多次被引用

name = "小明"  
  
age = 19  
  
score = 90.5

print("学生姓名为:{0},年龄为:{1:03d},成绩为:{2:.2f};\n {1:03d},{2:.2f},{2:.2f},{1:03d}".format(name,age,score))
# 学生姓名为:小明,年龄为:19,成绩为:90.5;
# 19,90.5,90.5,19

补充

- {整型变量名:0nd},表示占据n位,不足的用0补齐

  • {浮点型变量名:.nf},表示保留到小数点后n位,如%.2f表示保留到小数点后两位

04 输入

Python中使用的输入函数一般是input()函数,它是一个阻塞函数,必须等用户输入信息且按Enter键结束输入后,后续代码才能运行

格式:input(提示字符)

num = input("请输入一个数字:")  

print(type(num))

# 请输入一个数字:3
# <class 'str'>

在Python中,input() 函数返回的是一个字符串

05 运算符

(1)算术运算符

+、-、* 、 / 、% 、// 、 **

分别代表加、减、乘、除、取余、整除、幂

运算的优先级和数学中的运算优先级相同,%、//的优先级和 * / 优先级相同

总的运算优先级:+ - < * / // % < **

(2)赋值运算符

Python中的赋值运算符即:=

赋值格式:变量名 = 变量值

如果同时赋值多个变量,变量之间用 , 间隔,且 =左边的变量名和 =右边的变量值一一对应,变量名的个数和变量值的个数必须相同

补充:复合算术运算符

​ +=、-=、*=、/=、%=

解释:

X += Y —>X + Y,X -= Y —>X - Y, X * = Y —>X * Y, X /= Y —>X / Y
X %= Y —>X % Y

(3)比较运算符

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

比较运算符的运算返回值为bool值,成立为Ture,不成立为Flase

补充

在Python中,比较运算符可以直接连用,不必使用||进行或,且的连接

例如:想判断某个变量是否在某个区间,Java代码如下:

public class select {  
    public static void main(String[] args) {  
        int num = 10;  
        if(num > 0 || num < 20){  
            System.out.println(true);  
        }else{  
            System.out.println(false);  
        }  
    }  
}

而Python代码如下:

num = 10  

print(0 < num < 20) #Ture

(4)逻辑运算符

and,or,not (与MySQL中的相同),其返回结果都是bool类型

运算结果:

  • and:同真即真;

  • or:同假即假;

  • not:真变假,假变真

(5)短路运算符

在Python中,0、空字符串""和None都被看为False,其他数值型和非空字符串都被看为Ture

num = 0
str = ''
cha = None

if (num or str or cha ): # 同假即假
    print("真值输出")
else:
    print("假值输出")
# 假值输出

又有如下规则

  • 在计算 a and b 时,如果a是False,根据运算法则,无论b为何结果,整体的值为False如果a是True,根据运算法则,结果仅被b影响,因此整体的值为b

  • 在计算 a or b 时,如果a是True,根据运算法则,无论b为何结果,整体的值为True如果a是False,根据运算法则,结果仅被b影响,因此整体的值为b

因此,当Python执行判断语句时,只要一个条件就能判断出整个判断语句的最终值,那么Python不会继续执行后续的判断语句

(6)三目运算符

运算符的返回值是 if --else 条件的返回值

num1 = 5  
  
num2 = 6  
  
num_max = num1 if num1 > num2 else num2  # 如果num1 > num2 ,则返回为num1,否则返回num2
  
print(num_max) #num2 = 6

06 选择结构

if语句格式:

if 条件:
	条件成立执行的代码1
	
	条件成立执行的代码2

后续代码 # 没有缩进,无论条件是否成立,都会实现

注意

  • Python中对于缩进有着极其严苛的标准,默认将同一缩进的代码视为包含在统一代码块中,因此非if选择结构的代码不会进行缩进

if…else…语句格式

if 条件:
	条件成立执行的代码1
else:
	条件成立执行的代码2

后续代码 # 没有缩进,无论条件是否成立,都会实现

if…elif…else 语句格式

if 条件:
	条件成立执行的代码1
elif 条件:
	条件成立执行的代码2
else:
	条件成立执行的代码3

后续代码 # 没有缩进,无论条件是否成立,都会实现
  • 不管是哪种if结构,只有一个条件内的代码能被执行

  • if语句可以进行嵌套使用,以达到多条件判断的目的

07 循环结构

while循环

基本语法

while 条件:
	条件成立时重复执行的代码1
	
	条件成立时重复执行的代码2

循环的大体框架

  • 初始条件

  • 循环条件(判断跳出和执行循环的条件)

  • 循环体(重复要做的)

  • 下次循环的准备(i++)

如何写循环

  1. 初始状态如何?

  2. 重复的条件是什么?

  3. 重复做什么事?

  4. 如何才能到下次循环?

while循环的两个关键字:break和continue
break

break即终止当前循环;例如一共五个枣,吃到第三课发现了半条虫子,后续的枣子就都不吃了

num = 1  
while(num <= 5):  
    if (num == 3):  
        print("有半条虫子,不吃了!")  
        break  #关闭循环 循环内后续所有代码不执行
    print("吃了%d颗枣" % num)  
    num += 1

continue

continue即终止本次循环,不影响后续循环

num1 = 0  
while(num1 < 5):  
    num1 += 1  
    if (num1 == 3):  
        print("有一条虫子,换一颗枣吃")  
        continue  #此时不会执行后续的代码 但是会继续执行循环
    print(f"吃了{num1}颗枣")
while循环嵌套

嵌套while循环,顾名思义,就是一个while循环内嵌套着另一个while循环。外层循环控制主要流程,内层循环处理细节逻辑。通过合理设置循环条件,我们可以实现各种复杂的逻辑控制。

注意事项
  • 1、避免死循环:在设置while循环条件时,务必小心避免死循环。死循环会导致程序无法正常退出,消耗大量系统资源。

  • 2、合理设置循环变量:在使用嵌套while循环时,需要合理设置循环变量,确保程序按照预期运行。

  • 3、优化性能:在某些情况下,过度使用嵌套while循环可能导致程序性能下降。因此,在编写代码时,应尽量优化算法和逻辑结构。

while循环的else结构

基本结构

while 条件:
	条件成立时执行的代码
else :
	条件不成立执行的代码,随后循环终止
for循环

基本语法

for 临时变量 in 数据容器:
	重复执行的代码
  • for循环的次数由数据容器中数据量的个数决定

  • for循环是不需要循环条件的,因此不会出现循环不成立的情况

  • for循环必须配合数据容器使用

range函数

range函数返回的是一个整数序列,基本语法如下:

range(start,stop,step)

其含义是:从start开始,以step为步长,到stop结束,但是不包含stop

例如:range(1,11,2):从1开始,到10结束,以2为步长,即1-10内的奇数

注意

  • range默认从0开始,即start不写就默认为0

  • step默认为1

  • range内的迭代值无法被print输出

  • 步长为正数时:start必须大于stop,否则没有数据

  • 步长为负数时:start必须小于stop,否则没有数据

注意

  • for循环中的break关键字,continue关键字的功能和它们在while循环中的效果相同
for i in range(3):  
    user_name = input("请输入用户名:")  
    password = input("请输入密码:")  
  
    if user_name == "admin" and password == "admin8888":  
        print("登陆成功!")  
        break  
    else:  
        times = 2 - i # i从0开始  
        print(f"用户名或密码错误,你还剩{times}次机会")  
    if times == 0:  
        print("3次机会用尽,程序退出!")

08 字符串

定义:字符串是Python中的一种数据类型,通常由"“或者’'括起来,由于Python对”"和’'并不严格区分,因此在Python中不存在字符类型

char = 'a'  
print(type(char)) # <class 'str'>
  • 字符串的底层就是将字符串的每一个字符存连续地存储起来,并给每一个字符特定的索引

  • 索引值按照从左往右是从0开始的,从右往左是从-1开始的

  • 通过不同的索引值可以获取到字符串中的特定字符,格式为:字符串名称[索引值]

str = "人生苦短,我用pytohn"
print(str[0])  # 获取字符串的第一个字符:人(从左往右,以0为索引下标)
print(str[-8]) # 获取字符串的第一个字符:我(从右往左,以-1为索引下标)

字符串切片

所谓切片,即对数据容器中的部分数据进行操作;字符串、列表、元组都支持切片操作

语法:数据容器[开始位置索引:结束位置索引:步长]

str = "兰州牛肉面"
print(str[0:4]) # 兰州牛肉

注意

  • 字符串、列表、元组的切片,都会生成一个新的数据列,不会对原来的数据进行更改

  • 开始位置的索引值是包含的,但是结束位置的索引值是不包含的;

  • 步长就是数据的间隔(相邻数据索引值的差值),当步长为1时,可以省略不写

  • 开始位置索引值可以省略,此时步长若为正数,则起始位置为字符串的开始;若为负数,则起始位置为字符串结尾

  • 结束位置索引值可以省略,此时步长若为正数,则结束位置为字符串的开始;若为负数,则结束位置为字符串结尾

字符串操作方法

1、字符串查找

字符串查找即在字符串中查找子串出现的次数

index函数

index函数返回的是某个字符在字符串的索引值

语法格式:index(子字符串,开始位置索引值,结束为止索引值)

  • 开始位置索引值和结束位置索引值不写时,默认以整个字符串进行查找
str = "好好学习天天向上啊"
print(str.index("习"))  # 3
print(str.index("向上")) # 6 查找的是‘向’这个字的索引值
print(str.index("向下"))  # ValueError: substring not found

注意

  • 当index函数中的字符个数超过1个时,默认按照最开始的字符进行查找

  • 当index函数无法找到对应的子字符串时,会报错

find函数

find函数返回的是某个字符在字符串的索引值

语法格式:find(子字符串,开始位置索引值,结束为止索引值)

  • 开始位置索引值和结束位置索引值不写时,默认以整个字符串进行查找
str = "好好学习天天向上啊"
print(str.index("习"))  # 3
print(str.index("向上")) # 6 查找的是‘向’这个字的索引值
print(str.index("向下"))  # ValueError: substring not found

注意

  • 当find函数中的字符个数超过1个时,默认按照最开始的字符进行查找

  • 当find函数无法找到对应的子字符串时,会返回-1,有时候可以按照find的返回值进行数据的查找

rindex函数和rfind函数

rindex函数、rfind函数的用法和index函数、find函数一样,但是rindex函数和rfind函数是从右往左进行查询,返回的是子字符串的索引

count函数

count函数用于计算指定子字符串在字符串中出现的个数

语法结构:字符串.count(子字符串,开始位置索引值,结束位置索引值)

str = "好好学习天天向上啊"
print(str.count("好")) # 2
2、替换字符串

语法结构:replace(旧子串,新子串,替换次数)

注意

  • 替换次数不写时,默认全部替换;

  • 替换次数不差过子串出现的次数,如果超过了也只会替换出现的所有子串

str = "好好学习天天向下"
print(str.replace("向下", "向上"))  # 好好学习天天向上
# 旧字符串出现的次数仅1次 哪怕替换次数给再多也无法替换
3、分割字符串

语法结构:split(分隔符,最大分割次数)

split函数会按照指定分隔符,将字符串拆成一个个小字符串,最后返回的是以字符串形式组成的列表

str = "好好,学习,天天,向上"
print(str.split(",")) # ['好好', '学习', '天天', '向上']
4、字符串合并

语法结构:合并的分隔符.join(可迭代类型)

注意

  • 在使用join时,必须保证可迭代类型中的所有数据都是字符串类型
str = "好好 学习 天天 向上"
new_str = str.split(" ")
print(new_str) #['好好', '学习', '天天', '向上']
print("".join(new_str)) #好好学习天天向上
5、字符串转换
(1)capitalize

capitalize() 将字符串的第一个字母大写,同时将其余字母小写,但是对汉字、数字、符号等不做处理

str = "hello world HELLO"  

print(str.capitalize()) # Hello world hello
(2)title

title()将所有单词首字母大写 其余字母变小写,但是对汉字、数字、符号等不做处理

str = "hello world HELLO"
print(str.title()) #Hello World Hello
(3)upper和lower

upper()将所有字母全部变为大写,lower()将所有字母变为小写

str = "hello world HELLO"
print(str.lower())  # hello world hello
print(str.upper()) # HELLO WORLD HELLO
6、字符串的删除
(1)字符串两边内容的删除

strip()去除字符串左右两边指定的字符

语法格式:字符串.strip(需要消除的字符)

str = '$$$---hello python$$$'  
print(str.strip("$")) # ---hello python
  • strip()中如果不传入参数,则默认去除字符串左右两端的空白(包括制表符\t、换行符\n、空格等)

  • 如果strip()中有多个字符,如果字符串中首尾出现了包含在内的字符,则会删除否则不删除,跟如何书写的没有关系

str = '12334hello python41323123'  

#字符串首尾出现了123,包含了1、2、3的就删
print(str.strip("123"))  # 4hello python4

#字符串首尾出现了1、2、3、4,包含了1、2、、3、4的就删
print(str.strip("1234")) # hello python

print(str.strip("4123")) # hello python 
(2)字符串某一边内容的删除
  • rstrip()表示删除字符串右边的指定内容;

  • lstrip()表示删除字符串左边的指定内容

str = '12334hello python41323123'  

print(str.rstrip("1234"))  # 12334hello python
print(str.lstrip("1234")) # hello python41323123

7、字符串的判断

判断即判断字符串是否满足某种规则,返回值是布尔型True或False

(1)startwith和endwith
  • startwith即判断字符串是否以某个字符开头

  • endwith即判断字符串是否以某个字符结尾

(2)is判断
方法名解释
isalnum()判断是否全部为数字或字母
isspace()判断是否全部为空格
isnumeric()判断是否全部为数字(可以辨别中文的数字四、肆,阿拉伯数字4)
isdigit()判断是否全部为数字
isdecimal()判断是否全部为数字
isidentified()判断是否为标识符(命名规则)
isalpha判断是否全部为字母(默认中文当做字母)
  • 如果不希望中文也被认作字母,可以使用encode(‘utf-8’).isalpha()

09 列表

定义:列表名 = [数据1,数据2,数据3,…]

  • 列表中可以存储不同的数据类型,如int型、布尔型、浮点型、列表等,但是一般情况下列表中的数据类型是一致的

列表的操作

1、查询

同字符串一样,列表中的值也可以使用索引值进行获取,不过多赘述;

列表的特有方法 in/not in

  • 数据 in 列表名:表示查询列表中是否包含这个数据,返回值为布尔型;

  • 数据 not in 列表名:表示查询列表中是否不包含这个数据,返回值为布尔型;

2、增加
方法名解释
append()增加指定数据到列表中
insert()在指定位置增加数据
extend()在列表的末尾增加数据或增加一个序列
append()

append()方法不会产生新的列表,而是在原列表的基础上直接进行修改,默认是在列表的末尾增加数据

extend()

语法结构:列表1.extend(列表2)

注意

  • 调用完extend()方法后,列表1的数据会被改写,而列表2的数据不会变

  • 如果列表2是一个字符串类型的列表,那么调用完extend()方法后,字符串会被拆分为一个个字符添加到列表1中

insert()

语法格式:列表.insert(插入的位置索引,要插入的对象)

注意

  • 使用insert()插入数据后,原来的索引位上的数据会变成新插入的数据,而后续所有数据的索引位全部加1(即向后移动一位)

  • 由于insert()会改变其他数据的索引值,因此使用append()插入数据要更加安全

补充

  • 列表可以进行拼接
list1 = [1,2,3,4,2,4,3]  
list1 += [6,7,8,9]  
print(list1) # [1, 2, 3, 4, 2, 4, 3, 6, 7, 8, 9]

默认在原有列表的末尾增加指定的列表数据

3、删除
del()

del()函数将数据引用切断,不仅能删除元素更可以删除整个变量

list1 = [1,2,3,4,5]  
list2 = [1,2,3,4,5]  
del list2[1]  
print(list2)  # [1, 3, 4, 5]
del list1  
print(list1)  # name 'list1' is not defined.
  • 被删除元素的索引下标必须存在
pop()

pop()函数删除指定索引对应的元素,并返回该被删除的元素

list3 = [1,2,3,4]  
print(list3.pop(2))  # 3
print(list3) # [1, 2, 4]
  • pop函数会造成索引值的变化

  • 如果不给pop函数传参,默认删除最后的一个元素

  • 被删除元素的索引下标必须存在

remove()

remove()删除指定的元素

list4 = [1,2,3,4,2,4,3]  
list4.remove(2)  
print(list4)  # [1, 3, 4, 2, 4, 3]
print(list4.remove(2)) # None
  • remove()函数无法返回被删除的元素

  • 如果列表中有多个与被删除元素相同的元素,remove()函数只会删除从左往右的第一个相同元素

  • 被删除元素必须存在

clear()

clear()函数会清空列表

list = [1,2,3,4,2,4,3]  
list.clear()  
print(list) # []
4、列表遍历
(1)while遍历列表
list = [1,2,3,4,2,4,3]  
i = 0  
while i < len(list):  
    print(list[i])  
    i += 1
(2)for循环遍历列表
list = [1,2,3,4,2,4,3]  
for i in list:  
    print(

推荐使用for循环进行数据容器(字符串、列表、字典等等)的遍历

10 元组

元组使用小括号 ( ),列表使用方括号 [ ]

元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可

  • 元组中只包含一个元素时,需要在元素后面添加逗号 ”,“ ,否则括号会被当作运算符使用
tuple1 = (1)  
print(type(tuple1))  # <class 'int'>
tuple2 = (1,)  
print(type(tuple2))  # <class 'tuple'>

访问元组

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

tup1 = ('Google', 'Runoob', 1997, 2000)
tup2 = (1, 2, 3, 4, 5, 6, 7 )
print ("tup1[0]: ", tup1[0])  # tup1[0]:  Google
print ("tup2[1:5]: ", tup2[1:5]) # tup2[1:5]:  (2, 3, 4, 5)

注意

  • 元组是不可增删改的,元组内的数据不可更改

  • count、index、len三个函数依然适用于元组,其含义跟列表中的含义一样

  • for循环遍历元组和for循环遍历列表的语法相同

11 字典

字典是另一种可变数据容器,且可存储任意类型对象;

定义:dic = {key1 : value1, key2 : value2, key3 : value3 }

  • 字典的每个键值对用冒号 : 分割,每个对之间用逗号’,'分割,整个字典包括在花括号 {} 中;

  • 必须是唯一的,但值则不必;值可以取任何数据类型,但键必须是不可变的,如字符串,数字。

  • 创建字典可以用内置函数dict(),其语法是:dict(键 = 值)

dic = dict(name = 'Alice', age = 20, gende = 'female')  
print(dic) # {'name': 'Alice', 'age': 20, 'gende': 'female'}

访问字典中的键或者值

语法结构:

  • 字典名[键](获取值)

  • 字典名[值](获取键)

tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'} 
print ("tinydict['Name']: ", tinydict['Name']) # tinydict['Name']:  Runoob
print ("tinydict['Age']: ", tinydict['Age']) # tinydict['Age']:  7

修改字典

1、增加键值对

语法结构:字典名[键] = 值

dic = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}  
dic['School'] = "菜鸟教程"  # 添加信息
print(dic) #{'Name': 'Runoob', 'Age': 7, 'Class': 'First', 'School': '菜鸟教程'}
2、更改键的值

语法结构:字典名[键] = 新的值

dic = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}  
dic['Age'] = 8 
print(dic) # {'Name': 'Runoob', 'Age': 8, 'Class': 'First'}
3、删除字典中的元素

语法结构:del 字典名[键]

tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}  
del tinydict['Name']  # 删除键 'Name' 连同值一起删除  
print(tinydict) # {'Age': 7, 'Class': 'First'}

12 集合

集合(set)是一个无序的不重复元素序列;集合中的元素不会重复,并且可以进行交集、并集、差集等常见的集合操作。

可以使用大括号 { } 创建集合,元素之间用逗号 , 分隔, 或者也可以使用 set() 函数创建集合

set1 = {1, 2, 3, 4}            # 直接使用大括号创建集合
set2 = set([4, 5, 6, 7])      # 使用 set() 函数从列表创建集合

注意

  • 创建空集合必须使用set()函数,不能直接定义{ },因为这样是定义空字典

由于集合是无序不重复的特性,因此可以做为去重的方法

list1 = [1,2,3,4,5,3,2,1,3,5,7]
set1 = set(list1)
list2 = list(set1)
print(list2) # [1, 2, 3, 4, 5, 7]

集合的基本操作

1、添加元素
add()

语法格式:集合名.add(单个数据)

add()函数将单个元素添加到集合中,如果元素已存在,则不进行任何操作

set1= set(("Google", "Runoob", "Taobao"))  
set1.add("Jingdong")  
print(set1) # {'Taobao', 'Jingdong', 'Runoob', 'Google'}
update()

语法格式:集合名.update(参数)

update()函数中的参数可以是列表,元组,字典等,可以添加多个元素进集合

set1= set(("Google", "Runoob", "Taobao"))  
set1.update(["Jingdong","Viphome","LOL"])  
print(set1) # {'Runoob', 'Jingdong', 'Taobao', 'Google', 'Viphome', 'LOL'}
2、删除元素
(1)remove()

remove()函数将元素从集合中移除,如果元素不存在,则会发生错误

(2)discard()

discard()函数将元素从集合中移除,如果元素不存在,不会发生错误

(3)pop()

pop()函数会随机移除集合中的一个元素,此方法执行结果并不相同,pop()方法会对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除

方法名解释
isdisjoint()判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。
issubset()判断指定集合是否为该方法参数集合的子集。
union()返回两个集合的并集

13 推导式

Python 推导式是一种强大且简洁的语法,可以将一种数据类型转化为另一种数据类型

Python 支持各种数据结构的推导式:

  • 列表(list)推导式
  • 字典(dict)推导式
  • 集合(set)推导式
  • 元组(tuple)推导式

列表推导式

列表推导式格式:[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]

names = ['Bob','Tom','alice','Jerry','Wendy','Smith']  
new_names = [name.upper()for name in names if len(name) > 3]  
print(new_names) # ['ALICE', 'JERRY', 'WENDY', 'SMITH']

字典推导式

字典推导式基本格式:

  • { key: value for value in 集合 }
    或者
  • { key: value for value in 集合 if 条件}
dic = {x: x**2 for x in (2, 4, 6)}  #以集合中的数据为键,一定规则为值存放入字典
print(dic) # {2: 4, 4: 16, 6: 36}

集合推导式

集合推导式基本格式:

  • { 规则 for 变量 in 集合 }
  • { 规则 for 变量 in 集合 if conditional }
a = {x for x in 'abracadabra' if x not in 'abc'}  #字符串内除去abc的其他字母被写入集合
print(a) # {'d', 'r'}

元组推导式

元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组;元组推导式基本格式:

  • (expression for item in Sequence )
  • (expression for item in Sequence if conditional )
a = (x for x in range(1,10))  
print(a) # <generator object <genexpr> at 0x000001AF7ECD4040>  这里返回的是生成器对象

print(tuple(a)) # (1, 2, 3, 4, 5, 6, 7, 8, 9)  使用tuple()函数将生成器转化为元组

14 函数

1、函数的定义与调用

函数的定义

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段

我们可以定义一个有自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()

  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数;

  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明;

  • 函数内容以冒号 : 起始,并且缩进;

  • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None

语法格式:

def 函数名(参数列表):
    函数体
    return 返回值
函数的调用

函数的调用可以直接使用定义好的函数名(参数) 直接调用

def square_area(lenth,width):  
    if lenth != 0 and width != 0:  
        return lenth * width  
    else:  
        print("存在0值,数据有误!")  
  
lenth = float(input("请输入长:"))  
width = float(input("请输入宽:"))  
print("面积为:{}".format(square_area(lenth,width)))
  • 函数必须先定义再调用,即调用语句必须在函数定义语句下面,否则会报错

2、参数传递

在Python中,参数是没有数据类型的(不同于java);类型属于对象,对象有不同类型的区分,变量是没有类型的

a=[1,2,3]

a="Runoob"
  • 以上代码中,[1,2,3] 是 List 类型,“Runoob” 是 String 类型,而变量 a 是没有类型的,它仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象

  • 函数定义时传入的参数叫做形参只能在函数体内部使用;在调用时传入的参数叫做实参,传入进函数体内部被形参接收

可更改参数与不可更改参数

在 python 中,strings(字符串), tuples(元组), int(整型),float(浮点型) 是不可更改的对象,而 list(列表),dict(字典),set(集合) 则是可以修改的对象。

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a;

  • 可变类型:变量赋值 la=[1,2,3,4]** 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了

python 函数的参数传递:

  • 不可变类型:如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象
# 传入可变参数
def change(a):  
    print(id(a))  # 对象1  id:140710767215400
    a = 10  
    print(id(a))  # 新对象  id:140710767215688
  
  
a = 1 # 对象1  
print(id(a))  #140710767215400
change(a) 
  • 可变类型:如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
def changeme(mylist):  
    mylist.append([1, 2, 3, 4])  
    print("函数内取值: ", mylist)  # 函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
    return  
  
mylist = [10, 20, 30]  
changeme(mylist)  
print("函数外取值: ", mylist) # 函数外取值:  [10, 20, 30, [1, 2, 3, 4]]
# 这个mylist实际上是已经被调用changme函数后的列表  
位置参数

位置参数即按照位置顺序进行赋值的参数(形参)

def function1(num1,num2,num3):  
    print(num1,num2,num3)  
    
function1(1,2,3) #1 2 3
  • 位置参数的数量必须与函数体定义的参数数量相同,否则会报错
关键字参数

关键字参数就是通过“关键字 = 值”的形式赋值

def function1(num1,num3,num2):  
    print(num1,num3,num2)  
    
function1(num1 = 1 ,num2 = 2,num3 = 3) # 1 3 2
  • 位置参数和关键字参数可以一起使用,但是要注意避免重复赋值
def function1(num1,num3,num2):  
    print(num1,num3,num2)  
function1(1 ,num2 = 2,num1 = 3) #TypeError: function1() got multiple values for argument 'num1'
缺省参数

缺省参数即在定义函数时,给参数一个默认值,如果没有给参数赋值,则参数使用默认值

def func(a,b,c,d = 10):  
    print(a,b,c,d)  
  
func(a = 1, b = 2, c = 3) # 没有传入d的值因此输出默认d的值  1 2 3 10
func(a = 1, b = 2, c = 3, d = 4) # 传入d的值 会输出传入的值 1 2 3 4
位置不定长参数

语法格式

def 参数名(*args):
	函数体
def func(*args):  
    return args  
  
print(func(1, 2, 3)) # (1, 2, 3)  
print(type(func(1, 2, 3))) # <class 'tuple'>
  • 使用位置不定长参数时,数据传入函数内部后会被打包成一个元组,并被args接收,且在函数体内以元组的身份参与运算
关键字不定长参数

语法结构

def 参数名(**kwargs):
	函数体
def func(**kwargs):  
    return print(kwargs)  
  
func(a = 1, b =2, c = 3) # {'a': 1, 'b': 2, 'c': 3}
  • kargs在传参后会将实参位置未定义参数的关键字转化为字典的形式储存,并保存在kargs中
def func(**kwargs):  
    print(f"学生信息:{kwargs}")  
  
func(name = "张三", age = 18, gender = '男') # 学生信息{'name': '张三', 'age': 18, 'gender': '男'}

补充

  • 形参排布顺序为:位置参数 >> 位置不定长参数 >> 缺省参数 >> 关键字不定长参数

  • 调用时,先使用顺序赋值,后使用关键字赋值

3、拆包与组包

(1)组包

组包即将多个数据整合为一个数据容器,赋值给一个变量的过程

a = 1,2,3,4
print(a) # (1,2,3,4) 是一个元组
(2)拆包

拆包即将一个数据容器拆分成多个数据,赋值给多个变量的过程,例如通过循环,取用列表和字典中元素

4、函数的返回值

返回值:将函数内部运算的结果传入函数体外部;使用return关键字搭配使用

语法结构:

  • 函数的返回值如果不写或者只写return,默认会返回None

  • 在一个函数体中,return后会直接跳出函数体,后面的代码不会被执行

  • return只能返回一个元素,如果想返回多个元素,只能使用数据容器(列表、元组等)

5、变量的作用域

(1)局部变量

函数体内部定义的变量即局部变量,函数体外即被释放

def sum():
	a = 1
	b = 2
	print(a + b)
	
sum()



print(a + b) # NameError  a和b是局部变量 在函数体外不可使用
(2)全局变量

全局变量一般顶格书写,在函数体内部和外部都可以使用

def sum():  
    print(a + b)  
a = 11  
b = 10  
  
sum()  # 21
print(a + b) # 21

注意

  • python中,for循环、if分支中的变量全部都是全局变量
list1 = [9,10,11,12,13,14,15,16]  
for i in range(0,8):  
    print(list1[i])  
print(i)  # 7 最后一次循环的临时变量值
  
if True:  
    a = 1  
print(a) # 1
(3)global关键字

global关键字即声明某个变量为全局变量

a = 100  
b = 1  
def whatisa():  
    a = 1  # 局部变量 外部无法使用  
    global b # 改为全局变量  
    b = 10  
  
whatisa()  
print(a)  # 100  
print(b)  # 10

拓展:在python中,所有的变量都遵循legb原则,即调用变量时的顺序

legb原则

  • l:local
    首先在函数体内部查询

  • e:edge
    在外部函数中查询

  • g:globa
    在全局变量中查询

  • b:buil-in
    在系统内部变量中查询

6、引用类型

在Python中,数据分为三个维度:值(判断== )、数据结构(int,float,…)、唯一标识(id),唯一标识可以看做是内存地址

  • 值相等,数据结构和唯一标识不一定相等
# 值相等,数据结构和唯一标识不一定相等  
# 值相同  
num = 0  
boole1 = False  
print(num == boole1) # True  
  
# 数据结构不同  
print(type(num)) # <class 'int'>  
print(type(boole1)) # <class 'bool'>  
  
#唯一标识不同  
print(id(num)) # 140712513487624  
print(id(boole1)) # 140712512019040
  • 值和数据结构都相等的,唯一标识不一定相等
# 值和数据结构都相等的,唯一标识不一定相等  
# 值相同  
list1 = [1,2,3,4,5]  
list2 = [1,2,3,4,5] 
print(list1 == list2) # True  
  
# 数据结构相同  
print(type(list1)) # <<class 'list'>  
print(type(list2)) # <class 'list'>  
  
#唯一标识不同  
print(id(list1)) # 2439105380224  
print(id(list2)) # 2439162217664
  • 唯一标识相同,值和数据结构必定相同
# 唯一标识相同,值和数据结构必定相同  
# ID相同  
str1 = "1234"  
str2 = "1234"  
print(id(str1)) # 2851893434864  
print(id(str2)) # 2851893434864  
  
print(type(str1)) # <class 'str'>  
print(type(str2)) # <class 'str'>  
  
print(str1 == str2) # True

补充: 使用is关键字可以判断变量id是否相同

str1 = "1234"  
str2 = "1234"  
list1 = [1,2,3]  
list2 = [1,2,3]  
print(str1 is str2) # True  
print(list1 is list2) # False

15 文件处理

1、文件的基本操作

(1)打开文件

open()函数可以打开一个已经存在的文件或者创建一个指定文件

语法格式:file = open(name,model)

  • name:目标文件的地址字符串,可以是绝对路径也可以是相对路径

  • model:设置文件的打开方式

model解释
x写模式,新建一个文件,如果该文件已存在则会报错
r以只读方式打开文件,这是默认模式
w打开一个文件只用于写入;如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除;如果该文件不存在,创建新文件
a打开一个文件用于追加;如果该文件已存在, 新的内容将会被写入到已有内容之后如果该文件不存在,创建新文件进行写入
# 创建新文件  
file1 = open("text.txt", 'w', encoding='utf-8')  
# file1.write("1234")
file = open("text.txt", 'r', encoding='utf-8')  
print(file.read())  
file.close()
(2)文件写入

读取模式是’w’的前提下,使用file.write(写入内容)可以将需要写入的内容写入进文件

注意

  • 重新执行write()会清空文件中已有的内容

  • 写入文件时,必须要保证文件打开的编码格式和文件写入的编码格式一致

  • 当要写入多行数据时,可以使用 “”“写入内容”“” 进行写入,此时会将内容和格式一同写入文件

(3)文件读取

读取模式是’r’的前提下

  • 使用file.read(n) 可以将需要写入的文件内容读取出来;其中n代表读取出来的最大字符数,为空默认读取全部数据

  • 也可以使用readline() 函数进行读取,它的作用是:读取一整行的数据

file = open("test.txt", 'r', encoding = 'utf-8')  
while True:  
    lines = file.readline()  # 一行行读 知道读到空字符串即停止
    if lines == "":  
        break  
    print(lines) # 空山新雨后,天气晚来秋。
			 # 床前明月光,疑是地上霜。

  • readlines() 的作用是:读取所有的文件以 【\n】为分隔符 , 将所有的行以字符串元素的方式保存到列表当中进行返回
file = open("test.txt", 'r', encoding = 'utf-8')  
lines = file.readlines()  
print(lines) # ['空山新雨后,天气晚来秋。\n', '床前明月光,疑是地上霜。']

补充:可以使用os模块中的相关功能对文件进行重命名和删除功能

  • 重命名:os.rename(旧文件名称,新文件名称)

  • 删除:os.remove(文件名);删除文件时不会返回任何提示信息,而且不出出现在系统回收站中,此操作需谨慎(一般建议对需要删除的文件进行备份)

2、文件夹处理

Python中的文件夹处理需要使用os模块中的相关功能,在操作文件夹前要导入os模块

import os
(1)创建文件夹

os.mkdir(文件夹名称) ,创建文件夹必须保证此文件夹不存在,否则报错

  • 可以创建多级文件夹,但如果上级文件夹不存在则会报错
(2)删除文件夹

os.rmdir(文件夹名称),删除文件夹必须保证文件夹存在,否则报错

  • 可以删除多级文件夹,但如果上级文件夹不存在则会报错

  • 删除文件夹时必须保证文件夹为空,文件夹不是空文件夹会报错

二、面向对象

1 面向对象技术简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  • 方法: 类中定义的函数。

  • 类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

  • 数据成员: 类变量或者实例变量用于处理类及其实例对象的相关的数据。

  • 方法重写: 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

  • 局部变量: 定义在方法中的变量,只作用于当前实例的类。

  • 实例变量: 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。

  • 继承: 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

  • 实例化: 创建一个类的实例,类的具体对象。

  • 对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

类的定义

类(Class): 用来描述具有相同的属性和方法的对象的集合
类名的定义要使用大驼峰命名法(每个单词的首字母大写)

语法格式:

class (类名)

类的实例化

语法格式:对象名 = 类名()

class MyClass:  
    i = 12345  
  
    def study(self):  
        return 'hello world'  
  
# 实例化类  
x = MyClass()  
  
# 访问类的属性和方法  
print(x.i)   # 12345
print( x.study()) # hello world

(1) self关键字

在类中有一个特殊的关键字——self,指向的是实例化对象本身

在类的内部定义方法时会自动传入参数self,调用实例方法时,无需对self进行传值

self的作用

首先看一个例子

 class Student(object):  
    def study(self):  
        print(self)  
s1 = Student()
print(s1)  # #<__main__.Student object at 0x000001C70854E7D0>  
  
s1.study() # #<__main__.Student object at 0x000001C70854E7D0>

这里s1和self的地址值相同,意味着调用方法时会将对象本身传入方法内进行使用

self可以在方法内部调用实例所拥有的属性或方法

class Student(object):  
    def study(self):  
        print("我在学习")  
        self.eat()  
    def eat(self):  
        print("我在吃饭")  
s1 = Student()  
s1.study() # 我在学习
         # 我在吃饭

s1仅执行了study()方法,但是输出了eat()方法里的内容

(2) 添加和获取对象属性

属性即特征,对象属性既可以在类的外面获取也可以在类里面添加和获取

类外部添加和获取属性

语法结构:

  • 添加属性:对象名.属性名 = 值

  • 获取属性:对象.属性名

class Student(object):  
    def eat(self):  
        print("今天吃了面包!")  
  
s1 = Student()  
s1.name = "zhangsan"  
print(s1.name) # zhangsan  
  
  
s2 = Student()  
s2.age = 18  
print(s1.age,s2.name) #AttributeError: 'Student' object has no attribute 'age'  
  
  
s1.name = "liis"  
print(s1.name) # liis

print(s1.__dict__)  # {'name': 'liis'}
  • 对象被创建后,添加实例属性不会对其他对象造成影响

  • 使用 对象名.属性名 = 值 ,如果当前对象属性存在,则会重新赋值;如果不存在,则会创建一个对象属性

  • 使用

对象名.__dict__

可以查看对象中的属性和对应的值,结果存储在一个字典

类内部添加属性

语法结构

  • 添加属性:self.属性名 = 值

  • 获取属性:self.属性名

class Student(object):  
    def add_attr(self):  
        self.name = "xiaoming"  
        self.age = 19  
        self.gender = "女"  
  
s1 = Student()  
s1.add_attr()  
print(s1.name,s1.age,s1.gender)  # xiaoming 19 女
  
s1.name = "gaiguo"  
print(s1.name) # gaiguo
  • 在内部添加实例属性后,要在外部调用才能被传入

  • 在类的外部可以更改内部添加的实例属性

  • 在内部添加实例属性也不会影响对象之间的关系

(3) 魔术方法

魔术方法一般是系统特定时机自动调用的函数或者方法,绝大多数情况下不需要手动调用

一般格式:

__func__()
1 __init__()方法

在对象创建完成后,初始化对象自动调用的方法

class Student(object):  
    def __init__(self):  
        print("直接调用")  
  
s1 = Student() # 直接调用

只需实例化对象,不需要手动调用,init方法自动调用

2 带参的__init__方法
class Student(object):  
    def __init__(self,name,age):  
        print(name,age)  
  
# s1 = Student("jack") # TypeError: Student.__init__() missing 1 required positional argument: 'age'  
# s1 = Student("jack",16,18) # TypeError: Student.__init__() missing 1 required positional argument: 'age'  
s1 = Student("jack",16) # jack 16
  • 如果__init__方法内提供了参数,那么在实例化对象时必须传入相同数量的参数(不包括self的其他参数数量),否则会报错
class Student(object):  
    def __init__(self,name,age):  
        self.name = name  
        self.age = age  
  
s1 = Student("jack",16)  
print(s1.name,s1.age) # jack 16  
s2 = Student("jack",18)  
print(s2.name,s2.age) # jack 18

使用 self.参数名 = 参数名 可以实现动态传递,此时必须给每个变量单独赋值或者给默认值,否则会报错

3 __str__方法

__str__方法是数据被转换为str类型时自动调用的方法且只能返回字符串类型

class Student(object):  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
    def __str__(self):  
        return f"姓名:{self.name},年龄:{self.age}"  
  
s1 = Student("jack", 16)  
# 直接输出s1 输出的是内存地址  
# print(s1) # <__main__.Student object at 0x000001B72F941350>  
  
# 重写__str__方法后 再输出  
print(s1) # 姓名:jack,年龄:16

自动调用__str__方法的场景

  • 强制类型转换:str(对象)

  • 隐式类型转换:%s占位符,接收对象

2 面向对象三大特征

面向对象的三大特征即封装、继承和多态

  • 封装:将属性和方法写到类中的操作即为封装,封装可以为属性和方法添加私有权限;

  • 继承:子类默认继承父类所有的属性和方法,子类也可以重写父类的属性和方法;

  • 多态:多态必须在继承的条件下才能实现,不同对象调用同一方法或接口,表现不同的状态

1、封装

将属性和方法写入类的内部可以使实例获得较为全面的功能,并可以为属性和方法添加私有权限,保证接口的安全性

封装的优点

  • 可以让一个对象完成所有的功能或业务,同时代码维护和迭代也较为方便;

  • 可以设置私有属性和私有方法,提高代码安全性;

  • 降低模块或者类的使用难度,暴露少量接口即可完成全部功能

私有属性和私有类

属性或者方法只能在类内部调用而无法在类外部调用时,该类或方法成为私有类或私有方法

语法格式:__属性 或者 __方法

class Student(object):  
    def drive(self):  
        print("开着敞篷车")  
  
    def shopping(self):  
        self.drive()  
        print("购物去")  
  
s1 = Student()  
s1.drive() # 开着敞篷车

此时 dirve()只是一个中间方法,不会单独使用,因此将其私有化

class Student(object):  
    def __drive(self):  
        print("开着敞篷车")  
  
    def shopping(self):  
        self.__drive()  
        print("购物去")  
  
s1 = Student()  
# s1.drive() # AttributeError: 'Student' object has no attribute 'drive'
# 此时已无法再类外部使用drive()方法

s1.shopping()
# 开着敞篷车
# 购物去

使用__dict__查看私有属性,私有属性一定带有类名

class Student(object):  
    def __init__(self,name,age):  
        self.name = name  
        self.__age = age  # 私有属性
  
s1 = Student("张三",18)  
print(s1.__dict__) # {'name': '张三', '_Student__age': 18}
私有属性的获取与修改

如果一个数据只能存储数据而无法被获取到,那么这个数据存储方案将毫无意义;在Python中,使用get()和set()方法进行私有属性的获取与设置

class Student(object):  
    def __init__(self,name,age):  
        self.name = name  
        self.__age = age  
  
    def get_age(self):  
        return self.__age  
  
    def set_age(self,age):  
        self.__age = age  
  
s1 = Student("张三",18)  
print(s1.get_age()) # 18  
  
s1.set_age(81)  
print(s1.get_age()) # 81

使用set()方法时,不需要直接调用私有属性

因此,使用get()和set()方法可以对私有属性进行赋值,并在类的外部进行使用

使用get()和set()方法的意义

  • 某些数据在存入或者提取时,不能直接全部显示,也不能无法被调用,此时需要按照一定的规则进行加工,这时get()和set()方法就显得极为方便:例如:身份证号中间数字脱敏,电话号脱敏

  • 存入数据逻辑可以变化:例如存入性别时,可以有如下四个值:0、1、男、女,使用get()和set()方法后可以进行完全统一,不管如何输入都可以统一存放

2、继承

为了体现类的共性与个性,需要使用继承

语法结构

# 父类
calss B(object):
	pass
# 子类
class A(B)
	pass

python中支持多继承,即一个类可以继承多个其他类

(1)单继承

单继承:一个子类继承一个父类,并且可以多级继承

所谓多级继承,即被继承的父类可以是其他类的子类 (孙子类–>父类–>爷爷类)

class Perrson(object):  
    def __init__(self,name,age):  
        self.name = name  
        self.age = age  
  
class Father(Perrson):  
    def shout(self):  
        print("Man!")  
  
    def dance(self):  
        print("What can I say?")  
  
class Son(Father):  
    pass  
  
s1 = Son("张三",23) # 因为 Son 继承了Father Person 类,且Person类传入了参数 因此实例化对对象时要传参  
  
s1.shout()  
s1.dance()
  • 在类Son中,并没有写入其他方法,但是对象s1可以使用父类Father和Person中的公有方法;如果父类中的是私有方法,子类无法调用

  • 如果父类或者更高级的继承类中实现了__init__方法,并书写了参数,则实例化对象时必须传入参数,且数量不得有误

  • 使用 类名.__mro__ 可以输出类的继承链条,同时这个顺序也是方法或者属性查找的顺序

(2)多继承

多继承:一个类定义时继承了多个父类,可以同时使用多个父类中的方法或者属性

语法结构 : class 子类名(父类名1,父类名2…)

class Person(object):
    def sing(self):
       print("我要唱歌")

class Father(object):
    def shout(self):
        print("Man!")

    def dance(self):
        print("What can I say?")


class Son(Person,Father):
    pass

s1 = Son()
s1.sing() # Person类中的方法
s1.shout() # Father类中的方法
s1.dance() # Father类中的方法

当多个父类中,拥有相同的方法时,会优先调用继承位置更靠前的父类中的方法

class Person(object):
    def shout(self):
       print("我要唱歌")

class Father(object):
    def shout(self):
        print("Man!")

    def dance(self):
        print("What can I say?")


class Son(Person,Father): # Person类的继承位置更靠前
    pass

s1 = Son()

s1.shout() # 我要唱歌

s1.dance() # What can I say?

3、多态

多态即子类重写父类中的方法,调用不同子类的相同父类方法,产生不同的执行结果

要求

  • 多态必须依赖继承
  • 子类必须重写父类的方法
class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

class Father(Person):
    def shout(self):
        print("Man!")

class Son(Father):
    def shout(self):
        print("What can I say!")
        
    def __init__(self): # 重写__init__方法后,哪怕父类中有参数子类也不需要再传入参数
        pass

s1 = Son()
s1.shout() # 重写了父类的方法

3 异常、模块和包

1、异常

(1)异常捕获

语法结构

# 如果try中的代码出现异常则执行except中的代码,否则执行try中的代码
# 想要捕获多个异常:如果异常类型超过两个则添加括号,否则不添加
# 使用 as 变量 可以将异常信息传递到变量中,打印这个变量可以获取异常的详细信息
try:
	可能发生异常的代码
except (可能出现的异常类型) as 变量:
	出现异常后执行的代码
# 或者在try后面添加多个except
try:
	可能发生异常的代码
except 可能出现的异常类型1 as 变量:
	出现异常后执行的代码
except 可能出现的异常类型2 as 变量:
	出现异常后执行的代码
except 可能出现的异常类型3 as 变量:
	出现异常后执行的代码
...
try:
    print(a)
    print(1/0)
except(ZeroDivisionError,NameError) as error:
    print(error) # name 'a' is not defined

如果不知道具体的异常信息,可以直接使用 except Exception 捕获所有异常的父类,它包括了所有的异常

try:
    print("a" + 3) # TypeError	
    print(a)
    print(1/0)
except(ZeroDivisionError,NameError) as error:
    print(error)
except Exception:
    print("不知道具体的异常,但是能捕获") # 不知道具体的异常,但是能捕获
(2)else…finally

语法格式

try:
	可能发生异常的代码
except:
	出现异常后执行的代码
else:
	try中没出现异常则执行的代码
finally:
	无论是否出现异常都会执行的代码
try:
    print("a" + 3)
    print(a)
    print(1/0)
except(ZeroDivisionError,NameError) as error:
    print("出现异常")
else:
    print("没出现异常")
finally:
    print("无论出不出现异常都会执行")

print("能执行吗?") # TypeError: can only concatenate str (not "int") to str
                  # 无论出不出现异常都会执行

上述例子中

  • 出现了TypeError,但是并未捕获到,所以else的语句无法执行

  • 由于未捕获异常,因此程序崩溃,未缩进的print()语句无法执行;

  • 但是哪怕是程序崩溃,finally中的语句都会被执行

2、模块

模块(Module)就是一个.py文件,包含了Python对象定义和Python语句;模块能定义函数、类和变量,也包含了可执行的代码

(1)模块的导入方式

  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名
  • from 模块名 import * (导入这个模块中的全部功能)

(2)自定义模块

自定义模块中可以书写很多内容,但是导入时会将所有内容执行一遍;

自定义模块导入其他文件中、全局变量、函数和类

自定义模块的注意事项:

  • 自定义模块的命名必须符合标识符命名规则;
  • 自定义模块的命名不能与系统模块重名
  • 自定义模块要见名知意
__name__

__name__的作用是:说明当前文件执行的模块名

如果__name__的结果是__main__,这说明是在当前文件中打开;如果__name__的结果是__main__结果是其他文件名,则说明是在导入模块中打开

# model.py

a = 10
print(a) # 10
print(__name__) # __main__
# model_new.py

import model
# 10
# model
__all__

__all__表示控制import的功能列表

语法结构:__all__ = [功能名1,功能名2…],不包含在[]内的功能列表无法被导入使用

3、包

包就是一个文件夹,该文件夹下包含很多有联系的模块还有一个名为__init__.py的文件,包的本质依然是模块

导包的方法:

  • import 包名.模块名
  • from 包名 import 模块名
  • from 包名.模块名 import 功能名

__init__.py文件中通过__all__ = [] 控制import * 导入的内此时不会完全导入* 而是导入[]内的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值