python基础大全(一)
Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。
官方宣布,2020 年 1 月 1 日, 停止 Python 2 的更新。Python 2.7 被确定为最后一个 Python 2.x 版本。
笔者使用的是python3.8,该博文并不适合完全零基础的读者,并且不会将所有的python基础全部展示出来,该博客旨在解决一些python的关键用法,python零基础请移步以下网址:
安装
安装python有两种方式
直接安装python环境,网址:Download Python | Python.org
安装conda环境,搭建虚拟python环境,推荐这个办法搭建python环境,可使用不同python环境进行编程,具体搜笔者的另外一个博客,Anaconda
命令行运行python
在Linux或macOS系统中,您可以使用命令行来运行Python文件。步骤如下:
打开终端。
使用cd命令切换到文件所在目录。
输入 python 文件名.py,并按Enter键运行。
例如,如果文件名为test.py,并且它位于 /home/user/PythonProjects 目录下,可以输入以下命令来运行该文件:
cd /home/user/PythonProjects
python test.py
python -m test
也可以用 python3 来运行
cd /home/user/PythonProjects
python3 test.py
或者在文件前面加上python路径来运行
/usr/bin/python test.py
python -m 模块名
和 python 模块名.py
两种方式都可以运行Python文件,但它们有一些区别。
python -m 模块名
会自动搜索 sys.path,在其中寻找对应的模块文件,并运行它。它还可以运行没有 main.py 的模块。python 模块名.py
直接运行指定的文件。需要知道文件的确切路径。
所以,当你的模块被其他模块导入时,你可以使用 python -m 模块名
来运行你的模块,而不需要知道它的具体路径。
如果你只是想运行一个特定的脚本,你可以使用 python 文件名.py
。
命令行传参
在文件运行时,可以使用 sys.argv 列表来接收参数。sys.argv[0] 包含文件名,而后面的参数存储在 sys.argv[1] 到 sys.argv[n]。例如,在命令行中运行 Python 文件 test.py,并传递参数 arg1 和 arg2:
python test.py arg1 arg2
在 test.py 中,可以使用 sys.argv 列表来访问命令行参数。:
import sys
print(sys.argv[1]) #arg1
print(sys.argv[2]) #arg2
如果您希望程序能够处理更多的命令行选项和参数,可以使用argparse库。此库可以帮助您定义和处理命令行参数,并提供有关如何使用参数的帮助信息。例如:
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
在命令行中运行
python test.py 1 2 3 --sum # 输出6
这样就可以使用命令行来运行Python文件并传递参数了。
注释
注释不是越多越好。对于一目了然的代码,不需要添加注释。
对于复杂的操作,应该在操作开始前写上相应的注释。
对于不是一目了然的代码,应该在代码之后添加注释。
绝对不要描述代码。一般阅读代码的人都了解Python的语法,只是不知道代码要干什么
单行注释
描述某个变量(某行代码)的作用
第一种写法:
# 注释
ui = 1
第二种写法:
ui = 1 # 注释
突出某段代码的重要性
# ==================
# 请勿删除该变量!!!!
# ==================
ui = 1
类注释
描述某个类的作用
格式如下:
"""类用处"""
使用实例:
class test:
"""类用处"""
pass
方法注释
描述某个方法的作用
DocStrings 文档字符串使用惯例:它的首行简述函数功能,第二行空行,第三行为函数的具体描述。
格式如下(reST风格):
"""
方法的用处
:param parm: 形参的用处
:return: 返回的数据
"""
这是现在流行的一种风格,reST风格,Sphinx的御用格式,比较紧凑。
param为说明传入的形参
return为说明返回的数据
使用实例:
def test(self,parm01,parm02):
"""
方法的用处
:param parm01: 形参的用处01
:param parm02: 形参的用处02
:return: 返回的数据
"""
pass
基本数据类型
Python3 中有六个标准的数据类型:
Number(数字)
String(字符串)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)
Python3 的六个标准数据类型中:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
数组
python数组用于在单个变量中存储多个值
列表(List)
在 Python 中,列表是一种常用的数据类型,它可以存储多个元素。列表中的元素可以是任意类型,并且列表本身可以嵌套。
新建一个包含数字的列表
number = [1,2,3,4,5,6,7,8]
返回/修改列表中某下标的值
number[0] # 返回第一个列表中的值
number[-1] # 返回倒数第一个列表中的值
number[1:5] # 返回列表的第二个到第六个的值
number[1] = 1 # 修改列表某下标的值
其中number[1:5]
为列表切片操作,列表切片是通过使用下标范围来访问列表中的一个子集的过程。语法格式如下:
list_name[start:end]
其中,start
为切片的起始位置(包括该位置上的元素),end
为切片的结束位置(不包括该位置上的元素)。
例如,若要访问列表 my_list
中第 2 个元素到第 4 个元素,可以使用下面的代码:
sub_list = my_list[1:4]
如果不指定起始位置,切片将从列表的第一个元素开始,如果不指定结束位置,切片将到列表的最后一个元素结束。
可以使用负数下标来从列表末尾开始计算位置。例如,要访问列表 my_list
的最后三个元素,可以使用下面的代码:
sub_list = my_list[-3:]
另外,列表切片还可以使用步长来访问列表中的元素,语法格式如下:
list_name[start:end:step]
其中,step 为步长。例如,若要访问列表 my_list 中的每第二个元素,可以使用下面的代码:
sub_list = my_list[::2]
返回列表的长度
len(number)
循环打印列表元素
for i in number:
print(i)
添加列表元素
number.append(10) # 在数组的末尾加入元素10
删除列表元素
number.pop(1) # 删除第一个元素
number.remove(3) # 删除数组中元素为3的元素
拼接两个列表
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list = list1 + list2
print(list)
构建二维列表
list = [[1, 2, 3],[4, 5, 6]]
print(list[0][1])
Python包含以下列表函数:
函数 | 作用 |
---|---|
len(list) | 返回列表元素个数 |
max(list) | 返回列表元素最大值 |
min(list) | 返回列表元素最小值 |
list(seq) | 将元组转换为列表 |
列表中包含了以下内置方法:
方法 | 作用 |
---|---|
list.append(obj) | 在列表末尾添加新的对象 |
list.count(obj) | 统计某个元素在列表中出现的次数 |
list.extend(seq) | 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) |
list.index(obj) | 从列表中找出某个值第一个匹配项的索引位置 |
list.insert(index, obj) | 将对象插入列表 |
list.pop([index=-1]) | 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 |
list.remove(obj) | 移除列表中某个值的第一个匹配项 |
list.reverse() | 反向列表中元素 |
list.sort( key=None, reverse=False) | 对原列表进行排序 |
list.clear() | 清空列表 |
list.copy() | 复制列表 |
元组(Tuple)
Python 的元组与列表类似,不同之处在于元组的元素不能修改。元组的不可变指的是元组所指向的内存中的内容不可变。元组使用小括号 ( ),列表使用方括号 [ ]。
新建一个包含数字的列表
tup1 = (1,2,3,4,5,6,7,8)
返回元组中某下标的值
tup1[0] # 返回第一个
tup1[1:5] # 返回元组的第二个到第六个的值
返回元组的长度
len(tup1)
循环打印元组元素
for i in tup1:
print(i)
删除整个元组
del tup1
拼接两个元组
tup1 = (1,2,3,4)
tup2 = (5,6,7,8)
tup = tup1+tup2
print(tup)
构建二维元组
tup = ((1,2,3,4),(5,6,7,8))
print(tup[0][1])
Python包含以下列表函数:
函数 | 作用 |
---|---|
len(tuple) | 返回元组元素个数 |
max(tuple) | 返回元组元素最大值 |
min(tuple) | 返回元组元素最小值 |
tuple(iterable) | 将可迭代系列转换为元组。 |
字典(Dictionary)
字典是另一种可变容器模型,且可存储任意类型对象。它和javascript的对象或者json对象差不多,字典的每个键值 key=>value 对用冒号 : 分割,每个对之间用逗号(,)分割,整个字典包括在花括号 {} 中 ,一个简单的字典实例:
person = {'name': 'jhon', 'age': 20, 'contry': 'CHINA'}
键必须是唯一的,但值则不必。值可以取任何数据类型,但键必须是不可变的,如字符串,数字。两个重要的点需要记住:
不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行
返回元组字典里的值,如果用字典里没有的键访问数据,会输出错误。
person = {'name': 'jhon', 'age': 20, 'contry': 'CHINA'}
print(person['name'])
print(person['contry'])
修改/增加字典的值
person = {'name': 'jhon', 'age': 20, 'contry': 'CHINA'}
person['age'] = 21 # 键存在,则修改对应的键值
person['cash'] = 100000 # 键不存在,则增加对应的键值对
删除字典元素
del person['cash'] # 删除键'cash'
删除整个字典
del person
Python包含以下列表函数:
函数 | 作用 |
---|---|
len(dict) | 计算字典元素个数,即键的总数。 |
str(dict) | 输出字典,可以打印的字符串表示。 |
type(variable) | 返回输入的变量类型,如果变量是字典就返回字典类型。 |
字典包含了以下内置方法:
方法 | 作用 |
---|---|
dict.clear() | 删除字典内所有元素 |
dict.copy() | 返回一个字典的浅复制 |
dict.fromkeys() | 创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值 |
dict.get(key, default=None) | 返回指定键的值,如果键不在字典中返回 default 设置的默认值 |
key in dict | 如果键在字典dict里返回true,否则返回false |
dict.items() | 以列表返回一个视图对象 |
dict.keys() | 返回一个视图对象 |
dict.setdefault(key, default=None) | 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default |
dict.update(dict2) | 把字典dict2的键/值对更新到dict里 |
dict.values() | 返回一个视图对象 |
pop(key[,default]) | 删除字典 key(键)所对应的值,返回被删除的值。 |
popitem() | 返回并删除字典中的最后一对键和值。 |
集合(Set)
集合是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
新建一个字符串集合,打印后以字典的方式展示
s = set(("Google", "Alibaba", "Taobao", "Facebook"))
print(s)
增加集合中的元素,如果元素已存在,则不进行任何操作
s.add("Twitch")
s.update({"WeChat","Tencent"})
删除集合中的元素
s.remove("Tencent") # 若元素不存在会发生错误
s.discard("Tencent") # 若元素不存在不会发生错误
s.pop() # 对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除
判断元素是否在集合中存在
"Youtube" in s
集合包含了以下内置方法:
方法 | 作用 |
---|---|
add() | 为集合添加元素 |
clear() | 移除集合中的所有元素 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
difference_update() | 移除集合中的元素,该元素在指定的集合也存在。 |
discard() | 删除集合中指定的元素 |
intersection() | 返回集合的交集 |
intersection_update() | 返回集合的交集。 |
isdisjoint() | 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。 |
issubset() | 判断指定集合是否为该方法参数集合的子集。 |
issuperset() | 判断该方法的参数集合是否为指定集合的子集 |
pop() | 随机移除元素 |
remove() | 移除指定元素 |
symmetric_difference() | 返回两个集合中不重复的元素集合。 |
symmetric_difference_update() | 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。 |
union() | 返回两个集合的并集 |
update() | 给集合添加元素 |
深浅拷贝
我们在对变量进行赋值时,我们会用=
将对象与变量连通起来,此时,我们称之为引用,引用的是对象。
a = [1, 2, 3, 4, ['a', 'b']] # 原始对象
b = a # 赋值,传对象的引用
a.append(5) # 修改对象a
print('a = ', a)
print('b = ', b)
b[4].append('c') # 修改对象b中的['a', 'b']数组对象
print('a = ', a)
print('b = ', b)
print('a的地址是: ', id(a))
print('b的地址是: ', id(b), '是否与a相等', id(a) == id(b))
运行结果
a = [1, 2, 3, 4, ['a', 'b'], 5]
b = [1, 2, 3, 4, ['a', 'b'], 5]
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
a的地址是: 2401854257984
b的地址是: 2401854257984 是否与a相等 True
可以看到,在修改了a的值后,b的值也会被修改了。反过来修改b的值,a的值也会跟着修改。并且a与b的地址是一模一样的,那么证明这两个变量是完全相同的,如同实体与影子(b是a的影子)。
我们对a进行一次浅拷贝,使用copy模块,例子如下:
import copy
a = [1, 2, 3, 4, ['a', 'b']] # 原始对象
c = copy.copy(a) # 对象拷贝,浅拷贝
a.append(5) # 修改对象a
print('a = ', a)
print('c = ', c)
c[4].append('c') # 修改对象b中的['a', 'b']数组对象
print('a = ', a)
print('c = ', c)
print('a的地址是: ', id(a))
print('b的地址是: ', id(c), '是否与a相等', id(a) == id(c))
运行结果
a = [1, 2, 3, 4, ['a', 'b'], 5]
c = [1, 2, 3, 4, ['a', 'b']]
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
a的地址是: 3252829633472
b的地址是: 3252829634432 是否与a相等 False
可以看到,在修改了a的值后,c的值却不会被修改。反过来修改c的值,a的值竟然会跟着修改。
可以观察到a与c的地址是不一样的,可以知道a与c是两个不同的对象,但是指定的是同一个值。
我们对a进行一次深拷贝,使用copy模块,例子如下:
import copy
a = [1, 2, 3, 4, ['a', 'b']] # 原始对象
d = copy.deepcopy(a) # 对象拷贝,深拷贝
a.append(5) # 修改对象a
print('a = ', a)
print('d = ', d)
d[4].append('c') # 修改对象b中的['a', 'b']数组对象
print('a = ', a)
print('d = ', d)
print('a的地址是: ', id(a))
print('b的地址是: ', id(d), '是否与a相等', id(a) == id(d))
运行结果
a = [1, 2, 3, 4, ['a', 'b'], 5]
d = [1, 2, 3, 4, ['a', 'b']]
a = [1, 2, 3, 4, ['a', 'b'], 5]
d = [1, 2, 3, 4, ['a', 'b', 'c']]
a的地址是: 2280897003456
b的地址是: 2280897002240 是否与a相等 False
可以看到,无论修改a的值还是修改b的值,它们都不会互相影响。并且a与b的地址不相同。所以我们可以知道a与d是两个完全不同的对象,值与地址都不同。
由此我们可以得出结论:
b = a: 赋值引用,a 和 b 都指向同一个对象。a与b相互影响
b = copy.copy(a): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。a不影响b,b影响a。
b = copy.deepcopy(a): 深拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。a与b互不影响。
字符串
创建字符串
字符串是 Python 中最常用的数据类型。我们可以使用引号('
或"
)来创建字符串。
创建字符串很简单,只要为变量分配一个值即可。例如:
String1 = 'Hello World!'
String2 = "Hello python"
字符串查找
字符串长度
调用len
,该方法不仅仅用在字符串,也可以统计列表,元组的长度
name = "helloworld"
len(name)
索引
对标java的indexOf(int ch,int fromindex)
,索引是通过字符串下标返回该下标的字符
str[0:1]
其中str为变量,0是头下标,1是尾下标
特定字符串
调用find函数,返回首字母在匹配字符串的下标
name.find("World")
判断某字符串是否在该字符串里
用in
关键字,若存在则返回True
name = "helloworld"
print("world" in name)
计算子字符串在字符串中出现的次数
调用count
方法
name = "helloworld"
count = name.count("l",0,len(name))
print(count)
字符串操作
删除某特定尾字符
调用rstrip
,如果方法不传参则默认删除空格符
name = "helloworld;"
print(name)
count = name.rstrip(';')
print(count)
字符串类型转换
字符串类型转换为其他类型
int类型(整数类型)
str = '1'
int(str)
str = 'a'
int(str) # 强转
float类型(浮点类型)
str = '0.05'
float(str)
这里提一下浮点类型的四舍五入,可以调用round函数计算
number = 5.454245435
round(number,3)
number为传入的浮点类型,3位保留3位数
其他类型转换成字符串类型
number = 1
str(number)
正则表达式
正则表达式是一个特殊的字符序列,它能帮助人们方便的检查一个字符串是否与某种模式匹配。
可用RegExr: 学习、构建 和 测试 正则表达式 Test RegEx (regexr-cn.com)生成正则表达式
引入模块
import re
match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none
re.match(pattern, string, flags=0)
形参作用如下(按传入顺序):
pattern
:匹配的正则表达式string
:要匹配的字符串flags
:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
matcher = re.match("hello",name)
print(matcher)
匹配完成后,可用span
方法在起始位置匹配
matcher.span()
search
扫描整个字符串并返回第一个成功的匹配
re.search(pattern, string, flags=0)
形参作用如下(按传入顺序):
pattern
:匹配的正则表达式string
:要匹配的字符串flags
:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
matcher = re.search("hello",name)
print(matcher)
匹配完成后,可用group
方法在返回匹配的字
matcher.group()
sub
替换字符串中的匹配项
re.sub(pattern, repl, string, count=0, flags=0)
形参作用如下(按传入顺序):
pattern
:匹配的正则表达式repl
:替换的字符串,也可以是一个函数string
:要匹配的字符串count
:模式匹配后替换的最大次数,默认 0 表示替换所有的匹配flags
:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
print(name)
name = re.sub("hello","bello",name)
print(name)
变量
私有变量
不与其他共享,自己独享,如函数和方法的局部变量,实例变量
写的时候,在变量左边加两个下斜杆(_)即可
例如:
__a = 1
__b = "1"
变量赋值
单个变量赋值
i = 1000 # int型
j = 1000.0 # float型
name = "tom" # 字符串型
print(i)
print(j)
print(name)
多个变量赋值
给多个变量同时赋值,变量的值相同:
a = b = c = 1
为多个变量指定多个值:
a, b, c = 1, 2, "tom"
类变量
class内,不在class的任何方法内,使用类变量时,将类实例化后调用
class test:
a = "123"
__b = 1
def test01(self):
print(self.a) # 方法调用类变量
@classmethod
def test02(cls):
print(cls.__b) # 静态方法调用类变量
局部变量
函数内、class的方法(类方法、静态方法、实例方法)内,且变量前面没有修饰
def test01(self):
a = 1 # 局部变量
全局变量
全局变量供全局共享,全局类和函数均可访问,达到同步作用。同时还可以被外部文件访问。
全局变量使用的时候,需要用global显示声明。 一般情况下,如果函数直接调用全局变量,不做更新的话,一般没有问题,但如果有重新赋值,又没有在函数内部使用 global声明的话, 就相当于在内部创建了一个同名的局部变量,局部变量优先级要高于全局变量。
def myfunc():
global x
x = "fantastic"
实例变量
class的构造方法内,使用self修饰
def __init__(self):
self.a = 1 # 实力变量
删除变量
调用del
,可删除变量
name = "helloworld"
print(name)
del(name)
print(name)
多分支选择
注意,该处只适用于python 10以上的版本
switch
是“开关”的意思,它也是一种“选择”语句,但它的用法非常简单。switch
是多分支选择语句。说得通俗点,多分支就是多个 if。
python在10之后加入了match-case
语法,改语法的用法类似于switch,但是是比较高级的switch用法。match-case
语法的使用方法如下:
def http_error(status):
match status:
case 400:
return 'Bad request'
case 401:
return 'Unauthorized'
case 403:
return 'Forbidden'
case 404:
return 'Not found'
case _:
return 'Unknown status code'
可以看到,当status
中输入不同的信息之后,match
会进入到对应的分支上面进行匹配,从而返回对应的结果。该语法也等价于:
def http_error(status):
if status == 400:
return 'Bad request'
elif status == 401:
return 'Unauthorized'
elif status == 403:
return 'Forbidden'
elif status == 404:
return 'Not found'
else:
return 'Unknown status code'
case
中可以使用|符号代表逻辑或,就是if
上面的or
,例如:
week = 7
match week:
case 1:
print("星期一")
case 2:
print("星期二")
case 3:
print("星期三")
case 4:
print("星期四")
case 5:
print("星期五")
case 6 | 7:
print("周末")
match也有很多高级用法,比如匹配序列:
a = [1, 2, 3]
match a:
case [1]:
print("匹配 [1]")
case [1, obj]:
print("匹配长度为2的列表,且列表的第一个元素是1,第二个元素不限,并用 obj 作为第二个元素的别名,若能匹配上,可以通过obj变量获取第二个元素内容", obj)
case [1, *obj]:
print("匹配长度大于等于1的列表,且列表第一个元素是1,后面可以有多个元素,也可以没有任何元素", obj)
case [1, (2|3), 3]:
print("| 代表 or;(2|3)代表列表的第二个元素要么是2,要么是3")
case [1, (2|3) as second, 3]:
print("和上一个一样,只不过给第二个元素绑定了一个别名:second,如果匹配上,可以通过 second 变量获取第二个元素", second)
case [1, 2] | [1, 2, 3]:
print('匹配 [1,2] or [1,2,3]')
case [1, second, 3] if second == 2:
print('带有限制条件的匹配,后面的 if 条件满足了,才会进行匹配')
case _:
print('_ 代表匹配其他情况,类似于 if...else.. 语句中的 else')
匹配对象:
class A(object):
def __init__(self, x, y=None):
self.x = x
self.y = y
a = A(1, 1)
b = A(2, 2)
c = A(3) # 使用了默认参数
obj = [a, b, c]
for i in obj:
match i:
case A(x=1, y=1): # 此处不能直接写实例化的对象,要写 类名(参数,..)
print('匹配实例化类时,参数x=1, y=1 的对象')
case A(x=3):
print('匹配实例化类时,参数x=3,y使用了默认值的对象')
case A(x=first, y=second):
print("匹配参数为任意值的实例化对象,first,second两个变量,可以方便的获取对象 x,y 属性实际存储的值",first, second)
匹配字典:
a = {'name': 'wang', "age": 22}
b = {'name': b'zhang', 'age': "33"}
c = {'name': b'zhao', 'age': 23}
ls = [a, b, c]
for i in ls:
match i:
case {"name": name, 'age': int(age)}: # int(age) 代表匹配 age 字段是整数类型的值,name 字段没有规定,所以任意类型都会匹配
print(f"匹配 age 是整数类型的:{name},{age}")
case {"name": name, "age": str(age)}:
print(f'匹配 age 是字符串类型的:{name},{age}')
面向对象
类
用来描述具有相同的属性和方法的对象的集合。
类中双下划线函数的作用
使用demo类
class A:
def __init__(self):
print("我调用了init方法")
def __new__(cls):
print("我调用了new方法")
return super().__new__(cls)
def method(self):
print("执行function")
def __del__(self):
print("我调用了del方法")
if __name__ == '__main__':
a = A()
a.method()
__init__
负责进行对象的初始化,它是python中的构造方法
demo类中执行到__init__输出的是
我调用了init方法
__new__
负责创建类实例的静态方法,__new__的执行顺序优先于__init__
依照Python官方文档的说法,__new__方法主要是当用户继承一些不可变的class时(比如int, str, tuple), 提供给用户一个自定义这些类的实例化过程的途径。
__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
__new__必须要有返回值,返回实例化出来的实例,这点在实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
demo类中执行到__new__输出的是
我调用了new方法
我调用了init方法
__del__
负责销毁实例化对象,在编写程序时,如果之前创建的类实例化对象后续不再使用,最好在适当位置手动将其销毁,释放其占用的内存空间。
大多数情况下,Python 开发者不需要手动进行垃圾回收,因为 Python 有自动的垃圾回收机制,能自动将不需要使用的实例对象进行销毁。
无论是手动销毁,还是 Python垃圾回收机制自动销毁,都会调用 __del__方法。
demo类中执行到__del__输出的是
我调用了new方法
我调用了init方法
执行function
我调用了del方法
创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:
class Test01:
"""创建类"""
a = "1" # 类变量
构造方法
当创建了这个类的实例时就会调用该方法
def __init__(self):
pass
类的方法
类方法
def test01(self):
pass
私有方法
def __test01(self):
pass
抽象方法(不需要实例化对象直接调用,像调用类变量,例如:Test01.test01()
)
@classmethod
def test01(cls):
pass
实例化对象
实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。
test01 = Test01() # 创建一个名为test01对象
test02 = Test01() # 创建一个名为test02对象
访问属性
访问方法
test01.test01() # 调用类方法
调用类变量
test01.a
包
在模块中,有一个__init__.py
的文件,这个文件说明该文件夹为一个包,该文件夹的名字为包名
__init__.py
可以指定某个包下导入的类,例如,在Utils
包中的__init__
文件写入:
from .DataTimeUtils import DataTimeUtils
from .YAMLReader import YAMLReader
__all__ = ["DataTimeUtils",
"YAMLReader",]
在其他类中导入时使用from Utils import *
即可导入__init__
文件中指定的所有类
from Utils import *
print(DataTimeUtils.getDay(0))
也可以指定某一个特定的类
from Utils import DataTimeUtils
print(DataTimeUtils.getDay(0))
该办法可以让导入更加容易,并且一定程度封闭该包下的类,但是该方法实测过会损耗性能
__init__.py
默认不写时,可导入该包下的类,用from Utils.DataTimeUtils import DataTimeUtils
即可
引用类
from .... import ....
引用类时,使用from Test.Test02 import Test02
,具体是from 包名.类名 import 类名
,调用时,直接实例化即可,例:
from Utils.DataTimeUtils import DataTimeUtils
dtu = DataTimeUtils()
dtu.getDay(0)
当一个py文件中没有类时(面向过程编程),使用from Test.Test02 import function
,具体是from 包名.py文件名 import 方法名
,想要使用该方法时,直接调用即可,例:
from Test.Test02 import function
function()
import ....
引用类时,使用import Utils.DataTimeUtils
,具体是import 包名.模块名(py文件名)
,调用时,需要完整写出包名.模块名.类名()
去实例化一个类,例:
import Utils.DataTimeUtils
dtu = Utils.DataTimeUtils.DataTimeUtils()
day = dtu.getDay(0)
当一个py文件中没有类时(面向过程编程),使用import Test02
,具体是import 包名.模块名(py文件名)
,想要使用该模块中的方法时,使用模块名.方法名()
即可调用该方法,例:
import Test02
Test02.function()
动态导入
动态导入指的是在运行时加载模块。这可以用于延迟加载模块,或者根据需要加载模块。
最常见的方法是使用 importlib
模块的 import_module
函数。例如,你可以这样做:
import importlib
def get_module(name):
return importlib.import_module(name)
math = get_module('math')
print(math.add(1, 2)) # 3
你也可以使用 __import__
内置函数来实现动态导入:
def get_module(name):
return __import__(name)
math = get_module('math')
print(math.add(1, 2)) # 3
注意,这些方法只能用于导入模块,而不能用于导入模块中的特定对象。要动态导入模块中的特定对象,可以使用 getattr
函数:
def get_function(module_name, function_name):
module = __import__(module_name)
return getattr(module, function_name)
add = get_function('math', 'add')
print(add(1, 2)) # 3
继承
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
语法:
class base:
"""父类"""
pass
class Test01(base):
"""子类"""
pass
一个类可以继承多个类,称为多继承,使用时尽量单继承
语法:
class base01:
"""父类1"""
pass
class base02:
"""父类2"""
pass
class Test01(base01,base02):
"""子类"""
pass
调用
子类可以调用父类的方法与类变量,并且可以调用祖先(父类的父类)的方法与类变量
class base:
a = "1"
def base_test01(self):
print("test")
class Test01(base):
def test01(self):
print(self.a)
print(self.base_test01())
重写父类方法
子类可以重写父类的方法
class base:
a = "1"
def base_test01(self):
print("test")
class Test01(base):
def base_test01(self):
print("test01")
继承实现接口
在python中,是没有interface
的,实现接口,可以使用abc
模块实现,例
import abc
class base(metaclass = abc.ABCMeta):
@abc.abstractmethod
def base_test01(self):
pass
class Test01(base):
def base_test01(self):
print("test")
@abc.abstractmethod
定义该方法为抽象方法,metaclass = abc.ABCMeta
定义该类为抽象基类
若继承的接口类没有实现base_test01
,则报错:
TypeError: Can't instantiate abstract class Test01 with abstract methods base_test01
在继承抽象类的过程中,应该尽量避免多继承;而在继承接口的时候,反而鼓励多继承接口。
在抽象类中,可以对一些抽象方法做出基础实现;而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现。
文件操作
Open
如果想用python读取文件,第一步要用open函数打开文件。open()是python的内置函数,它会返回一个文件对象,这个文件对象拥有read、readline、write、close等方法。
open函数有两个参数:
open('file','mode')
其中,file为需要打开的文件路径,mode为打开文件的模式,如只读、追加、写入等
mode常用的模式:
r:表示文件只能读取
w:表示文件只能写入,若文件不存在会创建一个
a:表示打开文件,在原有内容的基础上追加内容,在末尾写入
w+:表示可以对文件进行读写双重操作
mode参数可以省略不填,默认模式为r;mode参数还可以指定以什么样的编码方式读写文本,默认情况下open是以文本形式打开文件的,比如上面的四种mode模式。
当你需要以字节(二进制)形式读写文件时,只需要在mode参数中追加'b'即可:
rb:以二进制格式打开一个文件,用于只读
wb:以二进制格式打开一个文件,用于只写
ab:以二进制格式打开一个文件,用于追加
wb+:以二进制格式打开一个文件,用于读写
with关键字
在打开文件时,很多人通常直接用open('file')。在文件读写时可以使用 with
关键字。优点是当子句体结束后文件会正确关闭,即使在某个时刻引发了异常。
with open('workfile') as f:
for i in range(0,3):
read_data = f.write("test")
f.closed
close
打开文件并处理完毕后,需要关闭文件,这里用到close方法。
f.close() 用来关闭文件并立即释放它使用的所有系统资源。如果没有显式地关闭文件,Python的垃圾回收器最终将销毁该对象并关闭打开的文件,但这个文件可能会保持打开状态一段时间。
应该要养成使用close()的习惯。使用方法很简单:
f = open(file) # 打开文件
f.close() # 关闭文件
read
当使用open函数打开文件后,就可以使用该文件对象的各种方法了,read就是其中一种。
read()会读取一些数据并将其作为字符串(在文本模式下)或字节对象(在二进制模式下)返回。
read方法有一个参数:
f.read(size) # f为文件对象
参数size(可选)为数字,表示从已打开文件中读取的字节计数,默认情况下为读取全部。
假设有一个文件sample1.txt,内容如下:
This is python big data analysis!
现在读取该文件:
with open('sample1.txt') as f:
content = f.read()
print(content)
f.close()
readline
readline方法从文件中读取整行,包括换行符'\n'。
换行符(\n)留在字符串的末尾,如果文件不以换行符结尾,则在文件的最后一行省略,这使得返回值明确无误。
如果 f.readline() 返回一个空的字符串,则表示已经到达了文件末尾,而空行使用 '\n' 表示,该字符串只包含一个换行符。
f.readline()有一个参数:
f.readline(size)
参数size表示从文件读取的字节数。
假设有一个文件sample2.txt,共三行,内容如下:
hello,my friends!
This is python big data analysis,
let's study.
用readline函数读取该文件:
with open('a.txt') as f:
print(f.readline())
print(f.readline(5))
f.close()
readline方法会记住上一个readline函数读取的位置,接着读取下一行。
readlines
readlines方法和readline方法长得像,但功能不一样,前面说过readline方法只读取一行,readlines方法则是读取所有行,返回的是所有行组成的列表。
readlines方法没有参数,使用更加简单。依旧以sample2.txt为例:
with open('a.txt') as f:
print(f.readlines())
f.close()
write
write方法顾名思义,就是将字符串写入到文件里。
它只有一个参数:
f.write([str]) # f为文件对象
参数[str]代表要写入的字符串
使用起来也很简单,比如将下面字符串(注意里面的转行符'\n')
'hello,my friends!\nthis is python big data analysis'
写入到文件sample3.txt里。
with open('sample3.txt','w') as f:
f.write('hello,my friends!\nthis is python big data analysis')
f.close()
pathlib
pathlib提供了一种面向对象的方式来操作文件系统路径。它的目标是提供一种更简洁、更具可读性的方式来处理文件和目录。
在Python 2.6版本引入了pathlib模块,并在Python 3中进一步改进。使用 pathlib,你可以通过创建 Path 对象来操作文件和目录的路径,并执行各种操作,如检查路径是否存在、创建新目录、遍历目录等。
pathlib 提供了一组丰富的方法和属性,使得路径操作更加方便和直观。你可以使用Path类的实例来代表文件路径或目录路径,然后通过调用相应的方法来执行所需的操作。这种面向对象的风格使得代码更易于理解和维护。
pathlib官方文档:pathlib-文件系统路径操作
引入
import pathlib
快速入门
以下是一个pathlib的快速入门例子:
from pathlib import Path
# 创建一个Path对象
file_path = Path("/path/to/file.txt")
# 检查路径是否存在
if file_path.exists():
print("文件存在")
# 获取文件名
print("文件名:", file_path.name)
# 获取文件后缀
print("文件后缀:", file_path.suffix)
# 获取文件大小
print("文件大小:", file_path.stat().st_size)
# 遍历目录中的文件
dir_path = Path("/path/to/directory")
for file in dir_path.iterdir():
print(file.name)
新建Path对象
为了使用pathlib,我们需要创建一个Path对象。
from pathlib import Path
# 创建一个Path对象
path = Path("/path/to/file.txt")
# 也可以像这样拼接起来
path = Path("D:\\","My_Document","project")
路径拼接
上面我们在新建Path
的时候执行了一次拼接,除了创建Path
类对路径进行拼接外,我们也可以使用/
符号进行路径拼接。
这里面的/
符号,并不是传统意义上字符串路径上的斜杠或者反斜杠符号,也不是python中的除号,它代表的是一个层级,表示文件之间的层级关系。
例如:
path = Path("/user/file/","file1") # 新建Path对象对路径进行拼接
print(path)
path = path / "test.txt" # 使用/对路径进行拼接
print(path)
输出:
/user/file/file1
/user/file/file1/test.txt
获取路径
新建path对象后,我们可以获取路径的不同部分、或不同字段等内容,比如:
from pathlib import Path
# 创建一个Path对象
path = Path("/path/to/file.txt")
path.name # 返回文件名+文件后缀
path.stem # 返回文件名
path.suffix # 返回文件后缀
path.suffixes # 返回文件后缀列表
path.root # 返回根目录
path.parts # 返回文件路径的每一部分
path.anchor # 返回根目录
path.parent # 返回父级目录
path.parents # 返回所有上级目录的列表
也可以获取系统的一些信息,比如:
from pathlib import Path
Path.cwd() # 返回当前python文件的文件夹
Path.home() # 返回系统用户文件夹
执行判断
Path().exists()
: 判断该文件或文件夹是否存在Path().is_dir()
,判断 Path 是否是一个文件夹Path().is_file()
,判断 Path 是否是一个文件
例子:
from pathlib import Path
path = Path("/path/to/file.txt")
if path.exists():
if path.is_file():
print("路径存在,为文件")
elif path.is_dir():
print("路径存在,为文件夹")
else:
print("不存在该文件/文件夹")
创建/删除操作
Path().mkdir()
: 创建文件夹Path().rmdir()
: 删除文件夹,注意,文件夹必须为空Path().unlink()
: 删除文件
例子:
from pathlib import Path
path = Path("/path/to/file.txt")
# 创建文件夹函数
if path.exists(): # 如果已经存在,则跳过并提示
print("文件夹已存在,无需创建")
else:
path.mkdir() # 创建文件夹
# 删除文件夹
if path.exists(): # 如果存在,则删除文件夹
path.rmdir()
else:
print("文件夹不存在,无需删除")
# 删除文件
if path.exists(): # 如果存在,则删除文件
path.unlink()
else:
print("文件不存在,无需删除")
文件读写
pathlib支持文件读写,Path().open()
等同于open
,可以用with
打开。以下是常用的文件读写api:
Path().open()
: 默认以r
格式打开文件Path().read_bytes()
: 打开文件,以字节流格式读取文件内容,等同open
操作文件的rb
格式,在读取文件后会自动关闭文件流Path().read_text()
: 打开文件,以 str 格式读取文件内容,等同open
操作文件的r
格式,在读取文件后会自动关闭文件流Path().write_bytes()
: 对文件进行写操作,等同open
操作文件的wb
格式,在写入文件后会自动关闭文件流Path().write_text()
: 对文件进行写操作,等同open
操作文件的w
格式,在写入文件后会自动关闭文件流
例子:
from pathlib import Path
path = Path("/path/to/file.txt")
with path.open('w') as f: # 创建并打开文件
f.write('aaaabbbbcccc') # 写入内容
file_text = path.read_text() # 读取内容
print(f"读取的文件内容为:{file_text}")
pathlib替代os常用操作
pathlib可以替代os的一些函数,详细对比如下:
pathlib函数 | os函数 | 功能描述 |
---|---|---|
Path().resolve() | os.path.abspath() | 获取文件绝对路径 |
Path().chmod() | os.chmod() | 修改文件权限和时间戳 |
Path().mkdir() | os.mkdir() | 创建文件夹 |
Path().rename() | os.rename() | 重命名文件或文件夹,如果路径不同,会移动该文件夹并重新命名 |
Path().replace() | os.replace() | 重命名文件或文件夹,如果路径不同,会移动该文件夹并重新命名,如果存在,则替换现有目标 |
Path().rmdir() | os.rmdir() | 删除文件夹,文件夹必须为空 |
Path().unlink() | os.remove() | 删除文件 |
Path.cwd() | os.getcwd() | 返回当前python文件的文件夹 |
Path().exists() | os.path.exists() | 判断该文件或文件夹是否存在 |
Path.home() | os.path.expanduser() | 返回系统用户文件夹 |
Path().is_dir() | os.path.isdir() | 判断是否为文件夹 |
Path().is_file() | os.path.isfile() | 判断是否为文件 |
Path().is_symlink() | os.path.islink() | 判断是否为符号链接 |
Path().stat() | os.stat() | 获取文件属性 |
PurePath().is_absolute() | os.path.isabs() | 判断是否为绝对路径 |
PurePath().joinpath() | os.path.join() | 连接目录与文件名或目录 |
PurePath().name | os.path.basename() | 获取文件名 |
PurePath().parent | os.path.dirname() | 获取文件路径 |
Path.samefile() | os.path.samefile() | 判断两个路径是否相同 |
PurePath().suffix | os.path.splitext() | 分离文件名和扩展名 |
shutil
shutil
模块提供了一组高级文件和目录操作函数,它与os模块形成互补的关系。os主要提供了文件或文件夹的新建、删除、查看等方法,还提供了对文件以及目录的路径操作。shutil模块提供了移动、复制、 压缩、解压等操作,恰好与os互补。
引入shutil,我们需要这么做:
import shutil
以下是常用的几种API:
方法 | 作用 |
---|---|
| 复制单个文件 |
| 和 |
| 复制整个目录树 |
| 移动或重命名文件或目录 |
| 递归删除目录树 |
| 创建文件归档(例如压缩文件)。 |
| 解压缩文件归档 |
下面是一些示例。
复制单个文件:
import shutil
shutil.copy("file1.txt", "file2.txt")
复制目录树:
import shutil
shutil.copytree("folder1", "folder2")
移动文件或目录:
import shutil
shutil.move("file.txt", "new_folder/file.txt")
创建压缩文件:
import shutil
shutil.make_archive("myfiles", "zip", "myfiles")
解压缩文件:
import shutil
shutil.unpack_archive("myfiles.zip", "extracted_files")
删除目录树
import shutil
shutil.rmtree("folder_to_delete")
请注意,在使用 shutil
模块的函数时,请谨慎操作,因为一些函数(如 rmtree()
)可能会删除文件或目录。
相对路径解决办法
python操作文件的时候,相对路径是把运行的当前的.py文件作为基准的
假设当前的目录为:
Test
test.py
image
test.png
main.py
当运行main.py
操作test.png
这个文件的时候,相对路径则是./image/test.png
但是,当运行test.py
操作test.png
这个文件的时候,相对路径则是../image/test.png
因为这个,可能在编写代码,进行代码单元测试时可能正常,结果到运行整个项目的时候,就报错了,但是发现错误时,需要将代码里的所有的路径全部改一遍,如果代码量多,则增加工作量,显然不是明智之举。而在开发的时候,由于思维惯性,不可避免会发生这种错误。以下提供解决办法
默认
在开发的时候根据启动类,调整开发思维,将所有的相对路径以启动类为基准进行编写
该方法强烈不推荐,对某个模块进行测试的时候会非常麻烦
动态获取绝对路径
思路:
在父类中获取改py文件的绝对路径
通过字符串搜索项目所在根目录,返回路径
将路径定义为类变量(或全局变量),子类应用即可
import os
abs_path = os.path.abspath(os.path.dirname(__file__)) # 返回当前py文件下的绝对路径
root_path = abs_path[0:abs_path.find("Test")] # 返回根目录
print(root_path) # 子类用self.root_path即可
动态切换当前工作目录
思路
动态获取当前绝对路径
abs_path
每个类调用
os.chdir(abs_path)
,动态切换当前工作目录到该路径中
abs_path = os.path.abspath(os.path.dirname(__file__))
os.chdir(abs_path)
OS
在 Python 中,os 模块是用于操作操作系统相关功能的模块。该模块提供了一组与操作系统交互的函数和方法,包括文件和目录操作,进程管理,环境变量管理等等。
以下是 os 模块的一些常用功能:
文件和目录操作:os 模块提供了许多用于文件和目录操作的函数和方法,如创建、删除、移动、复制、重命名文件和目录等。
进程管理:os 模块提供了一些函数和方法,用于启动新的进程,管理当前进程和其他进程,如获取进程 ID、等待进程结束等。
环境变量管理:os 模块提供了一些函数和方法,用于读取、设置、删除系统环境变量。
文件描述符操作:os 模块提供了一些函数和方法,用于打开文件、读写文件、关闭文件、获取文件描述符等。
杂项:os 模块还提供了一些其他功能,如获取系统信息、判断文件是否存在、获取文件大小、获取文件权限等。
引入
import os
执行shell命令
os.system()
是一个可以在 Python 中执行 shell 命令的函数。它接收一个字符串参数,该字符串参数是需要执行的 shell 命令,然后在终端中执行该命令并返回执行结果。
下面是一个使用 os.system() 函数执行 shell 命令的示例:
import os
# 执行一个 shell 命令并获取执行结果
result = os.system("ls -l")
print(result)
os.system() 函数的使用相对简单,可以方便地执行一些 shell 命令。但是需要注意的是,该函数执行的是一个新的 shell 进程,因此可能会导致一些性能上的问题。如果需要更高效地执行 shell 命令,可以考虑使用subprocess
模块中的函数。
文件操作
删除文件
os.remove(path) # path是文件的路径,如果这个路径是一个文件夹,则会抛出OSError的错误,这时需用用rmdir()来删除
os.rmdir(path) # path是文件夹路径,注意文件夹需要时空的才能被删除
os.unlink('F:\新建文本文档.txt') # unlink的功能和remove一样是删除一个文件,但是删除一个删除一个正在使用的文件会报错。
判断是否存在该文件
使用os.path.exists
判断某个文件是否存在
is_exists = os.path.exists("test.png")
print(is_exists)
创建文件夹
os.mkdir('d:\hello') # 在一级目录中创建
os.makedirs('d:\hello\world\123') # 创建多级目录
获取某文件的绝对路径
abs_path = os.path.abspath("test.png") # 返回test.png的绝对路径
py_abs_path = os.path.abspath(os.path.dirname(__file__)) # 返回当前py文件下的绝对路径
print(abs_path)
print(py_abs_path)
路径拼接
last_path = os.path.join("D:/Test", "test.png")
print(last_path)
检索目录下的文件
os提供了三个api来检索当下目录的文件,分别是os.listdir
、os.walk
与os.scandir
os.listdir
非常简单粗暴,它返回path目录下的文件夹和文件,但不包含子文件夹里的文件夹和文件,并按照目录树结构的排序输出结果,即深度优先。例如:
import os
# 列出当前工作目录中的所有文件和子目录
files = os.listdir()
# 列出指定目录中的所有文件和子目录
files = os.listdir('/path/to/directory')
os.walk()
通过“自上而下”(先遍历当前目录,后遍历子目录)或“自下而上”(先遍历子目录,后遍历当前目录)来遍历目录,生成目录树中的文件夹名和文件名。它可传输的形参如下:
top
:根目录下的每一个文件夹(包含它自己)topdown
:可选,为True时,则自上而下,而为False时,则自下而上,默认True
onerror
:可选,是一个函数,OSError实例followlinks
:可选,通过软链接访问目录
它同时返回三个结果:
root
:根目录dirs
:根目录包含的子文件夹files
:根目录包含的子文件
它使用的例子如下:
import os
path = 'd:\hello'
# 遍历指定目录下所有文件和子文件夹文件
for root,dirs,files in os.walk(path):
print(files)
如果该目录下面还有目录,则会继续搜索文件。如果只想搜索当前目录下的文件,可以在末尾加break
只浏览一层目录:
import os
path = 'd:\hello'
# 遍历指定目录下所有文件
for root,dirs,files in os.walk(path):
print(files)
break
如果遍历文件夹下面所有的文件(包含子文件夹),在遍历files的时候加入root即可,这是因为os.walk
会从外逐层遍历文件,root会记录遍历file的路径。
import os
from pathlib import Path
path = 'd:\hello'
# 遍历指定目录下所有文件
for root,dirs,files in os.walk(path):
for file in files:
print(Path(root, file))
os.scandir
返回path目录树中对应的os.DirEntry对象的迭代器(文件夹或文件),不包含子文件夹里的文件夹和文件,但运行效率比os.walk高。Python官方推荐使用os.scandir来遍历目录树。
它的用法基本如下:
import os
with os.scandir(path) as entries:
for entry in entries:
# 处理 entry
entries
中的entry
是一个DirEntry
对象,表示遍历到的每一个文件或目录。DirEntry
对象有以下属性和方法:
name
: 表示文件或目录的名称。path
: 表示文件或目录的完整路径。is_file()
: 返回一个布尔值,表示当前对象是否为文件。is_dir()
: 返回一个布尔值,表示当前对象是否为目录。stat()
: 返回一个os.stat_result对象,包含了文件或目录的详细信息,如大小、创建时间等。
使用scandir函数遍历目录时,会自动管理目录资源的关闭和释放,因此建议使用with语句来打开目录。此外,scandir函数返回的是一个生成器对象,因此可以在遍历时逐个处理文件或目录,而不必将所有文件或目录都读入内存,因此在处理大型目录时,使用scandir函数可以提高程序的性能。
改变当前工作目录到指定的路径
os.chdir(path)
进程管理
在 Python 的 os 模块中,有一些函数可以用于进程管理。以下是一些常用的函数:
os.fork()
: 创建一个新的进程,新进程是原进程的一个副本,但是在新进程中返回值是 0,而在原进程中则是新进程的 PID。
import os
import time
pid = os.fork()
if pid == 0:
# 子进程
print("Child process %d" % os.getpid())
time.sleep(1)
else:
# 父进程
print("Parent process %d" % os.getpid())
os.waitpid(pid, 0)
print("Child process %d has terminated" % pid)
os.exec()
: 在当前进程中执行一个新的程序,该程序替换当前进程。exec 函数有多个变种,如 os.execvp()、os.execvpe()、os.execve() 等。
import os
os.execvp('ls', ['ls', '-l'])
print("This line will not be executed")
os.waitpid(pid, options)
: 等待指定 PID 的进程结束,返回值是子进程的 PID 和退出状态信息。
import os
import time
pid = os.fork()
if pid == 0:
# 子进程
print("Child process %d" % os.getpid())
time.sleep(1)
exit(123)
else:
# 父进程
print("Parent process %d" % os.getpid())
pid, status = os.waitpid(pid, 0)
print("Child process %d has terminated with status %d" % (pid, status))
os.kill(pid, signal)
: 向指定 PID 的进程发送信号,signal 参数指定了信号类型,如 SIGTERM、SIGKILL 等。
import os
import time
# 创建一个新进程
pid = os.fork()
if pid == 0:
# 子进程
print("Child process %d" % os.getpid())
while True:
print("Child process is running")
time.sleep(1)
else:
# 父进程
print("Parent process %d" % os.getpid())
# 等待一段时间后向子进程发送 SIGTERM 信号
time.sleep(5)
os.kill(pid, 15) # 发送 SIGTERM 信号
print("Sent SIGTERM signal to child process %d" % pid)
环境变量管理
在 Python 的 os 模块中,可以使用以下常用函数来管理环境变量:
os.environ:获取当前进程的所有环境变量,返回一个字典。
os.getenv:获取指定名称的环境变量,如果不存在则返回 None。
os.putenv:设置指定名称的环境变量。
os.unsetenv:删除指定名称的环境变量。
下面是一些示例代码:
获取所有环境变量并打印出来:
import os
for k, v in os.environ.items():
print("%s=%s" % (k, v))
获取指定名称的环境变量并打印出来:
import os
value = os.getenv("PATH")
if value:
print("PATH=%s" % value)
else:
print("PATH environment variable not set.")
设置一个新的环境变量并打印出来:
import os
os.putenv("MY_VAR", "Hello World")
value = os.getenv("MY_VAR")
print("MY_VAR=%s" % value)
删除一个环境变量并打印出来:
import os
os.environ["MY_VAR"] = "Hello World"
value = os.getenv("MY_VAR")
print("MY_VAR=%s" % value)
os.unsetenv("MY_VAR")
value = os.getenv("MY_VAR")
if value:
print("MY_VAR=%s" % value)
else:
print("MY_VAR environment variable not set.")
语法糖
Python 中有许多语法糖,这些语法糖可以让你的代码更简洁、易读。以下是一些常用的语法糖:
列表推导式:这是一种简洁的创建列表的方式,可以在一行代码中完成循环、过滤和转换的操作。示例:
# 列表推导式:首先用[]盖住,for前面为循环内部的方法,之后append在list里面,结果放左边
list = [random.randint(0,100) for i in range(10)]
"""
该方法等价于
list = []
for i in range(10):
list.append(random.ranint(0,100))
"""
print(list)
字典推导式:这是一种简洁的创建字典的方式,可以在一行代码中完成循环、过滤和转换的操作。示例:
# 集合推导式:首先用{}盖住,for前面为循环内部的方法,之后add在list里面,写法与列表推导式一致
dic_list = {random.randint(0,100) for i in range(10)}
"""
该方法等价于
dic_list = []
for i in range(10):
dic_list.add(random.ranint(0,100))
"""
print(dic_list)
集合推导式:这是一种简洁的创建集合的方式,可以在一行代码中完成循环、过滤和转换的操作。示例:
# 字典推导式:首先用{}盖住,for前面为循环内部的方法,之后add在dic里面,写法与集合推导式几乎一致,只是多了个索引加个冒号
dic = {i:random.randint(0,100) for i in range(10)}
print(dic)
元组拆包:这是一种简洁的将元组中的元素赋值给变量的方式,可以在一行代码中完成多个赋值的操作。示例:
x, y = (1, 2)
print(x) # 1
print(y) # 2
三元表达式:这是一种简洁的条件表达式,它通常比if有更强的性能,可以在一行代码中完成条件判断和赋值的操作。示例:
x = 10
y = 20
z = 30
f = 50
maxvalue = x if x > y else y # 三元表达式,判断的结果放左边
"""
该方法等价于
maxvalue = 0
if x > y:
maxvalue = x
else:
maxvalue = y
"""
# 也可以像这样子套娃
maxvalue_2 = x if x > y and x > z and x > f else y if y > x and y > z and y > f else z if z > x and z > y and z > f else f
print(maxvalue)
print(maxvalue_2)
# 也可以不加if,用`and`和`or`输出结果
i = 1
j = i == 1 and "是" or "否"
print(j)
# 这种方式也可以套娃
i = 3
j = i == 1 and "是" or i == 2 and "是" or i == 3 and "是" or "否"
print(j)
try-else语句:用于在try语句成功后执行特定代码。
try:
print("运行i = 2/1,此时try运行成功")
i = 2/1
# print("运行i = 2/0,此时try运行失败")
# i = 2/0
except:
print("当try运行失败,except会被运行,此时else是不会被运行的")
else:
print("当try成功运行后,else才会被运行")
with语句:这是一种简洁的打开和关闭文件、锁定资源等操作的方式,可以避免手动关闭文件或释放资源导致的错误。示例:
with open("file.txt") as f:
data = f.read()
print(data)
lambda表达式:这是一种简洁的创建匿名函数的方式,可以在一行代码中完成函数定义和调用的操作。示例:
add = lambda x, y: x + y
result = add(1, 2)
print(result)
函数参数默认值:这是一种简洁的为函数参数设置默认值的方式,可以避免额外的判断和错误。示例:
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
greet("John")
greet("Jane", "Hi")
内置函数
Python 有很多内置函数,这些函数可以直接使用,不需要导入额外的模块。常用的内置函数包括:
print()
:用于输出信息到控制台。
print("hello world")
len()
:用于返回序列(如字符串、列表、元组)的长度。
list1 = [1, 2, 3]
print(len(list1))
type()
:用于返回对象的类型。
list1 = [1, 2, 3]
print(type(list1))
int()
、float()
、str()
:用于将其他类型转换为整数、浮点数、字符串。
string = '1'
print(int(string))
integer = 1
print(float(integer))
print(str(integer))
list()
:将其他类型转换为列表。
tup = (1, 2, 4)
print(list(tup))
min()
、max()
:用于返回序列中的最小/最大值。
list1 = [1, 2, 3]
print(min(list1))
print(max(list1))
all()
:用于判断列表(元组也行)中的所有元素是否都为 True,如果是返回 True,否则返回 False。
>>> all(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0
True
>>> all(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素
False
>>> all([0, 1,2, 3]) # 列表list,存在一个为0的元素
False
>>> all(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0
True
>>> all(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素
False
>>> all((0, 1, 2, 3)) # 元组tuple,存在一个为0的元素
False
>>> all([]) # 空列表
True
>>> all(()) # 空元组
True
any()
:用于判断列表(元组也行)中的所有元素是否包含True,如果有一个为 True,则返回 True,如果都是False,则放回False。
>>>any(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0
True
>>> any(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素
True
>>> any([0, '', False]) # 列表list,元素全为0,'',false
False
>>> any(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0
True
>>> any(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素
True
>>> any((0, '', False)) # 元组tuple,元素全为0,'',false
False
>>> any([]) # 空列表
False
>>> any(()) # 空元组
False
round()
:用于对浮点数进行四舍五入。
number = 3.1415926535
print(round(number, 3))
sum()
:用于对序列中的所有元素求和。
list1 = [1, 2, 3]
print(sum(list1))
sorted()
:用于对序列进行排序。
list1 = [1, 6, 3, 8, 5]
print(sorted(list1))
abs()
:用于返回数字的绝对值。
num = -1
print(abs(num))
num = 1
print(abs(num))
range()
:用于生成一个整数序列。
print(range(3))
# range(0, 3)
print(list(range(3))) # 需要转化成list才可以看得更加直观
# [0, 1, 2]
print(list(range(1, 3)))
# [1, 2]