赞
踩
conda env list
conda create -n 虚拟环境名 python==其版本
conda activate 虚拟环境名
pip install 安装内容
pip list
或conda list
conda deactivate
conda env remove --name 虚拟环境名
单行注释
#
开头,#
右边的所有东西都被当作说明文字#
后要添加一个空格多行注释
一对 连续的 三个 引号
"""
这是一个多行注释
在多行注释之间,可以写很多内容
"""
print("Hello Python")
在Python中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 才会被创建
等号(=
)用来给变量赋值
=
左边是一个变量名
=
右边是存储在变量中的值
# 定义qq_number的变量用来保存 qq号码
qq_number = "1234567"
# 输出 qq_number中保存的内容
print(qq_number)
# 定义苹果价格变量
price = 8.5
# 定义购买重量
weight = 7.5
# 计算金额
money = price * weight*
# 只要买苹果就返 5 元
money = money - 5
# 输出价格
print(money)
变量名 只有在第一次出现 才是 定义变量
变量名 再次出现,不是定义变量,而是直接使用之前定义过的变量
int
)flaot
)bool
)
True
非 0 数
--非零即真False
0
complex
)
type
函数**可以查看一个变量的类型In [1]: type(name)
Out [1]: str
在Python
中定义变量时需要指定数据类型吗?
Python
可以根据=
等号右侧的值,自动推导出变量中存储的数据类型变量是没有类型的,但他存储的数据是有类型的
函数 | 说明 |
---|---|
int(x) | 将 x 转换为一个整数 |
float(x) | 将 x 转换到一个浮点数 |
str(x) | 将 x 转换到一个字符串 |
- **想要将字符串转换成数字,必须要求字符串内的内容都是数**
运算符 | 描述 |
---|---|
== | 检查两个操作数的值是否 相等,如果是,则条件成立,返回True |
!= | 检查两个操作数的值是否 不相等,如果是,则条件成立,返回True |
> | 检测左操作数的值是否 大于 右操作数的值,如果是,则条件成立,返回True |
< | 检测左操作数的值是否 小于 右操作数的值,如果是,则条件成立,返回True |
>= | 检测左操作数的值是否 大于等于 右操作数的值,如果是,则条件成立,返回True |
<= | 检测左操作数的值是否 小于等于 右操作数的值,如果是,则条件成立,返回True |
// 取整除
**指数
条件1 and 条件2
True
False
条件1 or 条件2
True
False
not 条件
True
=
可以给变量赋值Python
还提供了一系列的 与 算数运算符 对应的 赋值运算符运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符 | c = a + b 将 a + b 的运算符结果赋值为 c |
+= | 加法赋值运算符 | i += 1 等价于 i = i + 1 |
-= | 减法赋值运算符 | |
*= | 乘法赋值运算符 | |
/= | 除法赋值运算符 | |
//= | 取整除赋值运算符 | |
%= | 取模(余数)赋值运算符 | |
**= | 幂赋值运算符 |
name="king"
print("我是"+name+"很菜")
格式化字符 | 含义 |
---|---|
%s | 字符串 |
%d | 有符号十进制整数,%06d 表示输出的整数显示位数,不足的地方使用 0 补全 |
%f | 浮点数,%.2f 表示小数点后只显示两位 |
%% | 输出% |
name = "小明"
print("我的名字叫 %s ,请多多关照!" % name)
# output:我的名字叫小明,请多多关照!
#字符串与数字拼接
class_num=57
avg_salary=16781 # 此数数字变成了字符串进行拼接
message = "python大数据学科,北京%s期,毕业平均工资:%s"%(class_num,avg_salary)
#output:python大数据学科,北京57期,毕业平均工资:16781
语法:f”内容{变量}”的格式来快速格式化
特点:不做精度控制,原样输出
p
print(f"我是{name}我成立于:{set_up_year}我今天的股票价格是:{stock_price}")
辅助符号控制数据的宽度和精度
例子
price = 9.00
weight = 5.00
money = price * weight
print("苹果单价 %.2f元/斤, 购买了%.3f斤, 需要支付%.4f元" % (price, weight, money))
#output 苹果单价 9.00元/斤, 购买了5.000斤, 需要支付45.0000元
print("1*1的结果是:%d"%(1*1))
print("字符串在Python中的类型名是:%s"% type("字符串"))
#output:1*1的结果是:1
#字符串在Python中的类型名是:<class 'str'>
name="传智播客"
stock_price=19.99
stock_code="003032"
stock_price_daily_growth_factor =1.2
growth_days=7
finally_stock_price=stock_price*stock_price_daily_growth_factor**growth_days
print(f"公司:{name},股票代码:{stock_code},当前股价:{stock_price}")
print("每日增长系数:%.1f,经过%d天的增长后,股价达到了:%.2f"%(stock_price_daily_growth_factor,growth_days,finally_stock_price ))
#output:公司:传智播客,股票代码:003032,当前股价:19.99
#每日增长系数:1.2,经过7天的增长后,股价达到了:71.63
print ("请告诉我你是谁")
name=input()#等价于input(请告诉我你是谁)
print("我知道你是%s"% name)
input:king
output:我知道你是king
import random
num = radom.randint(a, b) #返回 [a, b] 之间的整数,包含 a 和 b
if 要判断的条件:
条件成立时,要做的事情 # 要有4个空格做缩进
...
# 如果没有缩进 就不属于if的控制范围
Tab
键,或者 4个空格–建议使用空格if
语句以及缩进部分可以看成是一个完整的代码块age=int(input("请输入你的年龄:"))
if age>=18:
print("您已成年,游玩要补票10元。")
print("祝您游玩愉快"
"""
output:请输入你的年龄:18
您已成年,游玩要补票10元。
祝您游玩愉快
"""
if 要判断的条件:
条件成立时,要做的事情
...
else:
条件不成立时,要做的事情
...
if 条件1:
条件1满足执行的代码
...
elif 条件2:
条件2满足执行的代码
...
elif 条件3:
条件3满足执行的代码
...
else:
以上条件都不满足时,执行代码
...
elif
和 else
都必须和 if
联合使用,而不能单独使用if
, elif
和 else
以及各自缩进的diamagnetic,看成一个完整的代码块if 条件1:
条件1满足执行的代码
...
if 条件1基础上的条件2:
条件2满足时,执行的代码
...
# 条件2不满足的处理
else:
条件2不满足时,执行的代码
# 条件1不满足的处理
else:
条件1不满足时,执行的代码
has_ticket = True
knife_length = 15
if has_ticket:
print("车票检查通过,准备开始安检")
if knife_length <= 20:
print("安检通过,祝您旅途愉快")
else:
print("携带道具长度为 %d厘米" % knife_length)
print("不允许上车")
else:
print("请先买票!")
# 导入随机工具包 import random player = int(input("请输入您出的拳 石头(1)/剪刀(2)/布(3): ")) computer = random.randint(1, 3) print("玩家出的拳头是 %d - 电脑出的拳是 %d" % (player, computer)) # 玩家胜利的三种情况 if ((player == 1 and computer == 2) or (player == 2 and computer == 3) or (player == 3 and computer == 1)): print("玩家赢了!") # 平局 elif player == computer: print("平居") # 电脑获胜 else: print("电脑获胜!")
初始条件设置 - 通常是重复执行的 计数器
while 条件(判断 计数器 是否达到 目标次数):
条件满足时,做的事情1
条件满足时,做的事情2
...(省略)...
处理条件(计数器 + 1)
计算 0!100 之间所有数字的累计求和结果
# 0. 定义最终结果的变量
result = 0
# 1. 定义一个整数的变量记录循环的次数
i = 0
# 2. 开始循环
while i <= 100:
print(i)
# 每一次循环,都让 result 这个变量和 i 这个计数器相加
result += i
i += 1
print("0~100 之间的数字求和结果 = %d" % result)
while 条件1:
条件满足时,做的事情1
条件满足时,做的事情2
...(省略)...
while 条件2:
条件满足时,做的事情1
条件满足时,做的事情2
...(省略)...
处理条件2
处理条件1
补充:
i=1 while i<10: j=1 while j<=i: print(f"{j}*{i} = {j*i}\t",end=' ') j+=1 print('') i+=1 #output: 1*1 = 1 1*2 = 2 2*2 = 4 1*3 = 3 2*3 = 6 3*3 = 9 1*4 = 4 2*4 = 8 3*4 = 12 4*4 = 16 1*5 = 5 2*5 = 10 3*5 = 15 4*5 = 20 5*5 = 25 1*6 = 6 2*6 = 12 3*6 = 18 4*6 = 24 5*6 = 30 6*6 = 36 1*7 = 7 2*7 = 14 3*7 = 21 4*7 = 28 5*7 = 35 6*7 = 42 7*7 = 49 1*8 = 8 2*8 = 16 3*8 = 24 4*8 = 32 5*8 = 40 6*8 = 48 7*8 = 56 8*8 = 64 1*9 = 9 2*9 = 18 3*9 = 27 4*9 = 36 5*9 = 45 6*9 = 54 7*9 = 63 8*9 = 72 9*9 = 81
for 临时变量in待处理数据集:
循环满足条件时执行的代码
#例
name="king"
for i in name:
print(i)
range(num)
:获取一个从0开始,到num结束的数字序列(不含数字本身)
range(num1,num2)
:获得一个从num1开始到num2结束的数字序列(不含num2本身)
range(num1,num2,step)
:是从num1到num2(不包括num2)获取数字序列,步长以step为准(step默认为一)
for 临时变量in待处理数据集:
循环满足条件时执行的代码
for 临时变量in待处理数据集:
循环满足条件时执行的代码
### 5.break 和 continue ```py i = 0 while i < 10: # break 某一条件满足时,退出循环,不再执行后续重复的代码 # i == 3 if i == 3: break print(i) i += 1 print("over") #output: 0 1 2 over
i = 0 # 输出 0~10 不包括3 while i < 10: # - `continue` 某一条件满足时,不执行后续重复的代码 # i == 3 if i == 3: # 注意:在循环中,如果使用 continue 这个关键字 # 在使用关键字之前,需要确认循环的计数是否修改, # 否则可能会导致死循环 i += 1 continue print(i) i += 1 print("over") #output: 0 1 2 4 5 6 7 8 9 over
money=10000
for i in range(1,21):
import random
num = random.randint(1, 10)
print(f"员工的绩效为{num}")
if num<5:
print(f"员工{i}绩效分{num}不满足,不发工资,下一位")
continue
if money>=1000:
money-=1000
print(f"员工{i}绩效分满足发放工资1000,公司账户余额:{money}")
else:
print(f"余额不足,当前余额{money}元,不发了,下个月再来")
break
def 函数名():
函数封装的代码
...
def
是英文 define
的缩写函数名()
例:
name = "小明"
# Python 解释器知道下方定义了一个函数
def say_hello():
print("hello 1")
print("hello 2")
print("hello 3")
print(name)
# 只有在程序中,主动调用函数,才会让函数执行
say_hello()
print(name)
,
分隔例:
def sum_2_num(num1, num2):
"""对两个数字求和"""
return num1 + num2
# 调用函数,并使用 result 变量接受计算结果
result = sum_2_num(10, 20)
print("计算结果是 %d" % result)
return
关键字可以返回结果注意:
return
表示返回,后续代码都不会被执行
就是多行注释
def check(a):
"""
可用于解释函数作用
:param a: 解释参数意义
:return: 解释返回值意义
"""
调用函数的时候在pycharm中鼠标悬停可以查看函数的说明文档
test1
函数时,会把函数 test1
中的任务都执行完test2
中调用函数 test1
的位置,继续执行后续的代码def test1(): print("*" * 50) print("test 1") print("*" * 50) def test2(): print("-" * 50) print("test 2") test1() print("-" * 50) test2() #output: -------------------------------------------------- test 2 ************************************************** test 1 ************************************************** --------------------------------------------------
money=5000000 name=None name=input("请输入您的姓名:") def query(show_header): if show_header: print("---------查询余额---------") print(f"{name},您好,您的余额剩余:{money}元") def saving(num): global money #将money在函数内部定义为全局变量 money+=num print("---------存款---------") print(f"{name},您好,您存款:{num}元成功") query(False) def get_money(num): global money # 将money在函数内部定义为全局变量 money -= num print("---------取款---------") print(f"{name},您好,您取款:{num}元成功") query(False) def main(): print("---------主菜单---------") print(f"{name},您好欢迎来到atm,请输入您想操作的步骤") print("查询余额\t\t[输入1]") print("存款\t\t[输入2]") print("取款\t\t[输入3]") print("退出\t\t[输入4]") choice=input("请输入你的选择:") return choice while True: key=main() if key=="1": query(True) continue elif key=="2": num=int(input("您想要存入多少钱:")) saving(num) continue elif key=="3": num = int(input("您想要取出多少钱:")) get_money(num) continue else : print("程序退出") break
列表用 []
定义,数据之间使用 ,
分隔
name_list = ["zhangsan", "lisi", "wangwu"]
利用type()
得其数据类型为list
嵌套列表
mylist = [[1,2,3],[4,5,6]]
列表的索引从0开始
也可通过反向下标索引
最后一个元素的下标是-1
my_list=[[1,2,3],[4,5,6]]
# 3就是my_list[0][2]
嵌套的下标索引
输入第一个元素
my_list=[1,2,3,4]
print(my_list[0])
序号 | 分类 | 关键字/函数/方法 | 说明 |
---|---|---|---|
1 | 增加 | list.insert(索引,数据) | 在指定位置插入数据 |
list.append(数据) | 在末尾追加数据 | ||
list.extend(列表2) | 将列表2 的数据追加到列表 | ||
2 | 修改 | list[索引] = 数据 | 修改指定索引的数据 |
3 | 删除 | del list[索引] | 删除指定索引的数据 |
list.remove[数据] | 删除第一个出现的指定数据 | ||
list.pop() | 删除末尾数据 | ||
list.pop(索引) | 删除指定索引数据 | ||
list.clear() | 清空列表 | ||
4 | 统计 | len(list) | 列表长度 |
list.count(数据) | 数据在列表中出现的次数 | ||
5 | 排序 | list.sort() | 升序排序 |
list.sort(reverse=True) | 降序排序 | ||
list.reverse() | 逆序、反转 | ||
6 | 查询 | list.index() | 查找指定元素的下标 |
del
关键字(delete
) 同样可以删除列表中元素del
关键字本质上是用来 将一个变量从内存中删除的del
关键字将变量从内存中删除出,后续代码就不能再使用这个变量了Python
中为了提高列表的遍历效率,专门提供的 迭代 iteration 遍历for
实现迭代遍历name_list = ["小李广-花荣", "呼保义-宋江", "玉麒麟-卢俊义", "黑旋风-李逵"]
# 使用迭代遍历列表
"""
顺序从列表中依次获取数据,每一次循环过程中,数据都会保存在my_name 这个变量中,
在循环体内部可以访问当前这一次获取到的数据
"""
for my_name in name_list:
print("我的名字是 %s" % my_name)
index=0
while index<len(mylist):
print(```)
index+=1
Python
开发中,有特定的应用场景,
分隔**()**
定义info_tuple = ("zhangsan", 18, 1.75)
tuple = () # 也可是t0=tuple()
single_tuple = ("zhangsan",)
info_tuple = ("zhangsan", 18, 1.75)
# 1. 取值和取索引
print(info_tuple[0])
# 已知数据的内容,想得到该数据在元组中的索引
print(info_tuple.index("zhangsan"))
# 2. 统计计数
print(info_tuple.count("zhangsan"))
# 统计元组中包含元素的个数
print(len(info_tuple))
info_tuple = ("宋江", "及时雨", "天魁星")
# 使用迭代遍历元组
for my_info in info_tuple:
# 使用格式化字符串拼接 my_info 这个变量不方便!
# 因为元组中通常保存的数据类型是不同的!
print(my_info)
index=0
t8=(1,2,3,4)
while index<len(t8):
print(```)
index+=1
字符串就是一串字符,是变成语言中表示文本的数据类型
在 Python 中可以使用
一对双引号" "或者一对单引号’ '定义一个字符串
"
,可以使用单引号 ''
定义字符串'
,可以使用双引号 "
定义字符串方法 | 说明 |
---|---|
isspace() | 如果只包含空格(空白字符),则返回 True |
isalnum() | 如果至少有一个字符并且所有字符都是字母或数字则返回 True |
isalpha() | 如果至少有一个字符并且所有字符都是字母则返回 True |
isdecimal() | 如果只包含数字则返回 True,全角数字 |
isdigit() | 如果只包含数字则返回 True,全角数字,(1),\u00b2 |
isnumeric() | 如果只包含数字则返回 True, 全角数字,汉字数字 |
istitle() | 如果是标题化的(每个单词的首字母大写)则返回 True |
islower() | 如果包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True |
isupper() | 同上,大写返回 True |
方法 | 说明 |
---|---|
startswith(str) | 检查字符串是否是以 str 开头,是则返回 True |
endswith(str) | 同上,结尾 |
string.find(str,start=0,end=len(string)) | 检查 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,负责返回 -1 |
string.rfind(str,start=0,end=len(string)) | 类似上,从右边开始查找 |
string.index(str,start=0,end=len(string)) | 和 find() 类似,只不过如果 str 不在会报错 |
rindex() | 同上,从右边开始 |
string.replace(old_str, new_str, num=string.count(old) | 把 string 中的 old_str 替换成 new_str,如果 num 指定,则替换不超过 num 次 注:不是修改字符串本身,而是得到一个新的字符串 |
string.count("统计内容") | 统计字符串内某字符串出现次数 |
** ** | 统计字符串长度 |
方法 | 说明 |
---|---|
string.capitalize() | 把字符串的第一个字符大写 |
string.title() | 把字符串的每个单词首字母大写 |
string.lower() | 转换 string 中所有大写字母为小写 |
string.upper() | 转换 string 中的小写字母为大写 |
string.swapcase(0 | 翻转 string 中的大小写 |
方法 | 说明 |
---|---|
string.ljust(width) | 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 |
string.rjust(width) | 右对齐 |
string.center(width) | 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 |
方法 | 说明 |
---|---|
string.lstrip() | 截掉 string 左边(开始)的空白字符 |
string.rstrip() | 右边 |
string.strip() | 截掉 string 左右两边的空白字符,注:如果其中输入的是12这样的参数,删的不是十二,而是1,2都会删掉 |
方法 | 说明 |
---|---|
string.partition(str) | 把字符串 string 分成一个 3元素的元组(str前面,str,str后面) |
string.rpartition(str) | 同上,不过是从右边开始查找 |
string.split(str="",num) | 以 str 分隔符切片 string,如果 num 有指定值,则仅分隔 num+1个字符串,str默认包含\r,\t,\n,空格 ,注:字符串本身不变,而是得到一个列对象 |
string.splitlines() | 按照行(\r, \n )分隔,返回一个包含各行作为元素的列表 |
string.join(seq) | 以 string 作为分隔符,将 seq 中所有元素(的字符串表示)合并为一个新的字符串 |
my_str="itheima itcase boxuegu"
num=my_str.count("it")
print(f"字符串{my_str}中有{num}个it字符串")
mew_my_str=my_str.replace(" ","|")
print(f"字符串{my_str}被替换空格后,结果是:{mew_my_str}")
my_str_list=mew_my_str.split("|")
print(f"字符串{my_str}被|分割后,结果是:{my_str_list}")
#output:
"""
字符串itheima itcase boxuegu中有2个it字符串
字符串itheima itcase boxuegu被替换空格后,结果是:itheima|itcase|boxuegu
字符串itheima itcase boxuegu被|分割后,结果是:['itheima', 'itcase', 'boxuegu']
"""
for
循环遍历字符串中每一个字符序列:内容连续,有序,可使用下标索引的一类数据容器
切片——从一个序列中取出一个子序列
此操作不会影响序列本身,而是会得到一个新序列
方法适用于字符串、列表、元组
序列[开始索引:结束索引:步长]
起始
位开始,到 结束
位的前一位结束(不包含结束位本身)my_str ="万过薪月,员序程马黑来,nohtyP学" #倒序字符串,切片取出 result1 = my_str[::-1][9:14] print(f"方式1结果:{result1}") #切片取出,再倒序 result2 = my_str[5:10][::-1] print(f"方式2结果:{result2}") #Spilt分隔”,“,replace替换”来“为空,倒叙字符串 result3 = my_str.split(",")[1].replace("来","")[::-1] print(f"方式3结果:{result3}") """ 方式1结果:黑马程序员 方式2结果:黑马程序员 方式3结果:黑马程序员 """
#定义集合字面量
{元素,元素,元素...}
#定义集合变量
变量名称={元素,元素,元素...}
#定义空集合
变量名称=set()
方法 | 说明 |
---|---|
myset.add() | 添加新元素 |
myset.remove() | 移除元素 |
myset.pop() | 随机取出一个元素 |
myset.clear() | 清空集合 |
myset1.difference(myset2) | 取集合1和集合2的差集(集合1有而集合2没有的),结果是得到一个新集合,集合1,集合2不变 |
myset1.difference_update(myset2) | 消除2个集合的差集,就是**在集合1内删除和集合2相同的元素。集合1被修改,集合2不变 |
myset1.unior(myset2) | 集合1集合2合并为一个新集合,得到新集合,集合1,集合2不变 |
len(myset) | 统计集合元素数量 |
集合不支持下标索引,所以集合不可以用while循环来遍历
for循环遍历与之前的数据容器一样
dictionary
(字典)是除列表以外 Python
之中最灵活的数据类型
字典同样可以用来存储多个数据
物体
的相关信息和列表的区别
字典用 {}
定义
字典使用键值对存储数据,键值对之间使用,分隔
key
是索引
value
是数据:
分隔xiaoming = {
"name":"宋江",
"绰号":"及时雨",
"地位":"梁山统领三代目",
"星宿":"天魁星"
}
#从字典中基于key获取value
name=xiaoming.["name"]
方法 | 说明 |
---|---|
mydict[key]=Value (key原本不存在于字典中) | 新增元素 |
mydict[key]=Value (key原本存在于字典中) | 更新元素 |
mydict,pop(key) | 删除元素 |
mydict.clear() | 清空元素 |
mydict.keys() | 获取全部的key |
len(mydict) | 计算字典的元素数量 |
max(数据类型)
:最大元素min (数据类型)
: 最小元素list(容器)
:容器转列表tuple(容器)
:容器转元组str(容器)
:容器转字符串set(容器)
:容器转集合sorted(容器,[reverse==True/False])
通用排序功能,默认False是从小到大,若要反向reverse==True运算符 | Python表达式 | 结果 | 描述 | 支持的数据类型 |
---|---|---|---|---|
+ | [1,2]+[3,4] | [1,2,3,4] | 合并 | 字符串、列表、元组 |
* | ["Hi"]*3 | ["Hi","Hi","Hi"] | 重复 | 字符串、列表、元组 |
in | 3 in (1,2,3) | True | 元素是否存在 | 字符串、列表、元组、字典 |
not in | 4 not in (1,2,3) | True | 元素是否不存在 | 字符串、列表、元组、字典 |
> >= == < <= | (1,2,3)<(2,2,3) | True | 元素比较 | 字符串、列表、元组 |
in
在对字典操作时,判断的是字典的键in
和 not in
被称为成员运算符运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False | 3 in (1,2,3) 返回 True |
not in | 如果在指定的序列中没有找到值返回True,否则返回False | 3 not in (1,2,3) 返回 False |
注意:在对字典操作时,判断的是字典的键
函数调用时通过“键=值”形式传递参数
可以使函数更加清晰,容易使用,同时也清除了参数的顺序要求
可以不按照固定顺序
可以与位置参数混用,位置参数必须在前,且匹配参数顺序
def a(name,age):
...
a(name="dpy",age=20)
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数前面,但关键字参数之间不存在先后顺序
问题1:在函数内部,针对参数使用赋值语句,会不会影响调用函数时传递的实参变量?–不会
问题2:如果传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,同样会影响到外部的数据
def demo(num_list: list): #num_list 是参数名称,list表示是个列表 print("函数内部的代码") # 使用方法修改列表的内容 num_list.append(9) print(num_list) print("函数执行完成") gl_list = [1, 2, 3] demo(gl_list) print(gl_list) """ output: 函数内部的代码 [1, 2, 3, 9] 函数执行完成 [1, 2, 3, 9] """
运算符 +=
python
中,列表变量调用 +=
本质上是在执行列表变量的 extend
方法,不会修改变量的引用gl_list = [4, 8, 2]
# 默认按照升序排序 - 较常用
gl_list.sort()
print(gl_list)
# 如果需要降序排序,需要执行reverse参数
gl_list.sort(reverse=True)
print(gl_list)
指定函数的缺省参数
def print_info(name, gender=True):
gender_text = "男生"
if not gender:
gender_text = "女生"
print("%s 是 %s" % (name, gender_text))
# 假设班上的同学,男生居多,所以将默认值设置为男生
# 提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值!
print_info("小明")
print_info("小红", False)
"""
小明 是 男生
小红 是 女生
"""
缺省参数的注意事项
def print_info(name, gender=True, title):
pass
定义支持多值参数的函数
\*
可以接受元组\*
可以接受字典*args
– 存放元组参数,前面有一个 *
**kwargs
– 存放字典参数,前面有两个 *
args
是 arguments
的缩写,有变量的含义kw
是 keywprd
的缩写,kwargs
可以记忆键值对参数def demo(num, *nums, **person):
print(num)
print(nums)
print(person)
demo(1) # 输出:1 () {}
demo(1, 2, 3, 4, 5) # 输出:1, (2, 3, 4, 5) {}
demo(1, 2, 3, 4, 5, name="小明", age=18) # 输出:1, (2,3,4,5) {name="小明",age=18}
提示:多值参数的应用会经常出现在网络上一些大牛开发的框架中,知道多值参数,有利于读懂大牛的代码
多值参数案例 – 计算任意多个数字的和
import argparse
def sum_numbers(*args):
num = 0
# 循环遍历
for n in args:
num += n
print(args)
return num
res = sum_numbers(1, 2, 3, 4, 5)
print(res)
元组和字典的拆包
在调用带有多值参数的函数时,如果希望:
args
kwargs
就可以使用
拆包
,简化参数传递,拆包的方式是:
*
*
def demo(*args, **kwargs): print(args) print(kwargs) # 元组/字典变量 gl_num = (1, 2, 3) gl_dict = {"name":"小明", "age":18} # 会将两个参数都传递给 *args demo(gl_num, gl_dict) # 拆包语法,简化元组/自带你变量的传递 demo(*gl_num, **gl_dict) # 等价于 demo(1, 2, 3, name="小明", age=18) """ output: (1, 2, 3, 4, 5) 15 """
def func(compute):
result=compute(1,2)
print(result)
def compute(x,y)
return x+y
func(compute)
lambda 传入参数:函数体(一行代码)
def func(compute):
result=compute(1,2)
print(result)
func(lambda x,y x+y)
在计算机中,文件是以二进制的方式保存在磁盘上的文本文件和二进制文件
文本文件
二进制文件
序号 | 函数/方法 | 说明 |
---|---|---|
01 | open | 打开文件,并且返回文件操作对象 |
02 | read | 将文件内容读取到内存 |
03 | write | 将指定内容写入文件 |
04 | close | 关闭文件 |
open
函数负责打开文件,并且返回文件对象read/write/close
三个方法都需要通过文件对象来调用open
函数默认以只读模式打开文件,并且返回文件对象语法如下:
f = open("文件名", "访问方式",encoding(编码格式)(推荐使用UTF-8格式))
访问方式 | 说明 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常 |
w | 以只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a | 以追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
r+ | 以读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常 |
w+ | 以读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a+ | 以读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
f=open("C:\KING的python\pythonProject1\测试.txt","r",encoding="UTF-8")
read 方法
文件对象.read(num)
# num 表示要从文件中读取的数据的长度(单位是字节)
read
方法默认(不传入num值)会把文件的所有内容一次性读取到内存readline 方法
readline
方法可以一次读取一行内容readlines
方法一次读取全部内容f=open("C:\KING的python\pythonProject1\测试.txt","r",encoding="UTF-8")
print(f"读取10字节的结果,{f.read(11)}")
"""
output:读取11字节的结果,爱意随风起,风止意难平
"""
for
循环读取文件行
for line in f:
print(f"每一行数据是:{line}")
读取大文件的正确姿势
# 1.打开文件
file = open("README")
# 2.读取文件
while True:
# 每次读取一行
text = file.readline()
# 判断是否读取到内容
if not text:
break
print(text, end="")
# 关闭文件
file.close()
f.close()
with open
**可以在操作完成后自动关闭close文件,避免忘掉close方法with open("文件名", "访问方式",encoding(编码格式)(推荐使用UTF-8格式))as f:
#文件写入
f.write("想写入的内容")
#内容刷新
f.flush()
直接调用write时,内容并未直接写入文件,而是会积攒在程序的内存中,称之为缓冲区
当调用flash的时候,内容才会真正写入文件
这样做是避免频繁操作硬盘,导致效率降低
小文件复制
# 1.打开文件
file_read = open("README")
file_Write = open("README[复件]", "w")
# 2.读、写文件
text = file_read.read()
file_Write.write(text)
# 3.关闭文件
file_read.close()
file_Write.close()
大文件复制
# 1.打开文件 file_read = open("README") file_Write = open("README[复件]", "w") # 2.读、写文件 while True: # 读取一行内容 text = file_read.readline() # 判断是否读取到内容 if not text: break file_Write.write(text) # 3.关闭文件 file_read.close() file_Write.close()
Python 解释器
遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常try(尝试)
来捕获异常try:
尝试执行的代码
except:
出现错误的处理
try
尝试,下方编写要尝试的代码,不确定是否能够正常执行的代码except
如果不是,下方编写尝试失败的代码简单异常捕获演练 – 眼球用户输入整数
try:
# 不能确定正确执行的代码
num = int(input("请输入一个整数:"))
except:
# 错误的处理代码
print("请输入正确的整数格式")
print("-" * 50)
"""
output:
请输入一个整数:dpy
请输入正确的整数格式
--------------------------------------------------
"""
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):#这是捕获多个异常(创建一个元组)
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s " % result)
Python
解释器抛出异常时,最后一行错误信息的第一个单词,就是错误类型需求
8
除以用户输入的整数并且输出try:
# 1. 提示用户输入一个整数
num = int(input("输入一个整数:"))
# 2. 使用 `8` 除以用户输入的整数并且输出
res = 8 / num
print(res)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确的整数")
捕获未知错误
Python
解释器抛出异常而被终止,可以再增加一个 except
except Exception as result:
print("未知错误 %s" % result)
在实际开发中,为了能够处理复杂的异常情况,实际的异常语法如下:
提示:
- 有关完整语法的应用场景,在后续学习中,结合实际的案例会更好理解
try: # 尝试执行的代码 pass except 错误类型1: # 针对错误类型1,对应的代码处理 pass except 错误类型2: # 针对错误类型2,对应的代码处理 pass except (错误类型3, 错误类型4): # 针对错误类型3 和 4,对应的d代码处理 pass except Exception as result: # 打印错误信息 print(result) else: # 没有异常才会执行的代码 pass finally: # 无论是否有异常,都会执行的代码 print("无论是否有异常,都会执行的代码")
else
只有在没有异常时才会执行的代码finally
无论是否有异常,都会执行的代码try: # 1. 提示用户输入一个整数 num = int(input("输入一个整数:")) # 2. 使用 `8` 除以用户输入的整数并且输出 res = 8 / num print(res) except ValueError: print("请输入正确的整数") except Exception as result: print("未知错误 %s" % result) else: print("尝试成功") finally: print("无论是否出现异常都会执行的代码") print("-" * 20)
需求
demo1()
提示用户输入一个函数并且返回demo2()
调用 demo1()
demo2()
def demo1():
return int(input("请输入整数:"))
def demo2():
return demo1()
# 利用异常的传递性,在主程序捕获异常
try:
print(demo2())
except Exception as result:
print("未知错误 %s" % result)
模块是 Python 程序架构一个核心概念
.py
结尾的 Python
源代码文件都是一个模块import 模块名1
import 模块名2
提示:在导入模块时,每个导入应该独占一行
模块名.
使用模块提供的工具 – 全局变量、函数、类使用 as 指定模块的别名
如果模块的名字太长,可以使用
as
指定模块的名称,以方便在代码中的使用
import 模块1 as 模块别名
注意:模块别名应该符合大驼峰命名法
import time
print("你好")
time.sleep(5)
print("我好")
from ... import
的方式import 模块名
是一次性把模块中所有工具全部导入,并且通过 模块名/别名访问# 从模块 导入 某一个工具
from 模块1 import 工具名
模块名.
注意:如果两个模块,存在同名的函数,那么后导入模块的函数,会覆盖掉先导入的函数
import
代码就应该统一写在代码的顶部,更容易及时发现冲突as
关键字给其中一个工具起一个别名from ... import *
# 从模块导入所有工具
from 模块名1 import *
这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查
from time import sleep
print("你好")
sleep(5)
print("我好")
Python
的解释器在导入模块时,会:
在开发时,给文件起名,不要和系统的模块文件重名
Python
中每一个模块都有一个内置属性__file__
可以查看导入模块的完整路径
import random
# 生成一个 0~10 的数字
rand = random.randint(0, 10)
print(rand)
注意:如果当前目录下,存在一个
random.py
的文件按程序就无法正常运行 这个时候,Python
的解释器会加载当前目录下的random.py
而不会加载系统的random
模块
原则 – 每一个文件都应该是可以被导入的
一个独立的 Python
文件就是一个模块
在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍!
在很多 Python
文件中都会看到以下格式的代码:
只需要正常的写一个python文件
如果调用两个模块的同名函数,会调用后一个,因为后一个会将前一个覆盖
实际开发场景
在实际开发中,每一个模块都是独立开发的,大多都有专人负责
开发人员通常会
在模块下发增加一些测试代码
__main__
属性
__name__
属性可以做到,测试模块的代码只在测试情况下被运行,而在被导入时不会被执行!
__name__
是 Python
的一个内置属性,记录着一个字符串__name__
就是模块名__name__
是 __main__
# 导入模块
# 定义全局变量
# 定义类
# 定义函数
# 在代码的最下方
def mian():
# ...
pass
# 根据 __name__ 判断是否执行下方代码
if __name__ == "__main__":
main()
__all__
变量
__all__=['test_a']
def test_a:
def test_b:
```
- 如果一个模块文件有**`__all__`变量**,当使用`from 模块名 import *`导入时,只能导入这个列表中的元素 - 所以如上例只能调用test_a ### 5.python 的包 #### 01.**概念** - 包是一个**包含多个模块的特殊目录** - 目录下有一个特殊的文件 `__init__.py` - 包名的命名方式和变量名一致,小写字母 + `_` #### 02.**好处** - 使用 `import 保名` 可以**一次性导入包中所有模块** **案例演练** 1. 新建一个 `cm_message` 的包 2. 在目录下,新建两个文件 `send_message` 和 `receive_message` 3. 在 `send_message` 文件中定义一个 `send` 函数 4. 在 `receive_message` 文件中定义一个 `receive` 函数 5. 在外部直接导入 `hm_message` 的包 **`__init__.py`** - 要在外界使用包中的模块,**需要在 `__init__.py` 中指定对外界提供的模块列表** ```py # __init__.py # 从 当前目录 导入 模块列表 from ch_message import send_message from ch_message import receive_message # ch_10_导入包.py import ch_message ch_message.send_message.send("hello") txt = ch_message.receive_message.receive() print(txt)
__all___
变量来控制import *
**json.dump(data)**
方法把python数据转化为json数据data=json.dumps(data)
**json.loads(data)**
方法把json数据转化为python数据data=json.loads(data)
#导入json模块
import json
#准备符合格式json格式的python数据
data=[{"name":"老王"},{"name":"张三"}]
#通过json.dump(data)方法把python数据转化为json数据
data=json.dumps(data)
#通过json.loads(data)方法把json数据转化为python数据
data=json.loads(data)
json.dumps()
时用**json.dumps(data.ensure_ascii=False)
可以保证中文的正常显示**pycharts
模块官方画廊
#导包,导入Line功能构建折线图对象
from pyecharts.charts import Line
#得到折线图对象
line=Line()
# 添加x轴数据
line.add_xaxis(["中国","美国","英国"])
#添加y轴数据
line.add_yaxis("GDP",[30,20,10])
#通过render方法生成图表
line.render()
set_global_opts
**方法来进行配置#导包,导入Line功能构建折线图对象 from pyecharts.charts import Line from pyecharts.options import TitleOpts,LegendOpts,ToolboxOpts,VisualMapOpts #得到折线图对象 line=Line() # 添加x轴数据 line.add_xaxis(["中国","美国","英国"]) #添加y轴数据 line.add_yaxis("GDP",[30,20,10]) #通过全局配置项set_global_opts来设置 line.set_global_opts( title_opts=TitleOpts(title="GDP展示",pos_left="center",pos_bottom="1%"),#这是标题 legend_opts=LegendOpts(is_show=True), toolbox_opts=ToolboxOpts(is_show=True),#工具箱 visualmap_opts=VisualMapOpts(is_show=True),#视觉映视 ) #生成图表 line.render()
replace()
**的方法删除不需要的内容json.loads()
**将JSON
转字典from pyecharts.charts import Map #准备地图对象 map = Map() #准备数据 data = [ ("北京市",99), ("上海市",199), ("湖南省",299), ("台湾省",399), ("广东省",499) ] #添加数据 map.add("测试地图",data,"china") #绘图 map.render()
from pyecharts.charts import Map from pyecharts.options import VisualMapOpts #准备地图对象 map = Map() #准备数据 data = [ ("北京市",99), ("上海市",199), ("湖南省",299), ("台湾省",399), ("广东省",499), ("黑龙江省",9), ] #添加数据 map.add("测试地图",data,"china") #设置全局配置 map.set_global_opts( visualmap_opts=VisualMapOpts( is_show=True, is_piecewise=True, # 是否分段 pieces=[ {"min":1,"max":9,"label":"1-9人","color":"#CCFFFF"}, {"min":10,"max":99,"label":"10-99人","color":"#FFFF99"}, {"min":100,"max":499,"label":"99-499人","color":"#FF9966"} ] ) ) #绘图 map.render()
#导包
from pyecharts.charts import Bar
#通过Bar构建基础柱状图
bar=Bar()
#添加x轴数据
bar.add_xaxis(["中国","美国","英国"])
#添加y轴数据
bar.add_yaxis("GDP",[30,20,10])
#绘图
bar.render()
#导包
from pyecharts.charts import Bar
#通过Bar构建基础柱状图
bar=Bar()
#添加x轴数据
bar.add_xaxis(["中国","美国","英国"])
#添加y轴数据
bar.add_yaxis("GDP",[30,20,10])
#反转x轴和y轴
bar.reversal_axis()
#绘图
bar.render()
label_opts=LabelOpts(position="位置信息")
#导包
from pyecharts.charts import Bar
from pyecharts.options import LabelOpts
#通过Bar构建基础柱状图
bar=Bar()
#添加x轴数据
bar.add_xaxis(["中国","美国","英国"])
#添加y轴数据
bar.add_yaxis("GDP",[30,20,10],label_opts=LabelOpts(position="right"))
#反转x轴和y轴
bar.reversal_axis()
#绘图
bar.render()
Timeline
功能#导包 from pyecharts.charts import Bar,Timeline from pyecharts.options import LabelOpts #通过Bar构建基础柱状图 bar1=Bar() bar1.add_xaxis(["中国","美国","英国"]) bar1.add_yaxis("GDP",[30,30,10],label_opts=LabelOpts(position="right")) bar1.reversal_axis() bar2=Bar() bar2.add_xaxis(["中国","美国","英国"]) bar2.add_yaxis("GDP",[50,50,50],label_opts=LabelOpts(position="right")) bar2.reversal_axis() bar3=Bar() bar3.add_xaxis(["中国","美国","英国"]) bar3.add_yaxis("GDP",[70,60,60],label_opts=LabelOpts(position="right")) bar3.reversal_axis() #构建时间线对象 timeline=Timeline() #在时间线内添加柱状图对象 timeline.add(bar1,"点1") timeline.add(bar2,"点2") timeline.add(bar3,"点3") #自动播放设置 timeline.add_schema( play_interval=1000,#自动播放的时间间隔,单位毫秒 is_timeline_show=True,#是否显示时间线 is_auto_play=True,#是否自动播放 is_loop_play=True#是否循环自动播放 ) #绘图就是用时间线对象,而不是Bar对象 timeline.render("基础时间线柱状图.html")
from pyecharts.globals import ThemeType
#构建时间线对象
timeline=Timeline({"theme":ThemeType.想要修改的主题})
list.sort(key=选择排序依据的函数,reverse=True|False)
参数key,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
参数reverse,是否反转排序结果,True表示降序,False表示升序
#如下限套列表、要求对外层列表进行排序、排序的依据是内层列表的第二个元素数宇
#以前学习的sorted两数就无法适用了。可以使用列表的sort方法
my_list =[["a",33],["b",55],["c",11]]
#定义排序方法
def choose_sort_key(element):
return element[1]
#将元素传入choose_sort_key函数中,用来确定按照谁来排序
my_list.sort(key=choose_sort_key,reverse=True)
print(my_list)
"""
output:
[['b', 55], ['a', 33], ['c', 11]]
"""
data.reverse()
**在程序开发中,应该现有类,再有对象
在使用面向对象开发前,应该首先分析需求,确定一下程序中需要包含哪些类!
在程序开发中,要设计一个类,通常需要满足以下三个要素:
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类
提示:需求中没有设计的属性或者方法在设计类时,不需要考虑
#构建一个类 class Student: name=None gender=None nationality=None native_place=None age=None #创建一个对象 stu_1=Student() #对象属性进行赋值 stu_1.name="xdb" stu_1.gender="女" stu_1.nationality="中国" stu_1.native_place="江苏" stu_1.age=20 #获取对象的数据 print(stu_1.name) print(stu_1.gender) print(stu_1.nationality) print(stu_1.native_place) print(stu_1.age) """ xdb 女 中国 江苏 20 """
class 类名:
def 方法1(self, 参数列表):
pass
def 方法2(self, 参数列表):
pass
self
定义一个猫类 Cat 定义两个方法 eat 和 drink 按照需求 - -不需要定义属性 class Cat: """这是一个猫类""" def eat(self): print("小猫爱吃鱼") def drink(self): print("小猫要喝水") # 创建猫对象 tom = Cat() tom.eat() tom.drink() print(tom) addr = id(tom) print("%x" % addr)
引用概念的强调
在面向对象开发中,引用的概念是同样适用的
tom
变量中仍然记录的是对象在内存中的地址tom
变量引用了新建的猫对象print
输出对象变量,在默认情况下,是能够输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制标识) [
提示:在计算机中,通常使用十六进制标识内存地址
- 十进制和十六进制都是用来表达数字的,只是标识的方式不一样
- 十进制和十六进制的数字之间可以来回转换
%d
可以以10进制输出数字%x
可以以16进制输出数字self
是成员方法定义时必须填写的
在方法内部,想要访问类的成员变量,必须使用self
在类封装的方法内部,self
就表示当前调用方法的对象自己
调用方法时,程序员不需要传递 self
参数
在放啊内部
self.
访问对象的属性self.
调用其他的对象方法改造代码如下:
class Cat: """这是一个猫类""" def eat(self): # 哪一个对象调用方法,self 就是哪一个对象的引用 print("%s 爱吃鱼" % self.name) def drink(self): print("%s 要喝水" % self.name) # 创建猫对象 tom = Cat() # 可以使用 .属性名,通过赋值语句就可以了 tom.name = "Tom" tom.eat() tom.drink() # 再创建一个猫对象 jerry = Cat() jerry.name = "大懒猫" jerry.eat() jerry.drink() """ Tom 爱吃鱼 Tom 要喝水 大懒猫 爱吃鱼 大懒猫 要喝水 """
.
,然后按下 Tab
键,iPython
会提示改对象能够调用的方法列表dir
传入标识符/数据,可以查看对象内的所有属性及方法提示:
__方法名__
格式的方法是Python
提供的内置方法/属性
序号 | 方法名 | 类型 | 作用 |
---|---|---|---|
01 | __new__ | 方法 | 创建对象时,会被自动调用 |
02 | __init__ | 方法 | 对象被初始化时,会被自动调用 |
03 | __del__ | 方法 | 对象被从内存中销毁前,会被自动调用 |
04 | __str__ | 方法 | 返回对象的描述信息,print 函数输出使用 |
init
)__init__
方法,是对象的内置方法
__init__
方法是专门用来定义一个类具有哪些属性的方法
__init__
——构造方法
__init__
方法使用__init__
方法内部使用 self.属性名 = 属性的初始值
就可以定义属性Cat
类创建的对象,都会拥有该属性class Cat: """这是一个猫类""" def __init__(self): print("调用初始化方法") self.name = "Tom" def eat(self): print("%s 爱吃鱼" % self.name) # 使用类名()创建对象时,会自动调用初始化方法 __init__ tom = Cat() print(tom.name) tom.eat() """ Tom Tom 爱吃鱼 """
__init__
方法进行改造
__init__
方法的参数self.属性 = 形参
接收外部传递的参数类名(属性1,属性2,...)
调用class Cat: """这是一个猫类""" def __init__(self, name): print("调用初始化方法") self.name = name def eat(self): print("%s 爱吃鱼" % self.name) # 使用类名()创建对象时,会自动调用初始化方法 __init__ tom = Cat("Tom") print(tom.name) tom.eat() snow = Cat("Snow") snow.eat() """ 调用初始化方法 Tom Tom 爱吃鱼 调用初始化方法 Snow 爱吃鱼 """
07.__del__
方法
类名()
创建对象时,为对象分配空间后,自动调用 __init__
方法__del__
方法__init__
改造初始化方法,可以让创建对象更加灵活__del__
如果希望在对象被销魂前,再做一些事情,可以考虑使用该方法类名()
创建,生命周期开始__del__
方法一旦被调用,生命周期结束__str__
方法,控制类转换为字符串行为print
输出对象变量时,能够打印自定义的内容,就可以利用 __str__
这个内置方法注意:
__str__
方法必须返回一个字符串
class Cat: def __init__(self, name): self.name = name print("%s 来了" % self.name) def __del__(self): print("%s 走了" % self.name) #def __str__(self): # 必须返回一个字符串 #return "我是小猫[%s]" % self.name # tom 是一个全局变量,在程序执行结束时内存被释放 tom = Cat("Tom") print(tom) """ Tom 来了 <__main__.Cat object at 0x00000226E25E5940> Tom 走了 """
class Cat: def __init__(self, name): self.name = name print("%s 来了" % self.name) def __del__(self): print("%s 走了" % self.name) def __str__(self): # 必须返回一个字符串 return "我是小猫[%s]" % self.name # tom 是一个全局变量,在程序执行结束时内存被释放 tom = Cat("Tom") print(tom) """ output: Tom 来了 我是小猫[Tom] Tom 走了 """
__it__
,即可同时完成 小于符号 和 大于符号 2种比较class Student: def __init__(self,name,age): self.name=name self.age=age def __lt__(self, other): return self.age<other.age #传入参数:other,另一个对象 #返回值:True或False stu1=Student("zcx",17) stu2=Student("xdb",18) print(stu1<stu2) print(stu1>stu2) """ output: True False """
__lt__
class Student: def __init__(self,name,age): self.name=name self.age=age def __le__(self, other): return self.age<other.age #传入参数:other,另一个对象 #返回值:True或False stu1=Student("zcx",17) stu2=Student("xdb",17) print(stu1<stu2) print(stu1>stu2) """ output: True True """
class Student: def __init__(self,name,age): self.name=name self.age=age def __le__(self, other): return self.age==other.age #传入参数:other,另一个对象 #返回值:True或False stu1=Student("zcx",17) stu2=Student("xdb",17) print(stu1==stu2) """ output: True """
私有成员变量
私有成员方法
class Phone:
__current_voltage = None
def __keep_single_core(self): #
print("让CPU以单核模式运行")
phone =Phone()
phone.__keep_single_core()
"""
Traceback (most recent call last):
File "D:\KING的python\pythonProject1\test01.py", line 8, in <module>
phone.__keep_single_core()
AttributeError: 'Phone' object has no attribute '__keep_single_core'
"""
class Phone: __current_voltage =0.5 def __keep_single_core(self): #构建私有成员方法 print("让CPU以单核模式运行") def call_by_5g(self): if self.__current_voltage>=1: print("5g通话开启") else: self.__keep_single_core() print("电量不足,无法使用5g通话,并已经设置为单核运行进行省电") phone =Phone() phone.call_by_5g() """ 让CPU以单核模式运行 电量不足,无法使用5g通话,并已经设置为单核运行进行省电 """
[
class 类名(父类名):
#添加新内容
#不添加内容使用pass
Dog
类是 Animal
类的子类,Animal
类是 Dog
类的父类,Dog
类从 Animal
类继承Dog
类是 Animal
类的派生类,Animal
类是 Dog
类的基类,Dog
类从 Animal
类派生C
类从 B
类继承,B
类又从 A
类继承C
类就具有 B
类和 A
类的所有属性和方法子类拥有父类以及父类的父类中封装的所有属性和方法
class Phone: ID=None producer="K" def call_by_4g(self): print("4g通话") class Phone2024(Phone): face_id="10001" #面部识别id def call_by_5g(self): print("新功能5g通话") phone=Phone2024() print(phone.producer) phone.call_by_4g() phone.call_by_5g() """ K 4g通话 新功能5g通话 """
[]
class 子类名(父类名1,父类名2...):
#添加新内容
#不添加内容使用pass
class A: def test(self): print("test 方法") class B: def demo(self): print("demo 方法") class C(A, B): """多继承可以让子类对象,同时具有多个父类的属性和方法""" pass # 创建子类对象 c = C() c.test() c.demo()
class Phone: ID=None producer="K" def call_by_4g(self): print("4g通话") class NFReader: nfc_type="第五代" producer="K" def read_card(self): print("NFC读卡") def write_card(self): print("NFC写卡") class RemoteControl: rc_type="红外遥控" def control(self): print("红外遥控开启了") class MyPhone(Phone,NFReader,RemoteControl): pass phone=MyPhone() phone.call_by_4g() phone.read_card() phone.write_card() phone.control() """ 4g通话 NFC读卡 NFC写卡 红外遥控开启了 """
问题的提出
提示:开发时,应该尽量避免这种容易产生混淆的情况!–如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承
[]
Python 中的 MRO – 方法搜搜索顺序
__mro__
可以查看方法搜索顺序method resolution order
,主要用于在多继承时判断方法、属性的调用路径print(C.__mro__)
# 输出结果
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
__mro__
的输出结果从左至右的顺序查找的应用场景
[
具体的实现方式,就相当于在子类中定义了一个和父类同名的方法并且实现
class Phone: ID=None producer="K" def call_by_5g(self): print("父类5g通话") class Phone2024(Phone): producer = "Q" face_id="10001" #面部识别id def call_by_5g(self): print("新功能5g通话") phone=Phone2024() print(phone.producer) phone.call_by_5g() """ output: Q 新功能5g通话 """
super().父类方法
来调用父类方法的执行关于 super
Python
中 super
是一个特殊的类super()
就是使用 super
类创建出来的对象调用父类方法的另一种方式
在
Python 2.x
时,如果需要调用父类的方法,还可以使用以下方式:
父类名.方法(self)
Python 3.x
还支持提示
父类名
和 super()
两种方式不要混用class Phone: ID=None producer="K" def call_by_5g(self): print("父类5g通话") class Phone2024(Phone): producer = "Q" face_id="10001" #面部识别id def call_by_5g(self): print("新功能5g通话") #方式1 #print(f"父类的厂商是:{Phone.producer}") #Phone.call_by_5g(self) #方式2 print(f"父类的厂商是:{super().producer}") super().call_by_5g() phone=Phone2024() print(phone.producer) phone.call_by_5g() """ output: Q 新功能5g通话 父类的厂商是:K 父类5g通话 """
[]
class Dog(object): def __init__(self, name) -> None: self.name = name def game(self): print("%s 蹦蹦跳跳地玩耍..." % self.name) class XiaoTianDog(Dog): def game(self): print("%s 飞到天上玩耍..." % self.name) class Person(object): def __init__(self, name) -> None: self.name = name def game_with_dog(self, dog: Dog): print("%s 和 %s 快乐地玩耍..." % (self.name, dog.name)) # 让狗玩耍 dog.game() # 1.创建 狗 对象 wangcai1 = Dog("旺财") wangcai2 = XiaoTianDog("飞天旺财") # 2.创建一个 小明 对象 xiaoming = Person("小明") # 3.让小明调用和狗玩的方法 xiaoming.game_with_dog(wangcai1) print("----------------------") xiaoming.game_with_dog(wangcai2) """ output: 小明 和 旺财 快乐地玩耍... 旺财 蹦蹦跳跳地玩耍... ---------------------- 小明 和 飞天旺财 快乐地玩耍... 飞天旺财 飞到天上玩耍... """
变量:类型
在容器类型的详细注释中
元组类型设置类型详细注解,需要将每一个元素都标记出来
字典类型设置类型详细注解,需要两个类型,第一个是key第二个是value
方法2——在注释中进行类型注解
# type:类型
一般,无法直接看出变量类型只是,会添加变量的类型注解
#基础数据类型注释 import random v1:int =10 v2:str="慊慊为汝" v3:bool=True #类对象类型注释 class Student: pass stu:Student=Student() #基础容器类型注释 my_list:list=[1,2,3] my_tuple:tuple=(1,2,3) my_dict:dict={"xdb":666} #容器类型详细注释 mylist: list[int] = [1, 2, 3] mytuple: tuple[int, str, bool] = (1, "xdb", True) mydict: dict[str, int] = {"xdb": 666} #在注释中进行类型注释 v4=random.randint(1,10) #type:int def func(): return 10 v5=func() #type:intb
1.对形参进行类型注解
def 函数方法名(形参名:类型,形参名:类型,..)
pass
2.对返回值进行类型注解
def 函数方法名(形参:类型,...,形参:类型)->返回值类型:
pass
#对形参进行类型注解
def add(x:int,y:int):
return x+y
# add()
#对返回值进行类型注解
def func(data:list)->list:
return data
from typing import Union
from typing import Union
my_list:list[Union(int,str)]=[1,2,"K","Q"]
def func(data:Union[int,str])->Union[int,str]:
pass
查看数据库
show databases;
使用数据库
use 数据库名称
创建数据库
CREATE DATABASE 数据库名称 CHARACTER SET utf8;
删除数据库
drop database 数据库名称
查看当前使用的数据库
select database();
查看有哪些表
show tables;
删除表
drop table 表名称
drop table if exists 表名称
创建表
create table 表名称(
列名称 列类型,
列名称,列类型,
......
);
-- 列类型:
int -- 整数
float --浮点数
varchar -- 文本,长度为数字,做最大长度限制
date -- 日期类型
timestamp -- 时间戳类型
create table student(
id int,
name varchar(10),
age int
);
数据插入 INSERT
insert into 表[(列1,列2,...,列N)]values(值1,值2,...值N),(值1,值2,......,值N),......,(值1,值2,......,值N);
数据删除 DELETE
delete from 表名称 where 条件判断
-- 条件判断:列 操作符 值
操作符:= < > <= >= != 等等
delete from student where id=1;
3.数据更新 UPDATE
update 表名 set 列=值 where 条件判断
-- 条件判断:列 操作符 值
操作符:= < > <= >= != 等等
update student set name ='ddb' where id=5
select 字段列表或* from 表
select 字段 或 聚合函数 from where 条件 group by 列
select gender,avg(age),sum(age),min(age),from student group by gender
select 列 或 聚合函数 或 * from 表
where ...(判断条件)
group by ...(按照哪一列)
order by ...(按照哪一列) asc(升序排列)|desc(降序排列)
limit n,m (n是跳过几条,m是取几条)
链接对象.close()
关闭和MySQL数据库的连接游标对象.fetchall()
将查询结果封装进元组内from pymysql import Connection #构建mysql数据库链接 conn=Connection( host="localhost", #主机名 port=3306, #端口 user="root", #账户 password="123456" #密码 ) print(conn.get_server_info()) #执行非查询性质SQL cursor=conn.cursor() #获取游标对象 #选择数据库 conn.select_db("world")#先选择数据库 #使用游标对象,执行sql查询 #cursor.execute("create table test_pymysql(id int);") 创建一个表 cursor.execute("select * from student")#提取所有列 results=cursor.fetchall()#获取的结果是双层嵌套元组 # print(results) for r in results: print(r) #关闭链接 conn.close() """ output: 8.0.36 (10001, '周杰轮', 31, '男') (10002, '王力鸿', 33, '男') (10003, '蔡依琳', 35, '女') (10004, '林志灵', 36, '女') (10005, '刘德滑', 33, '男') (10006, '张大山', 10, '男') (10007, '刘志龙', 11, '男') (10008, '王潇潇', 33, '女') (10009, '张一梅', 20, '女') (10010, '王一倩', 13, '女') (10011, '陈一迅', 31, '男') (10012, '张晓光', 33, '男') (10013, '李大晓', 15, '男') (10014, '吕甜甜', 36, '女') (10015, '曾悦悦', 31, '女') (10016, '刘佳慧', 21, '女') (10017, '项羽凡', 23, '男') (10018, '刘德强', 26, '男') (10019, '王强强', 11, '男') (10020, '林志慧', 25, '女') """
autocommit=True
设置为自动确认from pymysql import Connection #构建mysql数据库链接 conn=Connection( host="localhost", #主机名 port=3306, #端口 user="root", #账户 password="123456",#密码 autocommit=True #自动确认 ) print(conn.get_server_info()) #执行非查询性质SQL cursor=conn.cursor() #获取游标对象 #选择数据库 conn.select_db("world")#先选择数据库 #使用游标对象,执行sql #cursor.execute("create table test_pymysql(id int);") 创建一个表 cursor.execute("insert into student values(10021,'xdb',17,'女')")#提取所有列 #通过commit确认 #conn.commit() #关闭链接 conn.close()
#导包
from pyspark import SparkConf,SparkContext
#创建SparkConf类对象
conf=SparkConf().setMaster("local[*]").setAppName("test_saprk_app")
#基于SparkConf类对象创建SparkContext类对象
sc=SparkContext(conf=conf)
#打印PySpark的运行版本
#print(sc.version)
#停止SparkContext对象的运行(停止PySpark程序)
sc.stop()
1.通过parallelize方法将python对象加载到Spark内,成为RDD对象
如果要查看RDD里面有什么内容,需要用**collect()
方法**
#导包 from pyspark import SparkConf,SparkContext #创建SparkConf类对象 conf=SparkConf().setMaster("local[*]").setAppName("test_saprk_app") #基于SparkConf类对象创建SparkContext类对象 sc=SparkContext(conf=conf) #通过parallelize方法将python对象加载到Spark内,成为RDD对象 rdd1=sc.parallelize([1,2,3,4,5])#列表 rdd2=sc.parallelize((1,2,3,4,5))#元组 rdd3=sc.parallelize("abcdefg") #字符串 rdd4=sc.parallelize({1,2,3,4,5})#集合 rdd5=sc.parallelize({"key1":"value1","key2":"value"})#字典 #如果要查看RDD里面有什么内容,需要用collect()方法 print(rdd1.collect()) print(rdd2.collect()) print(rdd3.collect()) print(rdd4.collect()) print(rdd5.collect()) sc.stop() """ output: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] ['a', 'b', 'c', 'd', 'e', 'f', 'g'] [1, 2, 3, 4, 5] ['key1', 'key2'] """
2.读取文件转RDD对象——通过textFile方法,读取文件数据加载到Spark内,成为RDD对象
PySpark也支持通过SparkContext
入口对象,来读取文件,来构建出RDD对象
#导包
from pyspark import SparkConf,SparkContext
#创建SparkConf类对象
conf=SparkConf().setMaster("local[*]").setAppName("test_saprk_app")
#基于SparkConf类对象创建SparkContext类对象
sc=SparkContext(conf=conf)
#通过textFile方法,读取文件数据加载到Spark内,成为RDD对象
rdd=sc.textFile("D:\KING的python\pythonProject1\测试.txt")
print(rdd.collect())
"""
output:
['爱意随风起,风止意难平', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝', '慊慊为汝']
"""
rdd.map(func)
# func : f:(T) ->U
# f: 表示这是一个函数(方法)
# (T) -> U 表示的是方法的定义:
# () 表示的是传入参数,(T)表示传入一个参数, () 表示没有传入参数
# T 是泛型的代称,在这里表示 任意类型
# U 也是泛型代称,在这里表示,任意类型
# -> U 表示返回值
# (T) -> U 总结起来的意思是:这是一个方法,这个方法接受一个参数传入,传入类型不限,返回一个返回值,返回类型不限
# (A) -> A 总结起来的意思是:这是一个方法,这个方法接受一个参数传入,传入类型不限,返回一个返回值,返回类型不限,返回值和传入参数类型一致
#导包 from pyspark import SparkConf,SparkContext import os os.environ['PYSPARK_PYTHON']="king D:\anaconda\envs\king\python.exe" #创建SparkConf类对象 conf=SparkConf().setMaster("local[*]").setAppName("test_saprk_app") #基于SparkConf类对象创建SparkContext类对象 sc=SparkContext(conf=conf) #准备一个RDD rdd =sc.parallelize([1,2,3,4,5]) #通过map方法得到全部的数据库都乘以10 def func(data): return data*10 rdd2=rdd.map(func) print(rdd2.collect())
对RDD执行map操作,然后进行解除嵌套操作
计算逻辑与map一致,比map多一个解除嵌套的作用
# 嵌套的list
lst = [[1,2,3],[4,5,6],[7,8,9]]
# 解除嵌套
lst = [1,2,3,4,5,6,7,8,9]
#导包 from pyspark import SparkConf,SparkContext import os os.environ['PYSPARK_PYTHON']="king D:\anaconda\envs\king\python.exe" #创建SparkConf类对象 conf=SparkConf().setMaster("local[*]").setAppName("test_saprk_app") #基于SparkConf类对象创建SparkContext类对象 sc=SparkContext(conf=conf) #准备一个RDD rdd =sc.parallelize(["xdb h","ddb m","xxx s","xtj d"]) #将rdd数据里面的一个个单词提取出来 rdd2 = rdd.flatMap(lambda x:x.spilt(" ")) print(rdd2.collect()) """ output: ['xdb','h','ddb','m','xxx','s','stj','d'] """
rdd.reduceByKey(func)
#func:(v,v) -> v
#接受2个传入参数(类型要一致),返回一个返回值,类型和传入要求一致
rdd = sc.parallelize([('a',1),('a',1),('b',1),('b',1),('b',1)])
result = rdd.reduceByKey(lambda a,b:a+b)
print(result.collect())
"""
output:
[('b',3),('a',2)]
"""
过滤掉想要的数据进行保留
rdd.filter(func)
# func:(T) -> bool 传入1个参数进来随意类型,返回值必须是True or False
返回值是True的数据被保留,False的数据被丢弃
对RDD数据进行去重,返回新的RDD
rdd.distinct() 无需传参
rdd.sortBy(func.ascending=False,numPartition=1)
#func:(T) -> U:告知按照rdd中的哪个数据进行排序,比如 lambda x:x[1] 表示按照rdd中的第二列元素进行排序
# ascending True升序 False 降序
# numPartition:用多少分区排序
def outer(num1):
def inner(num2):
nonlocal num1num1 += num2print(num1)
return inner
fn = outer(10)
fn(10)
#output: 20
def account_create(in1tial_amount=0) def atm(num, deposit=True): nonlocal initial_amount if deposit: initial_amount += num print(f"存款:+{num},账户余额{initial_amount}") else: initial_amount -= num print(f"取款:-{num},账户余额:{initial_amount}") return atm fn = account_create() fn(300) fn(200) fn(300,False) """ output: 存款:+300,账户余额:300 存款:+200,账户余额:500 取款:-300,账户余额:200 """
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能
定义一个闭包函数,在闭包函数内部:
import threading
thread_obj = threading.Thread([group [, target [, name [, args [, kwargs]]]]])group:暂时无用,未来功能的预留参数
- target:执行的目标任务名
- args:以元组的方式给执行任务传参
- kwargs:以字典方式给执行任务传参
- name:线程名,一般不用设置
#启动线程,让线程开始工作
thread_obj.start()
#演示多线程编程的使用 import time import threading def sing(): while True: print("我在唱歌,啦啦啦..") time.sleep(1) def dance(): while True: print("我在跳舞,畖呱...") time.sleep(1) if--name_- =='-_main--': # 创建一个唱歌的线程 sing_thread =threading.Thread(target=sing) # 创建一个跳舞的线程 dance_thread =threading.Thread(target=dance) # 让线程去于活吧 sing_thread.start() dance_thread.start()
从被匹配字符串开头进行匹配,匹配成功后返回匹配对象(包含匹配信息),匹配不成功,返回空(就是开头直接匹配,若不匹配向后直接不匹配)
s ='python itheima python itheima python itheima'
result = re.match('python', s)
print(result)#<re.Match object;span=(0,6),match='python'>
print(result.span())#(0,6)表示匹配成功,下标由0,6
print(result.group())#python
s ='1python itheima python itheima python itheima'
result =re.match('python',s)
print(result)#None
搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后
s ='1python666itheima666python666'
result = re.search('pytHon',s)
print(result)#<re.Match object;span=(1,7),match='python'>
print(result.span())#(1,7)
print(result.group())# python
整个字符串都找不到,返回None
s ='itheima666'
result =re.search('python',s)
print(result)# None
s =1python666itheima666python666
result = re.findall('python's )
print(result)#['python''python'
找不到返回空list:[]
s =1python666itheima666python666result = re.findall('itcast', s)print(result)#[]
字符 | 描述 |
---|---|
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,‘n’ 匹配字符 “n”。‘\n’ 匹配一个换行符。序列 ‘\’ 匹配 “” 而 “(” 则匹配 “(”。 |
^ | 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。 |
$ | 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。 |
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等价于 ‘o+’。‘o{0,}’ 则等价于 ‘o*’。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,“o{1,3}” 将匹配 “fooooood” 中的前三个 o。‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。 |
? | 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 “oooo”,‘o+?’ 将匹配单个 “o”,而 ‘o+’ 将匹配所有 ‘o’。 |
. | 匹配除换行符(\n、\r)之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像"(.|\n)"的模式。 |
(pattern) | 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘(’ 或 ‘)’。 |
(?:pattern) | 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 ‘industry|industries’ 更简略的表达式。 |
(?=pattern) | 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) | 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?<=pattern) | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"`(?<=95 |
(?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如"`(?<!95 |
x|y | 匹配 x 或 y。例如,‘z|food’ 能匹配 “z” 或 “food”。‘(z|f)ood’ 则匹配 “zood” 或 “food”。 |
[xyz] | 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 |
[^xyz] | 负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’、‘l’、‘i’、‘n’。 |
[a-z] | 字符范围。匹配指定范围内的任意字符。例如,‘[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符。 |
[^a-z] | 负值字符范围。匹配任何不在指定范围内的任意字符。例如,‘[^a-z]’ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
\cx | 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
\w | 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]'。 |
\W | 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。 |
\xn | 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,‘\x41’ 匹配 “A”。‘\x041’ 则等价于 ‘\x04’ & “1”。正则表达式中可以使用 ASCII 编码。 |
\num | 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,‘(.)\1’ 匹配两个连续的相同字符。 |
\n | 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 |
\nm | 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 |
\nml | 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。 |
\un | 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。 |
#匹配账号,只能由字母和数字组成,长度限制6到10位 r=^[0-9a-zA-Z]{6,10}$ s=123456_ print(re.findall(r,s)) #匹配QQ号,要求纯数字,长度5-11,第一位不为0 r=^[1-9][0-9]{4,10}$' s=123453678 print(re.findall(r,s)) #匹配邮箱地址,只允许99、163、gmail这三种邮箱地址 # abc.efg.dawqq.com.cn.eu.qq.aa.cc # abcgq.com #{内容}.{内容}.{内容}.{内容}.{内容}.{内容}.{内容}.{内容}@{内容}.{内容}.{内容} r=r'^[\w-]+(\.[\w-]+)*@(991163lgmail)(\.[\w-]+)+$' s='a.b.c.d.e.f.ggq.com.a.z.c.d.e' print(re.findall(r,s))
os
就是“operating system”的缩写,顾名思义,os
模块提供的就是各种 Python 程序与操作系统进行交互的接口。通过使用os
模块,一方面可以方便地与操作系统进行交互,另一方面也可以极大增强代码的可移植性。如果该模块中相关功能出错,会抛出OSError
异常或其子类异常。
注意,如果是读写文件的话,建议使用内置函数
open()
;如果是路径相关的操作,建议使用os
的子模块os.path
;如果要逐行读取多个文件,建议使用fileinput
模块;要创建临时文件或路径,建议使用tempfile
模块;要进行更高级的文件和路径操作则应当使用shutil
模块。
当然,使用os
模块可以写出操作系统无关的代码并不意味着os
无法调用一些特定系统的扩展功能,但要切记一点:一旦这样做就会极大损害代码的可移植性。
此外,导入os
模块时还要小心一点,千万不要为了图调用省事儿而将os
模块解包导入,即不要使用from os import *
来导入os
模块;否则os.open()
将会覆盖内置函数open()
,从而造成预料之外的错误。
注意,
os
模块中大多数接受路径作为参数的函数也可以接受“文件描述符”作为参数。
文件描述符:file descriptor,在 Python 文档中简记为 fd,是一个与某个打开的文件对象绑定的整数,可以理解为该文件在系统中的编号。
该属性宽泛地指明了当前 Python 运行所在的环境,实际上是导入的操作系统相关模块的名称。这个名称也决定了模块中哪些功能是可用的,哪些是没有相应实现的。
目前有效名称为以下三个:posix
,nt
,java
。
其中posix
是 Portable Operating System Interface of UNIX(可移植操作系统接口)的缩写。Linux 和 Mac OS 均会返回该值;nt
全称应为“Microsoft Windows NT”,大体可以等同于 Windows 操作系统,因此 Windows 环境下会返回该值;java
则是 Java 虚拟机环境下的返回值。
因此在我的电脑(win10)上执行下述代码,返回值是nt
:
>>> import os
>>> os.name
'nt'
而在 WSL(Windows Subsystem Linux,Windows 下的 Linux 子系统)上的结果则是:
>>> import os
>>> os.name
'posix'
查看
sys
模块中的sys.platform
属性可以得到关于运行平台更详细的信息,在此不再赘述
os.environ
属性可以返回环境相关的信息,主要是各类环境变量。返回值是一个映射(类似字典类型),具体的值为第一次导入os
模块时的快照;其中的各个键值对,键是环境变量名,值则是环境变量对应的值。在第一次导入os
模块之后,除非直接修改os.environ
的值,否则该属性的值不再发生变化。
比如其中键为“HOMEPATH”(Windows 下,Linux 下为“HOME”)的项,对应的值就是用户主目录的路径。Windows 下,其值为:
>>> os.environ["HOMEPATH"]
'd:\\justdopython'
Linux 下,其值为:
os.environ[“HOME”]
‘/home/justdopython’
这个函数需要传入一个路径作为top
参数,函数的作用是在以top
为根节点的目录树中游走,对树中的每个目录生成一个由(dirpath, dirnames, filenames)
三项组成的三元组。
其中,dirpath
是一个指示这个目录路径的字符串,dirnames
是一个dirpath
下子目录名(除去“.”
和“..”
)组成的列表,filenames
则是由dirpath
下所有非目录的文件名组成的列表。要注意的是,这些名称并不包含所在路径本身,要获取dirpath
下某个文件或路径从top
目录开始的完整路径,需要使用os.path.join(dirpath, name)
。
注意最终返回的结果是一个迭代器,我们可以使用for
语句逐个取得迭代器的每一项:
>>> for item in os.walk("."):
... print(item)
...
('.', ['do'], ['go_go_go.txt'])
('.\\do', ['IAmDirectory', 'python'], [])
('.\\do\\IAmDirectory', [], [])
('.\\do\\python', [], ['hello_justdopython.txt'])
“listdir”即“list directories”,列出(当前)目录下的全部路径(及文件)。该函数存在一个参数,用以指定要列出子目录的路径,默认为“.”
,即“当前路径”。
函数返回值是一个列表,其中各元素均为字符串,分别是各路径名和文件名。
比如定义以下函数:
def get_filelists(file_dir='.'):
list_directory = os.listdir(file_dir)
filelists = []
for directory in list_directory:
# os.path 模块稍后会讲到
if(os.path.isfile(directory)):
filelists.append(directory)
return filelists
“mkdir”,即“make directory”,用处是**“新建一个路径”**。需要传入一个类路径参数用以指定新建路径的位置和名称,如果指定路径已存在,则会抛出FileExistsError
异常。
该函数只能在已有的路径下新建一级路径,否则(即新建多级路径)会抛出FileNotFoundError
异常。
相应地,在需要新建多级路径的场景下,可以使用os.makedirs()
来完成任务。函数os.makedirs()
执行的是递归创建,若有必要,会分别新建指定路径经过的中间路径,直到最后创建出末端的“叶子路径”。
示例如下:
>>> os.mkdir("test_os_mkdir")
>>> os.mkdir("test_os_mkdir")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'test_os_mkdir'
>>>
>>> os.mkdir("test_os_mkdir/test_os_makedirs/just/do/python/hello")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'test_os_mkdir/test_os_makedirs/just/do/python/hello'
>>>
>>> os.makedirs("test_os_mkdir/test_os_makedirs/just/do/python/hello")
用于删除文件,如果指定路径是目录而非文件的话,就会抛出IsADirectoryError
异常。删除目录应该使用os.rmdir()
函数。
同样的,对应于os.makedirs()
,删除路径操作os.rmdir()
也有一个递归删除的函数os.removedirs()
,该函数会尝试从最下级目录开始,逐级删除指定的路径,几乎就是一个os.makedirs()
的逆过程;一旦遇到非空目录即停止。
该函数的作用是将文件或路径重命名,一般调用格式为os.rename(src, dst)
,即将src
指向的文件或路径重命名为,dst
指定的名称。
注意,如果指定的目标路径在其他目录下,该函数还可实现文件或路径的“剪切并粘贴”功能。但无论直接原地重命名还是“剪切粘贴”,中间路径都必须要存在,否则就会抛出FileNotFoundError
异常。如果目标路径已存在,Windows 下会抛出FileExistsError
异常;Linux 下,如果目标路径为空且用户权限允许,则会静默覆盖原路径,否则抛出OSError
异常,
和上两个函数一样,该函数也有对应的递归版本os.renames()
,能够创建缺失的中间路径。
注意,这两种情况下,如果函数执行成功,都会调用os.removedir()
函数来递归删除源路径的最下级目录。
“getcwd”实际上是“get the current working directory”的简写,顾名思义,也就是说这个函数的作用是**“获取当前工作路径”**。在程序运行的过程中,无论物理上程序在实际存储空间的什么地方,“当前工作路径”即可认为是程序所在路径;与之相关的“相对路径”、“同目录下模块导入”等相关的操作均以“当前工作路径”为准。
在交互式环境中,返回的就是交互终端打开的位置;而在 Python 文件中,返回的则是文件所在的位置。
在 Windows 下会有如下输出:
>>> os.getcwd()
'd:\\justdopython\\just\\do\\python'
Linux 下的输出则是:
>>> os.getcwd()
'/home/justdopython/just/do/python'
“chdir”其实是“change the directory”的简写,因此os.chdir()
的用处实际上是切换当前工作路径为指定路径。其中“指定路径”需要作为参数传入函数os.chdir()
,该参数既可以是文本或字节型字符串,也可以是一个文件描述符,还可以是一个广义的类路径(path-like)对象。若指定路径不存在,则会抛出FileNotFoundError
异常。
在 Windows 下,调用该函数的效果为:
>>> os.chdir("d:/justdopython/just/do")
>>> os.getcwd()
'd:\\justdopython\\just\\do'
在 Linux 下的效果则是:
>>> os.chdir("/home/justdopython/just/do") # 也可将参数指定为"..",即可切换到父目录
>>> os.getcwd()
'/home/justdopython/just/do'
有了这个函数,跨目录读写文件和调用模块就会变得非常方便了,很多时候也就不必再反复将同一个文件在各个目录之间复制粘贴运行,脚本完全可以坐镇中军,在一个目录下完成对其他目录文件的操作,正所谓“运筹帷幄之中,决胜于千里之外”也。
举例来说,可以通过将“当前工作目录”切换到父目录,从而直接访问父目录的文件内容:
>>> os.chdir("..")
>>> os.getcwd()
'D:\\justdopython\\just'
>>> with open("hello_justdopython.txt", encoding="utf-8") as f:
... f.read()
...
'欢迎访问 justdopython.com,一起学习 Python 技术~'
>>> os.listdir()
['hello_justdopython.txt']
其实这个模块是os
模块根据系统类型从另一个模块导入的,并非直接由os
模块实现,比如os.name
值为nt
,则在os
模块中执行import ntpath as path
;如果os.name
值为posix
,则导入posixpath
。
使用该模块要注意一个很重要的特性:os.path
中的函数基本上是纯粹的字符串操作。换句话说,传入该模块函数的参数甚至不需要是一个有效路径,该模块也不会试图访问这个路径,而仅仅是按照“路径”的通用格式对字符串进行处理。
更进一步地说,os.path
模块的功能我们都可以自己使用字符串操作手动实现,该模块的作用是让我们在实现相同功能的时候不必考虑具体的系统,尤其是不需要过多关注文件系统分隔符的问题。
这是一个十分实用的函数,可以将多个传入路径组合为一个路径。实际上是将传入的几个字符串用系统的分隔符连接起来,组合成一个新的字符串,所以一般的用法是将第一个参数作为父目录,之后每一个参数即使下一级目录,从而组合成一个新的符合逻辑的路径。
但如果传入路径中存在一个“绝对路径”格式的字符串,且这个字符串不是函数的第一个参数,那么其他在这个参数之前的所有参数都会被丢弃,余下的参数再进行组合。更准确地说,只有最后一个“绝对路径”及其之后的参数才会体现在返回结果中。
>>> os.path.join("just", "do", "python", "dot", "com")
'just\\do\\python\\dot\\com'
>>>
>>> os.path.join("just", "do", "d:/", "python", "dot", "com")
'd:/python\\dot\\com'
>>>
>>> os.path.join("just", "do", "d:/", "python", "dot", "g:/", "com")
'g:/com'
将传入路径规范化,返回一个相应的绝对路径格式的字符串。
也就是说当传入路径符合“绝对路径”的格式时,该函数仅仅将路径分隔符替换为适应当前系统的字符,不做其他任何操作,并将结果返回。所谓“绝对路径的格式”,其实指的就是一个字母加冒号,之后跟分隔符和字符串序列的格式:
>>> os.path.abspath("a:/just/do/python")
'a:\\just\\do\\python'
>>> # 我的系统中并没有 a 盘
当指定的路径不符合上述格式时,该函数会自动获取当前工作路径,并使用os.path.join()
函数将其与传入的参数组合成为一个新的路径字符串。示例如下:
>>> os.path.abspath("ityouknow")
'D:\\justdopython\\ityouknow'
该函数返回传入路径的“基名”,即传入路径的最下级目录。
>>> os.path.basename("/ityouknow/justdopython/IAmBasename")
'IAmBasename'
>>> # 我的系统中同样没有这么一个路径。可见 os.path.basename() 页是单纯进行字符串处理
整这个函数要注意的一点是,返回的“基名”实际上是传入路径最后一个分隔符之后的子字符串,也就是说,如果最下级目录之后还有一个分隔符,得到的就会是一个空字符串:
>>> os.path.basename("/ityouknow/justdopython/IAmBasename/")
''
与上一个函数正好相反,返回的是最后一个分隔符前的整个字符串:
>>> os.path.dirname("/ityouknow/justdopython/IAmBasename")
'/ityouknow/justdopython'
>>>
>>> os.path.dirname("/ityouknow/justdopython/IAmBasename/")
'/ityouknow/justdopython/IAmBasename'
哈哈实际上前两个函数都是弟弟,这个函数才是老大。
函数os.path.split()
的功能就是将传入路径以最后一个分隔符为界,分成两个字符串,并打包成元组的形式返回;前两个函数os.path.dirname()
和os.path.basename()
的返回值分别是函数os.path.split()
返回值的第一个、第二个元素。就连二者的具体实现都十分真实:
def basename(p):
"""Returns the final component of a pathname"""
return split(p)[1]
def dirname(p):
"""Returns the directory component of a pathname"""
return split(p)[0]
通过os.path.join()
函数又可以把它们组合起来得到原先的路径。
这个函数用于判断路径所指向的位置是否存在。若存在则返回True
,不存在则返回False
:
>>> os.path.exists(".")
True
>>> os.path.exists("./just")
True
>>> os.path.exists("./Inexistence") # 不存在的路径
False
一般的用法是在需要持久化保存某些数据的场景,为避免重复创建某个文件,需要在写入前用该函数检测一下相应文件是否存在,若不存在则新建,若存在则在文件内容之后增加新的内容。
该函数判断传入路径是否是绝对路径,若是则返回True
,否则返回False
。当然,仅仅是检测格式,同样不对其有效性进行任何核验:
>>> os.path.isabs("a:/justdopython")
True
这两个函数分别判断传入路径是否是文件或路径,注意,此处会核验路径的有效性,如果是无效路径将会持续返回False
。
>>> # 无效路径
>>> os.path.isfile("a:/justdopython")
False
>>>
>>> # 有效路径
>>> os.path.isfile("./just/plain_txt")
True
>>>
>>> # 无效路径
>>> os.path.isdir("a:/justdopython/")
False
>>> # 有效路径
>>> os.path.isdir("./just/")
True
\W- ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。