Python基础_学习笔记
一、前言
二进制文件打开后以十六进制展示
字符集
markdown
# ASCII
美国7位-128个
# ISO-88591
欧美8位-256
# GBK
中国
# unicode
万国码,一般编写程序时使用此编码
多种实现
utf-8 1-5个字节 最常用
utf-16 2-4字节
utf-32 4字节
# 出现乱码后要去检查编解码方式
计算机语言的发展
markdown
# 机器码
01010101
二进制机器执行快,但编写麻烦
# 符号语言(汇编)
1、符号替代机器码
2、编写完成后需要转换为机器码,再由计算机执行,符号转换为机器码的过程我们把它叫做汇编。将机器码转换为符号我们称之为反汇编,。
3、汇编语言一般只适合某些硬件,兼容性较差
# 高级语言
高级语言与英语语法类似,并且与机器的联系没有那么紧密了,也就是说我们可以通过高级开发语言在不同的硬件系统上执行,并且学习起来也相对容易,我们熟知的开发语言基本都是高级语言,例如c、c++、c#、Java、JavaScript、python
编译型语言和解释型语言
markdown
# 编译型语言
c语言会将.c的文件编译为机器码然后交由计算机执行
执行速度快
跨平台性差
# 解释型语言
Java、JS、Python
一边执行一边编译,将源码交给解释器,解释器解释执行
执行速度慢
跨平台性好
二、Python简介
Python应用场景
markdown
# 解释型语言
life is short you need python (人生苦短,我用python)
# 用途
- web应用
- 爬虫程序
- 科学计算
- 自动化运维
- 大数据(数据清洗)
- 云计算
- 桌面软件/游戏
- 人工智能
Python开发环境
markdown
# 安装python的解释器
CPython
用c语言编写的Python解释器
PyPy
用python开发的python解释器
IronPython
用.net开发的python解释器
JPython
用java开发的python解释器
# 下载安装包
https://www.python.org/downloads/
Python 交互模式
markdown
三个大于号属于命令提示符,输入命令即可执行
安装python时自动安装了IDLE,通过IDLE也可以进入交互模式,最大的特点是可以通过TAB按键来补全代码(需要把文件后缀名改为.py)
基础概念
markdown
# 表达式
1 + 5
2 * 9
# 语句
打印信息、获取数据、为变量赋值
print()
# 程序(program)
由一条一条的语句和一条一条的表达式组合而成
# 函数(function)
函数就是一种语句,完成特定的功能
内置函数
自定义函数
三、Python基础概念
Python基本语法
markdown
- 不用写分号
- "#"开头的为注释
- 每行最好不超过80个字符,使用反斜杠"\"来充当代码的换行符
变量
markdown
- 1.1 python变量不需要声明,直接赋值使用就可以
- 1.2 如果使用没有赋值的变量,会报错
- 1.3 python是动态类型语言,可以为变量赋值任意类型的值,也可以任意修改变量的值
标识符
markdown
1. 所有的可以自主命名的内容都属于标识符,比如变量名、函数名、类名
2. 可以包含字母、数字、下划线,但不能以数字开头
3. 标识符不能是Python的关键字或者保留字
4. 命名规范
4.1 下划线命名法。所有单词小写,单词之间以下划线分割(常用于日常编程)
4.2 帕斯卡命名法(大驼峰命名法)。首字母大写、每个单词首字母大写其余命名小写(常用于类名)
数值
markdown
1. 在Python中数值分为三种:整数、浮点数(小数)、复数
2. 在Python中所有的整数都是int类型,大小没有限制可以无限大。如果数字过大可以用下划线作为分割符号
999_999_999_999_999_999_999 * 10
# 表示其他进制的整数(只要输出一定是以十进制显示)
二进制 0b开头 0b10
八进制 0o开头 0o10
十六进制 0x开头 0x10
# 浮点(小数)
在Python中所有的浮点数都是float类型,但对于浮点数进行运算的时候可能会出现不精确的数字。
c = 0.1 + 0.2
字符串
markdown
- 长字符串,单引号和双引号不能跨行使用
- 单引号和双引号比如成双入对
- 三重引号可以换行并保留字符串中的格式 """ '''
- 字符串只能和字符串拼接
- print函数中以参数去传递字符串,这样可以格式化
转义字符
markdown
\'
\"
\n
\t
\\
\u2250
格式化字符串
markdown
# 1个占位
b = 'hello %s'%yuchao
# 2个占位
c = 'hello %s %s'%(name1,name2)
# 第一个占位符至少3个位置,不够的话空格自动补全
d = 'hello %3s %s'%(name1,name2)
# 第一个占位符限制3到5个位置
e = 'hello %3.5s %s'%(name1,name2)
# 保留两位小数且自动四舍五入
f = 'hello %.2f '%1234.546
# 只取整数
g = 'hello %d '%1234.546
# 各个占位符
%s 任意字符串
%f 浮点占位符
%d 整数占位符
# 格式化字符串,使用f可以直接嵌入变量,有点像前端的表达式写法
print(f'hello {name1} {name2}')
# 四种格式化方式
print('欢迎' + yuchao + '光临')
print('欢迎',yuchao,'光临')
print('欢迎%s光临'%yuchao)
print('欢迎%s%s光临'%(yuchao,'第一次'))
print(f'欢迎 {yuchao} 光临')
复制字符串
python
a = 'abc'
a = a * 2
print(a)
布尔值和空值
python
True
False
# True 相当于1 False相当于0
# None 空值 用来表示不存在
None
类型检查
python
type()
# 通过类型检查,可以检查只能值(变量)的类型
# 该函数将检查结果作为返回值返回,可以通过变量来接收函数的返回值
a = '123'
b = 123
c = 123.123
d = True
e = False
f = None
print(type(a))
print(type(b))
print(type(c))
print(type(d))
print(type(e))
print(type(f))
<class 'str'>
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'bool'>
<class 'NoneType'>
四、对象
对象(object)
markdown
- Python是一种面向对象的语言
- 一切皆对象
- 程序运行中,所有的数据都是存储到内存中然后在运行的
- 对象就是特意用来存储数据的一块区域
- 数值、字符串、布尔值这些都是对象
对象的结构
markdown
# 每个对象中都要保存三种数据
- id
> id用来标识对象的唯一性,每一个对象仅有一个唯一的id
> 可以通过id()来查询对象的id
> id是由解析器生成的,在Cpython中id就是对象的解析地址
> 对象一旦创建成功其id值不能再改变
- type(类型)
> 用来标示当前对象的数据类型
> 类型决定了对象具备什么功能
> 可以通过type()函数来查看对象的类型
> Python是一门强类型语言,对象一旦创建则不能修改其类型
- value
> 值是对象中具体存储的数据
> 对于有些对象值是可以改变的
> 对象分为两大类,可变对象 不可变对象
可变对象的值可以改变
不可编对象的值不能改变,之前学习的对象都是不可变对象
变量和对象
markdown
- 对象并没有直接存储到变量中,在Python中变量的作用更像是一个别名。
- 变量中存储的不是对象的值,而是对象的id(内存地址)
当我们使用变量时,实际上就是通过对象id在查找对象
- 变量中保存的对象,只有在为变量重新赋值时才会改变(重点!!!与java不同!!)
- 变量和变量相互之间是独立的,修改一个变量不会影响另一个变量
类型转换
markdown
类型对象不是改变原有对象,而是根据对象的当前值转换为一个新的对象。(有点像java的String字符串)
# 类型转换函数
int() float() str() bool()
- int()
规则
> 布尔值:True -> 1 False -> 0
> 浮点数:直接取整,省略小数点后的数字
> 字符串:符合整数的可以转换,不符合的报错
> 对于其他不可以转换类型的对象直接报错
- float()
规则基本与int()一致,不同的是会将对象类型转换为float
- str()
规则
> 布尔值:True -> 'True' False -> 'False'
> 整数: 123 -> '123'
> 浮点数 : 123.123 -> '123.123'
- bool() 可以将对象转换为布尔值,任何对象都可以被转换为布尔值
规则:对于所有表示空性质的对象都会转换为False,其余为True
0 None ''
五、运算符
算术运算符
python
+ #(如果是字符串则拼接)
-
* # (如果是字符串则复制后拼接)
/ #(运算后总会产生一个浮点类型)
// # (整除,只会保留整数)
** # (幂运算,n次方)
print(2 ** 3)
# 平方根
print(15 ** 0.5)
% # 取模,求两数相除的余数
赋值运算符
python
# 右侧的值赋值给左侧的变量
a = 5
a += 10
a -= 10
a /= 10
a //= 10 # 在对浮点数做复制运算时,//也会返回浮点数
a *= 10
a **= 10
关系运算符
python
>
>=
<
<=
# 比较的是对象的值,而不是引用地址或者id,与Java不一样
==
!=
# is 或者 is not 使用对象的id来比较其是否相等
is
is not
返回:True | False
# python中可以针对字符串做关系运行算(大于)或者(小于)的运算
# 当对于字符串进行比较时,实际上比较的是unicode编码
print('2' > '3') # False
print('2' > '1') # True
# python比较字符串是通过逐位比较的
# 利用该特性可以对字符串的顺序根据unicode来进行排序
print('2' > '11') # True
print('ab' > 'abc') # False
# 注意:如果不希望根据unicode来比较,则需要使用int函数int()将其转换为int类型
print(int('2') > int('11')) # False
逻辑运算符
markdown
- not 逻辑非
> 对于布尔值,会对布尔值取反,True -> False , False -> True
> 对于非布尔值,会将数值先转换为布尔值,然后再取反
- and 逻辑与
> 只有两边同时为True时,才会返回True,只要有一个False就会返回False
> 与运算是找False的
> Python中的逻辑与是短路与,如果第一个为False则不再看后面的布尔值
- or 逻辑或
> 或运算是找 True 的
> Python中的逻辑或是短路或,如果第一个为 True 则不再看后面的布尔值
- 逻辑运算符可以连着写
temp = 1 < 2 < 3
# 相当于 2 > 1 and 2 < 3
temp = 10 < 20 > 15
# 相当于 10 < 20 and 20 > 15
非布尔值的运算
python
# 我们对非布尔值的与或运算,Python会将其当作布尔运算,最终会返回原值
result = 1 and 2 # 2
result = 1 and 0 # 0
result = 0 and 1 # 0
result = 0 and None # 0
# 与运算时找False的,如果第一个值为False则直接返回第一个值,如果第一个值为True,则直接返回第二个值
# 或运算是找True的,如果第一个值为True则直接返回第一个值,如果第一个值为Flase,则直接返回第二个值
条件运算符 三元运算符
python
# 语法
> 语句1 if 条件表达式 else 语句2
a = 30
b = 50
c = 40
# 计算最大值
max = a if a > b else b
max = max if max > c else c
print(max)
max = a if (a > b and a > c) else (b if b > c else c)
print(max)
运算优先级
python
# 可以通过官方文档的表格查询,位置越靠下的地方优先级越高
# and 优先级高于 or
emp = 1 or 2 and 3
print(temp) # 1
# 开发过程中通过小括号来改变优先级
emp = ( 1 or 2 ) and 3
print(temp) # 3
六、分支语句
if语句
python
# if单行
num = 123
if num < 456: print("正确")
# if多行,以缩进作为区分,python严格要求缩进
if num > 50:
print("1")
print("2")
print("3")
print("4")
print("5")
print("这里结束if语句了")
# 因为tab占用字符可能在不同的编辑器不一致,所以官方建议使用空格作为分隔符,不过实际开发中没有强限制
# 如果要使用,如果使用空格就都适用空格,如果使用tab就都使用tab,现有编辑器设置后可以将tab转换为空格
input函数
python
age = input("请输入您的年龄,本程序自动计算距离退休时间:")
sex = input("请输入您的性别,本程序自动计算距离退休时间:")
if sex == "男":
print(65 - int(age))
if sex == "女":
print(60 - int(age))
if else
python
age = int(input("请输入您的年龄,本程序自动计算距离退休时间:"))
sex = input("请输入您的性别,本程序自动计算距离退休时间:")
if sex == "男":
print(65 - age)
else:
print(60 - age)
If elif else
python
# if-elif-else 只有一个代码块会执行
# 如果逻辑出现问题则会出现永远不会执行的代码 dead code 要尽量去避免的
age = int(input("请输入你的年龄:"))
if age < 18:
print("您是未成年人")
elif age < 30:
print("您是年轻人")
elif age < 40:
print("三十而立啦")
elif age < 50:
print("四十不惑啦")
elif age < 60:
print("五十知天命啦")
elif age < 70:
print("六十花甲之年啦")
elif age < 80:
print("七十古稀啦")
else:
print("高寿高寿!!")
if else的练习
python
# 判断是奇数还是偶数
num = int(input("请输入一个数字,程序自动判断奇数、偶数:"))
if num % 2 != 0:
print(f"您输入的{num}是一个奇数")
else:
print(f"您输入的{num}是一个偶数")
练习2
python
# 便携一个程序检查一个年份是否是闰年
# 提示:如果一个年份可以被4整除不能被100整除,或者可以被400整除,那这个年份就是闰年
year = int(input("请输入一个年份,程序自动判断是否是闰年:"))
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
print(f"您输入的{year}是闰年")
else:
print(f"您输入的{year}不是闰年")
练习3
python
# 练习3:
# 我家的狗5岁了,5岁的狗相当于多大年龄的人呢?
# 其实非常简单,狗的前两年每一年相当于人类的10.5岁,然后每增加一年就增加四岁。
# 那么5岁的狗相等于人类的年龄就应该是10.5+10.5+4+4+4+4=33岁
# 编写一个程序,获取用户输入的狗的年龄,然后通过程序显示其相当于人类的年龄
# 如果用户输入负数,请显示一个提示信息
dog_age = int(input('请输入小狗的年龄:'))
if dog_age < 0:
print("请输入正确的小狗年龄!")
elif dog_age <= 2:
person_age = 10.5 * dog_age
print(f"{dog_age}岁的小狗相当于{person_age}岁的人")
else:
person_age = (2 * 10.5) + (dog_age - 2) * 4
print(f"{dog_age}岁的小狗相当于{person_age}岁的人")
# 使用if嵌套实现 (通过缩进来实现嵌套,与Java和c的括号不一样)
dog_age = int(input('请输入小狗的年龄:'))
if dog_age > 0:
if dog_age <= 2:
person_age = 10.5 * dog_age
print(f"{dog_age}岁的小狗相当于{person_age}岁的人")
else:
person_age = (2 * 10.5) + (dog_age - 2) * 4
print(f"{dog_age}岁的小狗相当于{person_age}岁的人")
else:
print("请输入正确的小狗年龄!")
练习4
markdown
# 练习4:
# 从键盘输入小明的期末成绩:
# 当成绩为100时,"奖励一辆BMW
# 当成绩为[80-99]时,'奖励一台iphone'
# 当成绩为[60-79]时,'奖励一本参考书
# 其他时,什么奖励也没有
score = int(input("请输入小明的成绩(0-100):"))
if score > 100 or score < 0:
print("请输入合法的分数!!")
else:
if score == 100:
print("奖励一辆BMW")
elif score >= 80:
print("奖励一台iphone")
elif score >= 60:
print("奖励一本参考书")
else:
print("啥也没有,要不奖励两本高考真题吧!")
练习5
python
# 练习5:
# 大家都知道,男大当婚,女大当嫁。那么女方家长要嫁女儿,当然要提出一定的条件
# 高:180cm以上;富:1000万以上;帅:500以上;
# 如果这三个条件同时满足,则:我一定要嫁给他
# 如果三个条件有为真的情况,则:嫁吧,比上不足,比下有余。
# 如果三个条件都不满足,则:不嫁!'
high = int(input("你输入你的身高(cm):"))
deposit = int(input("你输入你的存款(万):"))
score = int(input("你输入你的颜值分数(1-1000):"))
if high >= 180 and deposit >= 1000 and score >= 500:
print("我一定要嫁给他!")
elif high >= 180 or deposit >= 1000 or score >= 500:
print("嫁吧,比上不足,比下有余!")
else:
print("滚!!")
七、循环语句
While循环
python
# 初始化表达式 条件表达式 更新表达式
num = 1
while num < 10000:
print(num)
num += 1
else:
print("程序结束啦")
# 练习1:
# 求100以内所有的奇数之和
count_num = 1
odd_num = 0
while count_num <= 100:
if count_num % 2 != 0:
odd_num += count_num
count_num += 1
else:
print(f"求100以内所有的奇数之和算完啦,100以内所有奇数之合为:{odd_num}")
# 练习2:
# 求100以内所有7的倍数之和, 以及个数
count_num = 1
odd_num = 0
seven_num = 0
while count_num <= 100:
if count_num % 7 == 0:
odd_num += count_num
seven_num += 1
count_num += 1
else:
print(f"求100以内所有7的倍数之和为:{odd_num},个数为{seven_num}")
# 练习3:
# 水仙花数是指一个n位数(n>=3), 它的每个位上的数字的次幂之和等于它本身(例如: 1 ** 3 +
# 5 ** 3 + 3 ** 3 = 153 )。
# 求1000以内所有的水仙花数
i = 100
while i < 1000:
thousand = i // 100
hundred = i // 10 % 10
# units_digit = i - (thousand * 100 + hundred * 10)
units_digit = i % 10
# print(f"当前数字:{i},千位数:{thousand},百位数:{hundred},个位数:{units_digit}")
if thousand ** 3 + hundred ** 3 + units_digit ** 3 == i:
print(f"1000以内的水仙花数{i}")
i += 1
else:
print("结束啦")
# 练习4:
# 获取用户输入的任意数, 判断其是否是质数
number = int(input("请输入一个数字:"))
i = 2
while number > i:
if number % i == 0 and i != number:
print(f"您输入的{number}可以被{i}整除,不是质数")
break
i += 1
else:
print(f"您输入的{number}是质数")
循环嵌套
python
# 倒三角
i = 0
while i < 9:
j = i
while j < 9:
print("*"," ",end="")
j += 1
i += 1
print("")
# 正三角
i = 0
while i < 9:
j = 0
while j <= i:
print("*"," ",end="")
j += 1
i += 1
print("")
# 九九乘法表
i = 1
while i <= 9:
j = 1
while j <= i:
print(f"{j} * {i} = ", (i*j), end=" ")
j += 1
i += 1
print("")
break和continue
python
break
跳出距离本次最近的循环
continue
跳出本轮循环
pass
通过,无意义
质数优化
python
from time import *
begin_time = time()
number = 2
while number <= 100:
i = 2
while number ** 0.5 >= i:
if number % i == 0:
# print(f"您输入的{number}可以被{i}整除,不是质数")
break
i += 1
else:
print(f"{number}是质数")
number += 1
end_time = time()
print("时间差:",end_time - begin_time)
八、列表
List列表、切片、步长
python
# 空的声明
my_list = []
print(type(my_list))
# 同类型+直接赋值
my_list = [1, 3, 5, 6, 7, 8, 9]
print(my_list)
# 可以存储不同类型的值,与Java不一致,不过一般还是存储同类型的值
my_list = [1, "str", print, 9.99]
print(my_list)
# len函数计算长度
print(len(my_list))
my_list = [1, 3, 5, 6, 7, 8, 9, 11, 14, 145, 345, 365]
# 获取指定索引的对象
print(my_list[0])
# python的list可以写负数,指的是倒数第一位、第二位
print(my_list[-1])
# 切片可以截取list 包含起始位置的数据,不包含结束位置的数据
print(my_list[0:3])
# 可以省略
# 从3到末尾
print(my_list[3:])
# 从首位到2
print(my_list[:2])
# 步长,切片跳跃数,取第n个
print(my_list[0:5:2])
print(my_list[0::2])
print(my_list[:5:2])
print(my_list[::2])
# 负数的步长表示从后往前数
print(my_list[::-1])
print(my_list[::-2])
List的通用操作 + * in not in len() max() min()
python
# +
list_a = [-1,1, 3, 4, 5, 6, 7, 8]
list_b = [1, 3, 4, 111, 344, 555]
print(list_a + list_b)
# *
print(list_a * 2)
# in
print(1 in list_b)
# not in
print(1 not in list_b)
# len()
print(len(list_b))
# min()
print(min(list_b))
# max()
print(max(list_b))
# 方法需要用对象.index()来调用,函数直接使用传递参数即可
# index() 第二个参数表示查找的起始位置,第三个参数表示的是结束位置
print(list_b.index(555))
print(list_b.index(555, 4, len(list_b)))
print(list_b.index(555, 4))
# 如果没有这个数值,则会抛出异常
# print(list_b.index(666))
# count() 统计参数的出现次数
print(list_b.count(555))
序列 (sequence)
markdown
- 序列是python中最基本的一种数据结构
- 数据结构指计算机中数据存储的方式
- 序列用于保存一组有序的数据,所有的数据在序列当中有一个唯一的位置(索引)
并且序列中的数据会按照添加的顺序来分配索引
- 序列的分类
可变序列(序列中的元素可以改变)
>列表(list)
不可变序列(序列中的元素不可改变)
> 字符串(str)
> 元组(tuple)
修改列表(修改、删除、切片修改、切片步长修改)
python
list_person = ['悟空', '沙僧', '八戒', '唐僧', '白骨精', '黑熊精', '鲶鱼精', '菩提祖师', '佛祖', '玉皇大帝']
# 修改
list_person[1] = '魔改-沙僧'
list_person[4] = '魔改-白骨精'
print(list_person)
# 删除
del list_person[1]
print(list_person)
# 通过切片修改列表,给切片赋值是只能使用序列
list_person[0:3] = ['魔改悟空', '魔改八戒', '魔改唐僧']
print(list_person)
# 通过切片的步长来赋值,也是需要给出对应长度的序列
list_person[0:3] = ['魔改悟空', '魔改八戒', '魔改唐僧']
print(list_person)
print(len(list_person) // 3)
list_person[::3] = ['魔改', '魔改', '魔改']
print(list_person)
# 以上操作只适用于可变序列
# 不可变序列在适用的时候可以使用list函数将其转换为可变序列
print(list('hello'))
列表的方法(append、insert、extend、clear、pop、remove、reverse、sort)
python
# 列表的方法
list_person = ['悟空', '沙僧', '八戒', '唐僧', '白骨精', '黑熊精', '鲶鱼精', '菩提祖师', '佛祖', '玉皇大帝']
# 最后 追加可变序列的数值
list_person.append('王母娘娘')
print(list_person)
# 插入元素 1、插入位置 2、插入元素
list_person.insert(2, '天兵')
print(list_person)
# 把一个可变序列追加到另一个序列
list_extend = ['金毛狮王', '长鼻子象精', '大哥黑鹰精']
list_person.extend(list_extend)
print(list_person)
# 清空序列
list_extend.clear()
print(list_extend)
# 取出并删除元素,需要返回值的场景
del_element = list_person.pop(1)
print(del_element)
print(list_person)
# 删除元素,不要返回值,
# 根据索引删除
del list_person[0]
print(list_person)
# 删除指定值元素
# 根据指定值删除
# 如果有多个只删除一个
list_person.append('王母娘娘')
list_person.remove("王母娘娘")
print(list_person)
number = '390298375925'
list_number = list(number)
print(list_number)
# 反转
list_number.reverse()
print(list_number)
# 排序
list_number.sort()
print(list_number)
# 降序排序
list_number.sort(reverse=True)
print(list_number)
列表的遍历
python
list_person = ['悟空', '沙僧', '八戒', '唐僧', '白骨精', '黑熊精', '鲶鱼精', '菩提祖师', '佛祖', '玉皇大帝']
# 创建循环遍历数值
i = 0
while i < len(list_person):
print(list_person[i])
i += 1
else:
print('遍历完成啦')
print('-' * 10)
# for循环
for element in list_person:
print(element)
可变对象
markdown
- 每个对象中都存储了三个数据
id(标识别)
type(类型)
value(值)
- 列表就是一个可变动向
a = [1, 2, 3]
- a[0] = 10 (改变对象)
- 这个操作是通过变量去修改对象中的值
- 不会改变变量所指向的对象
- 当我们去修改对象时,如果有其他变量也指向了该对象,则修改也会在其他的变量中体现
- a = [4, 5, 6] (该变量)
- 这个操作是在给变量重新赋值
- 这个操作会改变变量所指向的对象
- 为一个变量重新赋值时,不会影响其他的变量
- 一般只有在为变量赋值时才是修改变量,其余的都是修改对象
a = [1, 2, 3]
b = [1, 2, 3]
print(a, id(a))
a[1] = 3
print(a, id(a))
print(b, id(b))
a = [1, 2, 3]
print(a, id(a))
# == != 比较对象的值是否相等
# is is not 比较对象的id是否相等(是否为同一个对象)
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)
print(a is b)
a = b
print(a is b)
b[1] = -1
print(a == b)
九、元组
元组
python
# 元组不是空元组时,括号可以省略
# 如果元组不是空元组,它里面至少需要有一个值
my_tuple = ()
my_tuple_two = 10, 20, 30, 40
my_tuple_three = 100,
print(type(my_tuple))
# 元组的解包(解构)
# 解包指的就是将元组当中每一个元素都赋值给一个变量
a, b, c, d = my_tuple_two
print(a, b, c, d)
a = 100
b = 200
print(a, b)
# 利用元组的解包、解构去替换a和b的值
a, b = b, a
print(a, b)
# 在对元组进行解包、解构时,变量对数量必须和元组中的元素对数量一致
# 也可以在变量前边添加一个*,这样变量将会获取元组中剩余的元素
a, b, *c = my_tuple_two
print(a, b, c)
a, *b, c = my_tuple_two
print(a, b, c)
*a, b, c = my_tuple_two
print(a, b, c)
*a, b, c = 'hello world'
print(a, b, c)
# 注意不能同时出现两个*变量
Range()函数
python
# range() 是一个函数,可以用来生成一个自然数的序列
# 起始位置(省略默认1) 结束位置 步长(省略默认1)
result = range(5)
for element in result:
print(element)
print()
result = range(0, 10, 2)
for element in result:
print(element)
print()
result = range(20, 23, 2)
for element in result:
print(element)
# 可以通过range来创建一个指定循环次数的for循环
# 相比较于while更推荐使用for
for num in range(30):
print(num)
# 我们可以将一个包含双值子序列的序列转换为字典
# 子序列:如果序列中的元素也是序列,那么我们称其为子序列
a = [('name', 'wukong'), ('age', 18)]
b = dict(a)
print(b['name'])
print(len(b))
print('name' in b)
print('name' not in b)
# get方法
print(b.get('name'))
# 通过get获取没有这个参数则返回None
print(b.get('hello'))
# 通过get获取没有这个参数,返回默认值
print(b.get('hello'), '默认值')
# 修改字典 存在则修改 不存在则添加
b['name'] = 'bajie'
b['address'] = '高老庄'
for element in b:
print(b.get(element))
# setdefault(key,value)
# 已经存在则返回key的值,不会对字典做任何操作
# 不存在则添加key-value
# 于saveOrUpdate还是有一些差异的
print('返回值',b.setdefault('hello', '八戒'))
print('返回值',b.setdefault('name', '八戒-修改'))
for element in b:
print(b.get(element))
# update([other)
# d将其他的字典中的key-value添加到当前字典中
# 如果有重复的key,则后边的会替换当前的
a = {'1': 11, '2': 22, '3': 33}
b = {'3': 11, '4': 22, '5': 33}
a.update(b)
for element in a:
print(a.get(element))
# del删除
del b['3']
del b['4']
for element in b:
print(b.get(element))
# popitem随机删除一个key-value ,一般是最后一个
# 使用popitem删除一个空字典会报错
print()
result = a.popitem()
print(result)
result = a.popitem()
print(result)
# pop删除key-value,并返回删除的value
result = a.pop('2')
print(result)
# pop参数如果在字典中没有则报错 如果pop填写了默认值,则不会报错,返回默认值
result = a.pop('2','默认值')
print(result)
# 清空字段数据
a.clear()
print(len(a))
# copy
# 浅拷贝,修改一个不会影响另一个(正好与java相反,java的深拷贝才是这个概念,浅拷贝是只拿引用地址)
a = {'1': 11, '2': 22, '3': 33}
b = a.copy()
print(id(a), id(b))
# 浅拷贝会简单赋值对象内部的值,如果值也是一个可变对象,则值个可变对象不会被复制,只会拿到其id引用
a = {'1': {'name': 'wukong', 'age': 18}, '2': 22, '3': 33}
b = a.copy()
a['1']['name'] = 'bajie'
print(a,b)
# {'1': {'name': 'bajie', 'age': 18}, '2': 22, '3': 33} {'1': {'name': 'bajie', 'age': 18}, '2': 22, '3': 33}
obj = {
'name': '孙悟空',
'age': 18,
'gender': '男',
}
print("keys")
for k in obj.keys():
print(k)
print(obj.get(k))
print()
print(obj.items())
# 返回字典中的所有项,返回一个序列,这个序列包含双值子序列
print("items")
for k,v in obj.items():
print(k)
print(v)
print("values")
for v in obj.values():
print(v)
十、Set集合
python
# 集合 set
# 使用 {} 来创建结合 相当于取字典的key
s = {1, 2, 5, 6, 10, 11, 23, 45}
# 使用set()函数创建空的set集合
s1 = set()
s2 = set([1, 2, 3, 4])
s3 = set('hello')
# set函数的参数为字典时,只获取字典的key值
s4 = set({'a':10, 'b':20, 'c':3})
# 创建集合
# in not in
print(1 in s)
print(1 not in s)
# len获取长度
print(len(s))
print(s, type(s))
# add添加元素
s.add(1111)
s.add(11)
print(s)
# update() 将一个集合中的元素添加到当前集合中
# update() 可以传递序列或者字典,字典只使用键
s = {1, 2, 5, 6, 10, 11, 23, 45}
s2 = {888, 999, 1}
s.update(s2)
print(s)
# pop随机删除并返回一个集合中的元素
result = s.pop()
print(s)
# 删除指定原属
s.remove(888)
print(s)
# clear() 清空集合
print(s.clear())
# copy() 浅拷贝
集合的运算
python
s = {1, 2, 5, 6, 10, 11, 23, 45}
s2 = {1, 5, 555, 666}
# 交集
result_set = s & s2
print(result_set)
# 并集合
result_set = s | s2
print(result_set)
# 差集
result_set = s - s2
print(result_set)
# 异或集 获取只在一个集合中出现的元素
result_set = s ^ s2
print(result_set)
# <= 检查一个集合是否是另一个集合的子集
# a的元素可以在b集合中找到,则视a为b的子集,b集合是a集合的超集(超有点类似于java中的super概念)
s2.remove(555)
s2.remove(666)
result_set = s2 <= s
print(result_set)
# < 检查一个集合是否是另一个集合的真子集
# 如果超级b中含有子集所有元素,并且b中还有a中没有的元素,则b就是a的真超集,a是b的真子集
result_set = s2 < s
print(result_set)
s1 = {1, 2, 3}
s2 = {1, 2, 3}
print(s1 < s2)
print(s1 <= s2)
函数的参数、传递方式
python
# 函数名字可以使用字母、下划线
# 函数定义后面前后希望给出两个空行
def my_sum(a, b):
print(a + b)
# 调用函数,传递实参
my_sum(1, 10)
my_sum(2, 10)
my_sum(3, 10)
my_sum(4, 10)
# 定义形参数时可以指定默认值
# 指定默认值后,如果用户传递了参数则默认值没有任何作用,如果没有传递则默认值会生效
def my_sum(a, b=10):
print(a + b)
print()
my_sum(4)
my_sum(4, 20)
# 实参数的传递方式
# 位置参数,通过位置来赋值,上面的就是位置参数
# 关键字参数
# 通过参数名来传递
print()
my_sum(4)
my_sum(b=50, a=30)
# 位置和关键字可以混合使用,但必须将位置参数写在前面
my_sum(50, b=100)
实参的类型
markdown
# 参数在调用时可以传递任意类型的对象,解析器不会检查实惨的类型 (和java相比属于弱类型语言)
# 123 True 'hello' None [1, 2, 3] {'name':'宇超','age':18} {1, 2, 3}
# 如果形参是变量,则函数内的重新赋值不会影响变量,如果形参是对象,那么在函数内修改会同步修改外面的对象
# 这个概念也是相当于java的引用,传递对象到形参实际就是把对象的id给赋值到变量上面了
# 如果不想出现这个情况,则需要使用copy()函数做浅拷贝、或者对列表进行切片 、再或者深拷贝
不定长参数
python
# 不定长参数
# *a会将所有的位置实参接收并统一保存到一个元组里面tuple,我们称之为装包
def my_sum(*a):
print(a)
def my_sum_two(*a, b, c):
print(a)
print(b)
print(b)
def my_sum_three(a, *b, c):
print(a)
print(b)
print(b)
def my_sum_four(*, a, b, c):
print(a)
print(b)
print(b)
def dict_function(**a):
print('a=', a)
print('a type:', type(a))
def dict_more_function(a, b, **c):
print('a=', a)
print('b=', b)
print('c=', c)
my_sum(100)
# 带*的参数只能有一个,可以配合其他参数使用,一般放最后一个位置
my_sum_two(100, 200, b=300, c=400)
# 当然*也可以不放在最后一位,这样的话*号后面的参数就必须带关键字
my_sum_three(100, 200, 300, c=400)
# 如果要求所有参数必须以关键字进行参数传递,则在开头使用*
my_sum_four(a=100, b=200, c=300)
# 单*号形参仅允许位置参数传递,**支持关键字传递,传递的类型是字典
# 如果是多参数,字典参数一定放到最后一个
dict_function(a=1, b=2, c=3)
dict_obj = {'name':'宇超','age':18}
dict_function(a=1, b=2, c=dict_obj)
print('解包')
def fn4(a, b, c):
print(a)
print(b)
print(c)
# 创建一个元组
t = (10, 20, 30)
fn4(*t)
print('对字典解包')
# 创建一个字典
d = {'a': 10, 'b': 20, 'c': 30}
fn4(**d)
return
markdown
# return可以返回任意对象,甚至于一个函数,内嵌函数,不过这种使用的很少
# 如果只写return,后面没有跟任意变量或者对象,则返回None,一旦执行return则自动结束
# 有点类似于break
文档字符串
python
# 内置函数help,给出帮助文档
# doc str 文档字符串,对函数的说明(相当于java方法的文档注释)
help(print)
def fn1(a: int, b: bool, c: str = 'hello'):
"""
:param a: a
:param b: b
:param c: c
:return: None
"""
print(a)
print(b)
print(c)
help(fn1)
fn1(10, True)
十一、作用域
python
# 作用域表示的是变量的生效区域 (与java一致,局部变量和全局变量)
a = 10
def update():
global a
a = 20
print(a)
# 在函数内部修改全局变量,需要声明global关键字
update()
print(a)
命名空间
python
# 返回的是一个字典 locals() globals()
local_namespace = locals()
print(local_namespace)
local_namespace['a'] = '123'
print(local_namespace['a'])
def fn1():
function_local_scope = locals()
print(function_local_scope)
a = 10
b = 20
function_local_scope = locals()
function_local_scope['c'] = 30
print(function_local_scope)
function_global = globals()
print(function_global)
fn1()
递归
python
def factorial(n):
"""
该函数用来求任意数的阶乘
:param n: 入参
:return: 返回计算阶乘的结果
"""
# 基线条件,判断n是否为1,如果为1则此时不能继续递归
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(10))
def power(n, i):
"""
其实python的幂运算也可以做到, n ** i ,此处主要是为了练习递归
:param n: 数字
:param i: 几次幂
:return: 计算结果
"""
if i == 1:
return n
return n * power(n, i - 1)
print(power(10, 3))
print(10 ** 3)
def hui_wen(s):
"""
算字符串是否为回文,从前往后和从后往前念都是一样的输出视为回文
:param s:检查的字符串
:return: 返回True或者False
"""
if len(s) < 2:
return True
elif s[0] != s[-1]:
return False
return hui_wen(s[1:-1])
print(hui_wen('abccba'))
函数高阶创建
markdown
# 函数是一等对象
# 一定能对象具备一下特点
- 对象在运行时创建
- 能赋值给变量或作为数据结构中的元素
- 能作为参数传递
- 能作为返回值返回
# 高阶函数
接收函数作为参数,或者将函数作为返回值的就是高阶函数
filter()过滤器
python
# filter() 可以从序列中过滤出符合条件的元素,保存到一个新的序列中
# 参数:1、函数。根据函数来过滤序列(可以迭代的结构) 2、需要过滤的序列(可迭代的结构)
def fun1(i):
"""
只要偶数
:param i:
:return:
"""
if i % 2 == 0:
return True
return False
def fun2(i):
"""
只要奇数
:param i:
:return:
"""
if i % 2 != 0:
return True
return False
def fun3(i):
"""
只要3的倍数
:param i:
:return:
"""
if i % 3 == 0:
return True
return False
number_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(filter(fun3,number_list)))\
匿名函数-lambda-语法糖
python
# lambda 函数表达式用来创建一些简单的函数,它是函数创建的又一种方式
# 语法: lambda 参数列表:返回值
def fn5(a, b):
return a + b
print(fn5(5, 10))
print((lambda a, b: a + b)(5, 10))
# filter
number_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(filter((lambda i: i % 3 == 0),number_list)))
# map() 函数可以对可迭代对象中的所有元素做指定参数,然后添加到新的一个对象中返回
result = map(lambda i: i + 1, number_list)
print(list(result))
sort()方法 sorted()函数
python
l = ['aa', 'ddddddddd', 'bbbb', 'ccccc', 'ffffff']
# sort()
l.sort()
print(l)
l.sort(key=len)
print(l)
l = ['1231', '234234', '34535', '12', '6666']
l.sort(key=int)
print(l)
# sorted()
# 与sort用法基本一致,但sorted()可以对任意的序列进行排序,并且sorted不会影响原来的对象,而是返回一个新的对象
new_list = sorted(l)
print(new_list)
new_list = sorted(l,key=int)
print(new_list)
闭包
python
# 形成闭包的条件
# - 函数嵌套
# - 将内部函数作为返回值返回
# - 内部函数必须要使用外部函数的变量
def fn():
a = 10
def inner(b):
return a + b
return inner
inner_fun = fn()
print(inner_fun(20))
# 求多个数的平均数
nums = [34, 45, 56, 67, 78, 2, 62, 78]
print(sum(nums) / len(nums))
nums = []
def averager(n):
# 将n添加到列表中
nums.append(n)
# 求平均值
return sum(nums) / len(nums)
print(averager(10))
print(averager(20))
print(averager(30))
# 如果这里改变nums值,则可能会异常
print(averager(40))
def make_averager():
nums = []
def averager(n):
# 将n添加到列表中
nums.append(n)
# 求平均值
return sum(nums) / len(nums)
return averager
averager_function = make_averager()
print(averager_function(10))
print(averager_function(20))
print(averager_function(30))
装饰器
python
# 装饰器
"""
函数开始前和开始后分别打印一条语句,或者计算函数运行时间
可以直接通过修改代码来实现这个需求,但是会违反开闭原则OCP(对扩展开放,对修改关闭)
"""
def fun1(a, b):
print("正常函数")
return a + b
def fun_decorate(a,b):
print("程序开始了")
r = fun1(a,b)
print("程序结束了")
return r
print(fun_decorate(10,20))
# 每次都得定义一个新的函数,太麻烦!
def begin_end(fun):
def new_function(a,b):
print("程序开始了")
result = fun(a,b)
print("程序结束了")
return result
return new_function
new_function = begin_end(fun1)
print(new_function(40,50))
# 参数固定,不通用!
def begin_end(fun):
def new_function(*args, **kwargs):
print("程序开始了")
result = fun(*args, **kwargs)
print("程序结束了")
return result
return new_function
def begin_end_two(fun):
def new_function(*args, **kwargs):
print("two程序开始了")
result = fun(*args, **kwargs)
print("two程序结束了")
return result
return new_function
new_function = begin_end(fun1)
print(new_function(40,50))
print()
# 通过装饰器可以来扩展函数功能 使用@装饰器名字来使用(有点java面向切面开发的感觉了 )
# 可以同时为一个函数指定多个装饰器,这样函数将先内后外去装饰
@begin_end
@begin_end_two
def say_hello():
print("大家好~~~")
say_hello()
类
python
# 命名规范
# 下划线命名法。所有单词小写,单词之间以下划线分割(常用于日常编程)
# 帕斯卡命名法(大驼峰命名法)。首字母大写、每个单词首字母大写其余命名小写(常用于类名)
class MyClass():
pass
temp = MyClass()
print(temp)
print(type(temp))
# 都是MyClass的实例
temp = MyClass()
temp1 = MyClass()
temp2 = MyClass()
temp3 = MyClass()
# 使用isinstance来判断temp是否是类的实例
print(isinstance(temp, MyClass));
# 类的type为type
print(id(MyClass) , type(MyClass))
temp.name = '孙悟空'
temp1.name = '猪八戒'
print(temp.name)
print(temp1.name)
类的定义
markdown
- 类和对象的内容其实都是对现实生活中的十位或者程序中的内容做了抽象
- 两部分组成
> 数据(属性)
> 行为(方法)
- 类的代码块中,我们可以定义变量和函数
变量会成为公共的实例属性,所有该类的实例都可以通过 对象.属性名 的形式访问
函数同上
- 注意:
方法调用时,第一个参数由解析器自动调用,所以方法一定要定义一个形参数
python
class Person():
name = 'name'
age = 18
def say_hello(self):
print('你好')
person = Person()
person.say_hello()
属性和方法
python
# self指的是实例,方法是看不到类的属性的,需要由实例去传递
class Person():
name = 'name'
age = 18
def say_hello(self):
print('你好',self.name)
person = Person()
person.name = '沙僧'
person_two = Person()
# person_two.name = '八戒'
person.say_hello()
person_two.say_hello()
# 属性和方法的查找流程
# > 调用一个对象时,解析器首先会在对象中去找是否含有这个属性
# > 如果有则返回当前对象的属性值
# > 如果没有,则去对象的类对象中去寻找,如果有则返回类对象中的属性值
# > 如果类对象中也没有这个属性值则报错
# 类对象和实例对象中都可以保存属性(方法)
# > 如果这个属性(方法)是所有实例共享的,则应该放到保存的类对象中
# > 如果这个属性(方法)是某个实例独有,则应该保存到实例对象中
# 一般情况下,属性保存到实例对象中
# >方法保存到类对象中
对象初始化
python
# 可以在类中定义一些特殊方法(魔术方法)
# 特殊方法都是以 __开头,__结尾(双下划线)
# 特殊方法不需要我们自己调用,不要尝试去调用特殊方法
# 特殊方法将会在特殊的时刻自动调用
class Person:
def __init__(self, name, age):
print(self)
self.name = name
self.age = age
def say_hello(self):
print("大家好,我是%s,年龄%s"%(self.name,self.age))
p1 = Person('宇超',18)
p1.say_hello()
创建对象的流程
markdown
# 创建对象的流程
> 创建一个变量
> 在内存中创建一个新对象
> __init__(self)方法执行
> 将对象的id赋值给变量
类属性的安全性
python
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print(f"小狗%s今年%s岁了,正在奔跑" % (self.name, self.age))
dog1 = Dog('嘟嘟',2)
dog1.run()
dog1.name = '黑豹'
dog1.age = '6'
dog1.run()
# 目前可以通过对象.属性来修改属性的值,导致对象中的属性被随意更改,非常不安全。
# 可以通过封装的方式来增强数据安全
封装
python
# 使用封装虽然确实增加了类的定义和复杂程度,但是它也保证了数据的安全性
# 1.隐藏属性名,使调用者无法轻易修改对象中的属性
# 2.增加爱了set、get方法可以有效控制属性是否为只读
# 3.set方法可以增加数据有效性校验,保证数据的准确性
# 4.使用getter方法获取属性,使用setter方法设置属性,可以在修改属性的同时做一些其他事情,比如日志记录
class Dog:
def __init__(self, name, age):
self._name = name
self._age = age
def get_name(self):
return self._name
def set_name(self, name):
self._name = name
def get_age(self):
return self._age
def set_age(self, age):
if age < 1:
print("年龄不合法!")
else:
self._age = age
def run(self):
print(f"小狗%s今年%s岁了,正在奔跑" % (self._name, self._age))
dog1 = Dog('嘟嘟', 2)
dog1.run()
dog1.name = '黑豹'
dog1.age = -6
dog1.run()
# 目前可以通过对象.属性来修改属性的值,导致对象中的属性被随意更改,非常不安全。
# 可以通过封装的方式来增强数据安全
装饰器property
python
# 通过 @property 和 @属性名.setter 可以使方法可以想像属性一样去使用
# 且方法名字不需要再加get_或者set_
# 需要注意,使用property装饰的化,方法名字必须和属性名字一样(这里的下划线名字等同于不加下划线,下划线的意思是隐藏属性)
class Dog:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = age
def run(self):
print(f"小狗%s今年%s岁了,正在奔跑" % (self._name, self._age))
dog1 = Dog('嘟嘟', 2)
dog1.run()
dog1.name = '黑豹'
dog1.age = 4
dog1.run()
继承
python
# 继承可以直接让子类继承父类的方法或者属性,避免编写重复性的代码,并且也符合OCP原则
# 所以我们经常需要通过继承一个类进行扩展
class Animal:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
def say_hello(self):
print("你好呀!%s" % self._name)
class Dog(Animal):
def __init__(self, name, age):
super().__init__(name)
self._age = age
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def run(self):
print("%s岁的小狗%s在奔跑"%(self._age,self._name))
dog = Dog('黑豹',18)
dog.say_hello()
dog.run()
dog.name = '嘟嘟'
dog.age = 4
dog.run()
# 实例
print(isinstance(dog, Animal))
# 子类
print(issubclass(Dog, Animal))
# object子类
print(issubclass(Dog, object))
继承后的方法优先级
markdown
1. 优先调用当前对象
2. 没有则调用父类对象
3. 父类对象也没有的话,以此类推继续往上找,直到找到object,如果object还没有,则报错
支持多继承
python
class C(A,B):
pass
# 不建议使用多继承,因为多继承会让我们的代码过于复杂
多态
python
# 系统函数其实都以object参数的形式实现了多态,所以函数的入参才可以通用
# 比如
len()
print()
面向对象的三大特征:
python
封装:确保对象中的数据安全
继承:保证对象的可扩展性
多态:保证程序的灵活性
类的属性和方法
python
# 类的属性和方法
class A(object):
# 在类中直接定义的属性是类属性,类属性可以通过类以及实例访问到
# 但是类属性只能通过类对象来修改,无法通过实例对象来修改
count = 0
def __init__(self):
# 通过实例对象添加的属性属于实例属性
# 实例属性只能通过实例对象的访问和修改,类对象无法访问和修改
self._name = '孙悟空'
# 在类中定义,以self为第一个参数的方法都是实例方法
# 调用实例方法时,python会将调用对象最为self传入
def test(self):
print('这里是test方法,实例方法')
# 通过 @classmethod 修饰的方法为类方法
# 类方法的第一个参数cls,也会被自动传递,cls就是当前的类对象
# 类方法和实例方法的区别是第一个参数self 和 cls
# 类方法可以通过类去调用,也可以通过实例去调用,没有区别
@classmethod
def test2(cls):
print('这里是test2方法,类方法')
print(cls.count)
print(cls)
# 在类中使用 @staticmethod 来修饰但方法属于静态方法,可以被类以及实例对象调用
# 可以理解为和当前类无关但方法,只是保存在当前类但一个函数
@staticmethod
def test3():
print('这里是test3,静态方法')
a = A()
print(A.count)
a.count = 10
print(a.count)
print(A.count)
A.count = 100
print(a.count)
print(A.count)
# 实例方法可以用类调用,但需要传入实例对象
A.test(a)
# 类方法可以直接调用,不需要实例参数
A.test2()
a.test3()
A.test3()
垃圾回收
python
# 在python中有自动的垃圾回收机制,他会自动将这些没有引用的对象删除,不需要我们手动删除
class A:
def __init__(self):
self._name = 'A类'
@property
def name(self):
return self._name
def __del__(self):
print("A()对象被删除了~~`", self)
a = A()
print(a.name)
b = a
print(a.name)
# 其实这里的a和b都是存储了A()实例的id地址,他们两个置为None后不存在引用了,则对象被回收
# b = None
# a = None
# 当然如果要手动删除的话,使用del关键字是一样的
del a
del b
input("输入回车退出程序")
特殊方法 str repr gt lt ge le eq bool add sub
python
class Animal:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
# print输出的效果
def __str__(self):
return 'Animal [name=%s , age=%s]' % (self._name, self._age)
# (指定对象在交互模式中输出的结果)
def __repr__(self):
return 'animal'
def __gt__(self, other):
return self._age > other._age
def __ge__(self, other):
return self._age >= other._age
def __eq__(self, other):
return self._age == other._age
def __lt__(self, other):
return self._age < other._age
def __le__(self, other):
return self._age < other._age
def __bool__(self):
if self._age > 19:
return True
return False
a = Animal('大象', 18)
b = Animal('大象', 20)
print(a)
print(repr(a))
print(a > b)
print(a >= b)
print(b > a)
print(a < b)
print(a <= b)
print(a == b)
print(bool(a))
print(bool(b))
模块
markdown
# 将一个程序拆分成一个一个小的模块,通过模块组合,来搭建一个程序
- 优点:
1. 方便开发
2. 方便维护
3. 模块可以复用
# 一个.py文件就是一个模块
模块的创建A
python
import TestModule
print(TestModule)
TestModule.say_hello()
模块的创建B
python
import TestModule as test
print(test)
test.say_hello()
print('模块的名字,原始名字:', test.__name__)
# __main__
print('当前模块的名字:', __name__)
# __main__ 是主模块,一个模块只有一个主模块
模块的使用1 导入模块并作别名
python
import PersonInit as person
p = person.Person('宇超', 18)
p.say_hello()
# import其实也可以直接引用函数、类、变量
from PersonInit import Person
p = Person('宇超', 18)
p.say_hello()
模块的使用2 单独导入类、函数、属性
python
from PersonInit import test1,test2,count,Person
p = Person('宇超', 18)
p.say_hello()
test1()
test2()
print(count)
模块的使用3 *
python
# 不建议使用* ,相当于把代码全部拷贝过来,存在冗余
from PersonInit import *
p = Person('宇超', 18)
p.say_hello()
test1()
test2()
print(count)
模块的使用4 导入的变量、函数作别名
python
from PersonInit import test1,test2 as test3,count,Person
p = Person('宇超', 18)
p.say_hello()
test1()
def test2():
print("这是我自己的的test2")
test2()
test3()
print(count)
模块的使用4 私有属性、测试方法
python
# 模块中以 _开头的变量是不会被 from 模块 import * 去导入的,除非 import 模块
_age = 18
def test1():
print("我是test1")
def test2():
print("我是test2")
# 测试代码不想要被其他模块引入,则增加判断即可避免
if __name__ == '__main__':
test1()
test2()
包
python
# 包其实可以理解为文件夹
# 包中必须要有 __init__.py文件,可以用来放主程序的内容
# 导包
import 包名字
from 包名字 import 模块名字
# __pycache__ 是模块的缓存文件
# python在执行前,需要被解析器转换为机器码,然后再执行
# 我们在使用模块(包)时,也需要将模块的代码先转为机器码然后再交给计算机执行
# 为了提高程序运行的性能,python会在编译一次后,将代码保存到一个缓存文件中
# 这样下次加载这个模块(包)时,就可以不再重新编译而是直接加载缓存中编译好的代码(类似于java的.class)
from PackageTest.B import say_hello
from PackageTest import A
say_hello()
A.say_hello()
sys、os标准库
python
import sys
import pprint
import os
# 获取执行代码时命令行包含的参数,该属性是个列表
print(sys.argv)
# 美化输出当前程序引用的所有模块,这是个字典
pprint.pprint(sys.modules)
# 退出程序
# sys.exit()
# 退出程序并给出提示
# sys.exit("程序异常,退出!")
# 运行python的平台
print(sys.platform)
# 环境变量
pprint.pprint(os.environ)
# 字典
pprint.pprint(os.environ['JMETER_HOME'])
# 操作系统命令
result = os.system('ls -l')
print(result)
异常
python
print('hello')
try:
# try存放业务,可能出现异常
# print(10/0)
print(10 / 1)
except:
print("捕获异常!")
else:
print("程序正常执行")
print('你好')
异常2
python
print("出现异常前")
l = []
try:
print(c)
except NameError:
print("出现 NameError")
except ZeroDivisionError:
print('出现 ZeroDivisionErrorL')
except IndexError:
print('出现 IndexError')
except Exception:
print('出现 Exception')
else:
print('正常结束程序')
finally:
print('一定会执行的部分')
print("程序结束")
抛出异常
python
class MyException(Exception):
pass
def add(a, b):
if a < 0 or b < 0:
raise MyException('自定义异常')
r = a + b
return r
add(10, -1)
print(add(10, 21))
打开文件
python
# 绝对路径
file_path = '/Users/jiayuchao/Desktop/temp.txt'
# 可以使用\\来对\做转意,也可以用字符串前加r的方式输出原始字符串
# file_path = r'/Users/jiayuchao/Desktop/temp.txt'
# 使用 ./ ../来切换目录
file_test_path = './test.txt'
# open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
file_obj = open(file_path)
print(file_obj)
test_obj = open(file_test_path)
print(test_obj)
关闭文件
python
# 绝对路径
file_path = '/Users/jiayuchao/Desktop/temp.txt'
# 可以使用\\来对\做转意,也可以用字符串前加r的方式输出原始字符串
# file_path = r'/Users/jiayuchao/Desktop/temp.txt'
# 使用 ./ ../来切换目录
file_test_path = './test.txt'
# open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
file_obj = open(file_path)
print(file_obj)
file_obj.close()
# 被关闭,此时无法使用,会抛异常 SyntaxError: encoding problem: None
# print(file_obj)
try:
with open(file_test_path) as test_obj:
print(test_obj.read())
except FileNotFoundError:
print("文件没有找到")
else:
print("程序正常结束")
print(test_obj.read())
打开文件,指定编码
python
try:
with open(file_test_path, encoding='gbk') as test_obj:
print(test_obj.read())
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
读取大文件
python
file_test_path = '/Users/jiayuchao/Downloads/苏研接口.postman_collection.json'
try:
with open(file_test_path, encoding='utf-8') as test_obj:
file_content = ''
chunk = 100
while True:
content = test_obj.read(chunk)
if not content:
# 内容读取完毕,退出for循环
break
file_content += content
print(file_content)
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
读取一行、所有行 readline readlines
python
file_test_path = '/Users/jiayuchao/Downloads/苏研接口.postman_collection.json'
try:
with open(file_test_path, encoding='utf-8') as test_obj:
# print(test_obj.readline())
# print(test_obj.readline())
# print(test_obj.readline())
# 返回一个列表
all_lines_list = test_obj.readlines()
print(all_lines_list[0],all_lines_list[1],all_lines_list[2],all_lines_list[3])
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
针对文件的操作权限
python
file_test_path = './test.txt'
# 不指定操作类型默认为
# r只读 不存在则报错
# w 表示可写,使用w来写入文件时,不存在则会创建文件,如果存在则会截断(清空数据)文件
# a 表示追加,不存在则创建,存在则追加末尾
# r+ 读写权限,文件不存在则报错
# w+ 读写权限,去a+区别时会截断(清空)数据
# a+ 读写权限,不存在则创建,存在则追加末尾
try:
with open(file_test_path,'a', encoding='utf-8') as test_obj:
test_obj.write("123123")
test_obj.write("123123214314")
test_obj.write("1231232143142353252")
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
针对二进制文件做读写
python
file_test_path = '/Users/jiayuchao/Downloads/代码分支管理-贾宇超20240801.pptx'
dest_path = './代码分支管理-贾宇超20240801.pptx'
try:
with open(file_test_path, 'rb') as test_obj:
chunk = 1024 * 100
with open(dest_path, 'wb') as dest_obj:
while True:
content = test_obj.read(chunk)
print(test_obj.tell())
if not content:
# 内容读取完毕,退出for循环
break
dest_obj.write(content)
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
tell seek
python
file_test_path = '/Users/jiayuchao/Downloads/vms_data_clean_mupan-20240221-v1.sh'
try:
# seek的非默认参数好像必须自定二进制读取才可以,不然会丢数据抛异常,估计和我中文有关系?
with open(file_test_path, 'rb') as test_obj:
# 跳跃至从0开始数的第50个位置
test_obj.seek(50)
# test_obj.seek(80,0)
# 跳跃至从当前位置开始的第100个位置
# test_obj.seek(100,1)
# 跳跃至从结尾往前数100个位置
# test_obj.seek(-100,2)
print(test_obj.read())
# 读取的当前位置
print(test_obj.tell())
except FileNotFoundError:
print("文件没有找到")
except UnicodeDecodeError:
print("编码错误")
else:
print("程序正常结束")
Listdir() cwd() remove() rename() chdir()
python
import os
from pprint import pprint
# 目录列表
pprint(os.listdir())
# 当前目录
pprint(os.getcwd())
# 改变目录
os.chdir('..')
pprint(os.getcwd())
pprint(os.listdir())
# os.rmdir("tmp")
# open('aa.txt','w')
# 可以对文件做重命名,也可以移动位置
# os.rename('aa.txt','bb.txt')
os.rename('aa.txt','../bb.txt')
# os.remove('bb.txt')