type
Post
status
Published
summary
本文整理了一些python基础知识点,数据类型,函数,文件操作、常用函数和模块,以及一些易混淆的知识点;为了方便查阅和复习使用。
slug
date
Apr 15, 2020
tags
python基础
category
基础知识
password
icon
URL
Property
Apr 19, 2023 12:52 PM
一、数据类型
1.1、字符串
- 可以在字符串中使用
\
(反斜杠)来表示转义,也就是说\
后面的字符不再是它原来的意义,例如:\n
不是代表反斜杠和字符n,而是表示换行;而\t
也不是代表反斜杠和字符t,而是表示制表符。所以如果想在字符串中表示'
要写成\'
,同理想表示\
要写成\\
。
- 如果不希望字符串中的
\
表示转义,我们可以通过在字符串的最前面加上字母r
来加以说明,如:s1 = r'\'hello, world!\''
前缀 r 和 f 可以一起使用
- Python为字符串类型提供了非常丰富的运算符,我们可以使用
+
运算符来实现字符串的拼接,可以使用*
运算符来重复一个字符串的内容,可使用in
和not in
来判断一个字符串是否包含另外一个字符串(成员运算),我们也可以用[]
和[:]
运算符从字符串取出某个字符或某些字符(切片运算)
- 格式化输出字符串:占位符
a, b = 5, 10
print(f'{a} * {b} = {a * b}')
python3.6之后的写法print('%d * %d = %d' % (a, b, a * b))
print('{0} * {1} = {2}'.format(a, b, a * b))
- 在Python中,我们还可以通过一系列的方法来完成对字符串的处理:
str1 = 'hello, world!' print(len(str1)) # 13 # 通过内置函数len计算字符串的长度 print(str1.capitalize()) # Hello, world! # 获得字符串首字母大写的拷贝 print(str1.title()) # Hello, World! # 获得字符串每个单词首字母大写的拷贝 print(str1.upper()) # HELLO, WORLD! # 获得字符串变大写后的拷贝 print(str1.find('or')) # 8 # 从字符串中查找子串所在位置,找不到返回-1 print(str1.find('shit')) # -1 print(str1.index('or')) # 与find类似但找不到子串时会引发异常 print(str1.index('shit')) # ValueError: substring not found print(str1.startswith('He')) # False # 检查字符串是否以指定的字符串开头,会区分大小写 print(str1.startswith('hel')) # True print(str1.endswith('!')) # True # 检查字符串是否以指定的字符串结尾 print(str1.center(50, '*')) # 将字符串以指定的宽度居中并在两侧填充指定的字符 print(str1.rjust(50, ' ')) # 将字符串以指定的宽度靠右放置左侧填充指定的字符 str2 = 'abc123456' print(str2.isdigit()) # False # 检查字符串是否只由数字构成 print(str2.isalpha()) # False # 检查字符串是否只以字母构成 print(str2.isalnum()) # True # 检查字符串是否以数字和字母构成 str3 = ' Jackfrued@126.com ' print(str3.strip()) # 修剪字符串两端的指定字符,默认是空格 print(str3.split()) # 按照指定字符切割字符串,python内置的函数只能使用单个分隔符 re.split('。|!|?','字符串1。文本?') # 用re模块可以一次使用多个分隔符 print(str3.lower()) # 转换字符串中所有大写字符为小写 print(str3.upper()) # 转换字符串中的小写字母为大写 print(str3.swapcase()) # 将字符串中大写转换为小写,小写转换为大写 print(str3.lstrip()) # 截掉字符串左边的空格或指定字符 print(str3.rstrip()) # 删除字符串末尾的空格或指定字符 print(str3.replace(old, new [, max])) # 将字符串中的old替换成new, 如果max指定,则替换不超过max次。 seq = '_'.join(seq) # 以指定字符串作为分隔符,将seq中所有的元素(的字符串表示)合并为一个新的字符串 # 占位符可以和以上方法一起使用 ['subject_%s'%i.lower() for i in data_.columns]
1.2、列表
- 列表(
list
),也是一种结构化的、非标量类型,它是值的有序序列,每个值都可以通过索引进行标识,定义列表可以将列表的元素放在[]
中,多个元素用,
进行分隔,可以使用for
循环对列表元素进行遍历,也可以使用[]
或[:]
运算符取出列表中的一个或多个元素。
- 列表生成式:
f = [x for x in range(1, 10)]
f = [x*2 for x in range(1, 10) if x>5]
f = [x*2 if x>5 else x for x in range(1, 10)]
f = [x + y for x in 'ABCDE' for y in '1234567']
f = [(name, sex) for name, sex in zip(list1, list2)]
list1 = [1, 3, 5, 7, 100] # 增 print(list1.append(200)) # [1, 3, 5, 7, 100, 200] # 在列表的最后追加元素 print(list1.insert(1, 400)) # [1, 400, 3, 5, 7, 100, 200] # 在索引1的位置插入元素 # 删 del list1[2] # 删除指定索引的元素 print(list1) # [1, 400, 5, 7, 100, 200] list.remove(5) # 移除列表中某个值的第一个匹配项 print(list1) # [1, 400, 7, 100, 200] print(list1.pop()) # 200 # 移除列表中的一个元素(默认最后一个元素), 并且返回该元素的值, 可以指定索引 # 查 print(list1[3]) # 100 # 取索引为3的元素 print(list1[-1]) # 100 # 取最后一个元素 print(list1[1:3]) # [400, 7] # 取一个区间(前开后闭:能取到1不能取到3) # 改 list1[1] = 'value' # 赋值 print(list1) # [1, 'value', 7, 100, 200] # 其他方法 list(seq) # 将其他seq转换为列表 len(list1) # 列表长度 min(list1) # 列表最小值 max(list1) # 列表最大值 list1.count(obj) # 统计某个元素在列表中出现的次数 list1.index(obj) # 从列表中找出某个值第一个匹配项的索引位置 list1.reverse() # 反转列表 list1.clear() # 清空列表元素 list1.sort(reverse=True) # 排序——直接在原列表上进行排序 list1 += [1000, 2000] # 合并两个列表 # 排序——不会修改原列表,返回新列表 list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry'] list2 = sorted(list1) # 根据首字母在字母表中的位置升序 print(list2) # ['apple', 'blueberry', 'internationalization', 'orange', 'zoo'] list3 = sorted(list1, reverse=True) # 根据首字母在字母表中的位置倒序 print(list3) # ['zoo', 'orange', 'internationalization', 'blueberry', 'apple'] list4 = sorted(list1, key=len) # 根据元素长度升序 print(list4) # ['zoo', 'apple', 'orange', 'blueberry', 'internationalization'] # 列表反转 # 方法0:list1.reverse() # 方法1:list(reversed(a)),reversed(a)返回的是迭代器,所以前面加个list转换为list # 方法2:sorted(a,reverse=True) # 方法3:a[: :-1],其中[::-1]代表从后向前取值,每次步进值为1 # b = a[i:j:s];i是起点,j是终点,s是步长 # 当s<0,且i缺省时,则a默认为-1. # 当s<0,且j缺省时,默认为-len(a)-1 # 所以a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍,即倒序。
1.3、元组
Python中的元组与列表类似也是一种容器数据类型,可以用一个变量(对象)来存储多个数据,不同之处在于元组的元素不能修改
这里有一个非常值得探讨的问题,我们已经有了列表这种数据结构,为什么还需要元组这样的类型呢?
- 元组中的元素是无法修改的,事实上我们在项目中尤其是多线程环境(后面会讲到)中可能更喜欢使用的是那些不变对象(一方面因为对象状态不能修改,所以可以避免由此引起的不必要的程序错误,简单的说就是一个不变的对象要比可变的对象更加容易维护;另一方面因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以方便的被共享访问)。所以结论就是:如果不需要对元素进行添加、删除、修改的时候,可以考虑使用元组,当然如果一个方法要返回多个值,使用元组也是不错的选择。
- 元组在创建时间和占用的空间上面都优于列表。我们可以使用sys模块的getsizeof函数来检查存储同样的元素的元组和列表各自占用了多少内存空间,这个很容易做到。我们也可以在ipython中使用魔法指令%timeit来分析创建同样内容的元组和列表所花费的时间,
1.4、集合
Python中的集合跟数学上的集合是一致的,不允许有重复元素,而且可以进行交集、并集、差集、补集等运算。

# 创建集合的字面量语法 set1 = {1, 2, 3, 3, 3, 2} print(set1) print('Length =', len(set1)) # 创建集合的构造器语法(面向对象部分会进行详细讲解) set2 = set(range(1, 10)) set3 = set((1, 2, 3, 3, 2, 1)) print(set2, set3) # 创建集合的推导式语法(推导式也可以用于推导集合) set4 = {num for num in range(1, 100) if num % 3 == 0 or num % 5 == 0} print(set4) set1.add(4) set1.add(5) set2.update([11, 12]) set2.discard(5) if 4 in set2: set2.remove(4) print(set1, set2) print(set3.pop()) print(set3) # 集合的交集、并集、差集、对称差运算 print(set1 & set2) # print(set1.intersection(set2)) print(set1 | set2) # print(set1.union(set2)) print(set1 - set2) # print(set1.difference(set2)) print(set1 ^ set2) # print(set1.symmetric_difference(set2)) # 判断子集和超集 print(set2 <= set1) # print(set2.issubset(set1)) print(set3 <= set1) # print(set3.issubset(set1)) print(set1 >= set2) # print(set1.issuperset(set2)) print(set1 >= set3) # print(set1.issuperset(set3)) .argsort() # 返回数组值从小到大的索引值 [::-1] # 倒序取值
1.5、字典
Python中的字典跟我们生活中使用的字典是一样一样的,它可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。
# 创建字典的字面量语法 scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82} print(scores) # 创建字典的构造器语法 items1 = dict(one=1, two=2, three=3, four=4) # 通过zip函数将两个序列压成字典 items2 = dict(zip(['a', 'b', 'c'], '123')) # 创建字典的推导式语法 items3 = {num: num ** 2 for num in range(1, 10)} # 更新字典中的元素 scores['白元芳'] = 65 scores['诸葛王朗'] = 71 scores.update(冷面=67, 方启鹤=85) print(scores.get('武则天')) # get获取对应key的value,原字典中元素不变 print (scores.get('武则天', 0.0)) # 没有设置 Salary,输出默认的值 0.0 # 删除字典中的元素 print(scores.popitem()) # 取出最后一个元素,原字典中元素变少,取出来的数据以元组的形式存在 print(scores.pop('骆昊', 100)) # 取出指定key值对应的value,原字典中元素变少 # 清空字典 scores.clear() print(scores)
1.6、json
将python类型数据转换成json
dict1 = {} dict2 = {} json.dumps([dict1, dict2]) '[{}, {}]'
将json转换成python数据类型
json.loads(json.dumps([dict1, dict2])) [{}, {}] load函数可以处理的json形状: 1、json中只有一个字典的情况:'{}' 2、json中只有多个字典的情况: '[{},{},{},{}]'
二、模块/函数
2.1、zip 函数
- 传入一个列表时,zip函数会将这个列表内每个元素单独构成元组,返回由这些元组组成的列表。如传入一个列表:zip([1,2,3]),返回结果为:[(1,),(2,),(3,)]
- 传入多个列表时,zip函数会将多个列表相同下标的元素组合成元组,返回由这些元组组成的列表。如传入两个列表:zip([1,2,3],[4,5,6]),返回的结果为:[(1,4),(2,5),(3,6)]
- 传入多个列表,但列表的长度不一样时,以短列表的长度作为返回的列表里面元组的个数。如传入不同长度的列表:zip([1,2],[3,4,5]),返回值是:[(1,3),(2,4)]
- 传入一个二维的数据类型:zip(*[[1,2],[3,4]]),返回的结果为:[(1,3),(2,4)]。*表示处理二维或多维数据
2.2、chain 函数
chain 函数它将所有可迭代对象组合在一起,并生成一个可迭代对象作为输出。
当输入只有一个参数,但参数是一个二维的可迭代对象是前面加个星号(*)*表示处理二维或多维数据
常规用法
from itertools import chain list1 = ["Tom", "Jack", "Will", "July"] list2 = ["man", "man", "man", "woman"] for x in chain(list1, list2, zip(list1, list2)): print(x) Tom Jack Will July man man man woman ('Tom', 'man') ('Jack', 'man') ('Will', 'man') ('July', 'woman')
一个参数不带*
from itertools import chain list1 = ["Tom", "Jack", "Will", "July",["man", "man", "man", "woman"]] for x in chain(list1): print(x) Tom Jack Will July ['man', 'man', 'man', 'woman']
一个参数带*
from itertools import chain list1 = ["Tom", "Jack", "Will", "July",["man", "man", "man", "woman"]] for x in chain(*list1): print(x) T o m J a c k W i l l J u l y man man man woman
2.3、itertools 模块
import itertools # 产生ABCD的全排列 itertools.permutations('ABCD') # 产生ABCDE的五选三组合 itertools.combinations('ABCDE', 3) # 产生ABCD和123的笛卡尔积 itertools.product('ABCD', '123') # 产生ABC的无限循环序列 itertools.cycle(('A', 'B', 'C'))
2.4、sorted 函数
sorted() 函数对所有可迭代的对象进行排序操作。
sorted(iterable, key=None, reverse=False)
参数说明:
- iterable -- 可迭代对象。
- key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
# 指定key进行排序 >>>example_list = [5, 0, 6, 1, 2, 7, 3, 4] >>> result_list = sorted(example_list, key=lambda x: x*-1) # 将原列表中的元素都乘以-1,然后进行升序 >>> print(result_list) [7, 6, 5, 4, 3, 2, 1, 0]
你也可以使用 list 的 list.sort() 方法
另一个区别在于list.sort() 方法只为 list 定义。而 sorted() 函数可以接收任何的 iterable。
示例:
all_lines = ' '.join(list(train_df['text'])) word_count = Counter(all_lines.split(' ')) # 返回的数据是Counter类型的字典 print(word_count) """ Counter({'3750': 3702, '648': 2423, '900': 1602, '3370': 980, '4464': 816, '6122': 790, '4939': 724, '7399': 686, '3659': 614}) """ print(word_count.items()) """ dict_items([('2967', 63), ('6758', 23), ('339', 1), ('2021', 42), ('1854', 78), ('3731', 35), ('4109', 142), ('3792', 79)]) """ word_count = sorted(word_count.items(),key=lambda x: x[1],reverse=True) # word_count.items()将字典变成元组,key是指定用元组里的第二个值作为比较来机型排序,reverse=True是降序,默认是False升序 print(word_count) """ [('3750', 3702), ('648', 2423), ('900', 1602), ('3370', 980), ('4464', 816), ('6122', 790), ('4939', 724), ('7399', 686)] """
三、类和对象
简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。
3.1、定义类
在Python中可以使用
class
关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,代码如下所示。说明:写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。
class Student(object): # __init__是一个特殊方法用于在创建对象时进行初始化操作 # 通过这个方法我们可以为学生对象绑定name和age两个属性 def __init__(self, name, age): self.name = name self.age = age def study(self, course_name): print('%s正在学习%s.' % (self.name, course_name)) # PEP 8要求标识符的名字用全小写多个单词用下划线连接 # 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识) def watch_movie(self): if self.age < 18: print('%s只能观看《熊出没》.' % self.name) else: print('%s正在观看岛国爱情大电影.' % self.name)
3.2、创建和使用对象
def main(): # 创建学生对象并指定姓名和年龄 stu1 = Student('骆昊', 38) # 给对象发study消息 stu1.study('Python程序设计') # 给对象发watch_av消息 stu1.watch_movie() stu2 = Student('王大锤', 15) stu2.study('思想品德') stu2.watch_movie() if __name__ == '__main__': main()
3.3、类的方法
3.3.1、魔法方法
__init__: 用于在创建对象时进行初始化操作 __str__: 如果类中定义了这个方法,则在print(类名)时,打印出来的内容是__str__方法return的内容 __slots__: 限定类的对象只能绑定_name, _age和_gender属性 __slots__ = ('_name', '_age', '_gender')
3.3.2、实例方法
类的实例方法由实例调用,至少包含一个self参数,且为第一个参数。执行实例方法时,会自动将调用该方法的实例赋值给self。
self
代表的是类的实例,而非类本身。self
不是关键字,而是Python约定成俗的命名3.3.3、静态方法
实际上,我们写在类中的方法并不需要都是对象方法,例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。
静态方法由类调用,无默认参数。将实例方法参数中的self去掉,然后在方法定义上方加上@staticmethod,就成为静态方法。它属于类,和实例无关。建议只使用类名.静态方法的调用方式。
from math import sqrt class Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c @staticmethod def is_valid(a, b, c): return a + b > c and b + c > a and a + c > b def perimeter(self): return self._a + self._b + self._c def area(self): half = self.perimeter() / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main(): a, b, c = 3, 4, 5 # 静态方法和类方法都是通过给类发消息来调用的 if Triangle.is_valid(a, b, c): t = Triangle(a, b, c) print(t.perimeter()) # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数 # print(Triangle.perimeter(t)) print(t.area()) # print(Triangle.area(t)) else: print('无法构成三角形.') if __name__ == '__main__': main()
3.3.4、类方法
类方法由类调用,采用@classmethod装饰,至少传入一个cls(代指类本身,类似self)参数,通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象。执行类方法时,自动将调用该方法的类赋值给cls(相当于是类调用了自己)。建议只使用类名.类方法的调用方式。
python装饰器:理解 Python 装饰器看这一篇就够了
from time import time, localtime, sleep class Clock(object): """数字时钟""" def __init__(self, hour=0, minute=0, second=0): self._hour = hour self._minute = minute self._second = second @classmethod def now(cls): ctime = localtime(time()) return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec) def run(self): """走字""" self._second += 1 if self._second == 60: self._second = 0 self._minute += 1 if self._minute == 60: self._minute = 0 self._hour += 1 if self._hour == 24: self._hour = 0 def show(self): """显示时间""" return '%02d:%02d:%02d' % \ (self._hour, self._minute, self._second) def main(): # 通过类方法创建对象并获取系统时间 clock = Clock.now() while True: print(clock.show()) sleep(1) clock.run() if __name__ == '__main__': main()
3.4、类的封装、继承和多态
面向对象有三大支柱:封装、继承和多态。
简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。
- is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
- has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
- use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。
封装
"隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口"
我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。
继承
可以在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则
class Person(object): """人""" def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age @age.setter def age(self, age): self._age = age def play(self): print('%s正在愉快的玩耍.' % self._name) def watch_av(self): if self._age >= 18: print('%s正在观看爱情动作片.' % self._name) else: print('%s只能观看《熊出没》.' % self._name) class Student(Person): """学生""" def __init__(self, name, age, grade): super().__init__(name, age) self._grade = grade @property def grade(self): return self._grade @grade.setter def grade(self, grade): self._grade = grade def study(self, course): print('%s的%s正在学习%s.' % (self._grade, self._name, course)) class Teacher(Person): """老师""" def __init__(self, name, age, title): super().__init__(name, age) self._title = title @property def title(self): return self._title @title.setter def title(self, title): self._title = title def teach(self, course): print('%s%s正在讲%s.' % (self._name, self._title, course)) def main(): stu = Student('王大锤', 15, '初三') stu.study('数学') stu.watch_av() t = Teacher('骆昊', 38, '砖家') t.teach('Python程序设计') t.watch_av() if __name__ == '__main__': main()
多态
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)
from abc import ABCMeta, abstractmethod class Pet(object, metaclass=ABCMeta): """宠物""" def __init__(self, nickname): self._nickname = nickname @abstractmethod def make_voice(self): """发出声音""" pass class Dog(Pet): """狗""" def make_voice(self): print('%s: 汪汪汪...' % self._nickname) class Cat(Pet): """猫""" def make_voice(self): print('%s: 喵...喵...' % self._nickname) def main(): pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')] for pet in pets: pet.make_voice() if __name__ == '__main__': main()
四、文件/异常
4.1、文件读写的两个问题
打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加)
- 文件类型:t(文本类型)、b(二进制类型)
- 操作模式:r(读)、w(写)、a(追加)、+(更新(可读可写))
- 以上两种可以相互组合:(r、w、a默认是操作文本文件t的,所以下面t被省略了)
- r, r+, rb, rb+
- w, w+, wb, wb+
- a, a+, ab, ab+
- 多种模式的区别对比
模式 | r | r+ | w | w+ | a | a+ |
写文件 | ㅤ | ✓ | ✓ | ✓ | ✓ | ✓ |
读文件 | ✓ | ✓ | ㅤ | ✓(有坑,详见下文) | ㅤ | ✓(有坑,详见下文) |
创建文件 | ㅤ | ㅤ | ✓ | ✓ | ✓ | ✓ |
覆盖文件 | ㅤ | ㅤ | ✓ | ✓ | ㅤ | ㅤ |
r+ | 读写模式 | 能写,打开不存在的文件会报错;新写入的内容会覆盖原文件中的内容,写入几个字符,则覆盖几个字符 |
w+ | 写读模式 | 能读,但是读不到内容,因为w先把文件内容清空了 |
a+ | 追加读模式 | 能读,但读不到内容,因为文件指针默认在最后一行,可用seek移动文件指针位置;只针对读取文件,写文件还是只能从最后开始写 |
f=open('test.txt','a+') f.seek(5) #此处的seek不起作用,因为对写文件不起作用 res=f.write('hh\n') f.seek(2) #从下标是2的字符开始读取文件 res1=f.read() print(res1)
4.2、文件读写的两种方式
需要写入,直接将参数
'r'
改为'w'
,追加改为'a'
4.2.1、直接读写
f = open('致橡树.txt', 'r', encoding='utf-8') content = f.read() f.close() # 关闭打开的文件,释放掉程序中获取的外部资源
4.2.2、with关键字
# with关键字指定文件对象的上下文环境并在离开上下文环境时自动释放文件资源 with open('致橡树.txt', 'r', encoding='utf-8') as f: content = f.read()
4.2.3、按行读取
除了使用文件对象的
read
方法读取文件之外,还可以使用for-in
循环逐行读取或者用readlines
方法将文件按行读取到一个列表容器中import time def main(): # 一次性读取整个文件内容 with open('致橡树.txt', 'r', encoding='utf-8') as f: print(f.read()) # 通过for-in循环逐行读取 with open('致橡树.txt', mode='r') as f: for line in f: print(line, end='') time.sleep(0.5) print() # 读取文件按行读取到列表中 with open('致橡树.txt') as f: lines = f.readlines() print(lines) if __name__ == '__main__': main()
4.3、异常捕获
在Python中,我们可以将那些在运行时可能会出现状况的代码放在
try
代码块中,在try
代码块的后面可以跟上一个或多个except
来捕获可能出现的异常状况。例如在上面读取文件的过程中,文件找不到会引发FileNotFoundError
,指定了未知的编码会引发LookupError
,而如果读取文件时无法按指定方式解码会引发UnicodeDecodeError
,我们在try
后面跟上了三个except
分别处理这三种不同的异常状况。最后我们使用finally
代码块来关闭打开的文件,释放掉程序中获取的外部资源,由于finally
块的代码不论程序正常还是异常都会执行到(甚至是调用了sys
模块的exit
函数退出Python环境,finally
块都会被执行,因为exit
函数实质上是引发了SystemExit
异常),因此我们通常把finally
块称为“总是执行代码块”,它最适合用来做释放外部资源的操作。def main(): try: with open('致橡树.txt', 'r', encoding='utf-8') as f: print(f.read()) except FileNotFoundError: print('无法打开指定的文件!') except LookupError: print('指定了未知的编码!') except UnicodeDecodeError: print('读取文件时解码错误!') if __name__ == '__main__': main()
4.4、读写文本文件
读取文本文件时,需要在使用
open
函数时指定好带路径的文件名(可以使用相对路径或绝对路径)并将文件模式设置为'r'
(如果不指定,默认值也是'r'
),然后通过encoding
参数指定编码(如果不指定,默认值是None,那么在读取文件时使用的是操作系统默认的编码),如果不能保证保存文件时使用的编码方式与encoding参数指定的编码方式是一致的,那么就可能因无法解码字符而导致读取失败。from math import sqrt def is_prime(n): """判断素数的函数""" assert n > 0 for factor in range(2, int(sqrt(n)) + 1): if n % factor == 0: return False return True if n != 1 else False def main(): filenames = ('a.txt', 'b.txt', 'c.txt') fs_list = [] try: for filename in filenames: fs_list.append(open(filename, 'w', encoding='utf-8')) for number in range(1, 10000): if is_prime(number): if number < 100: fs_list[0].write(str(number) + '\n') elif number < 1000: fs_list[1].write(str(number) + '\n') else: fs_list[2].write(str(number) + '\n') except IOError as ex: print(ex) print('写文件时发生错误!') finally: for fs in fs_list: fs.close() print('操作完成!') if __name__ == '__main__': main()
4.5、读写二进制文件
def main(): try: with open('guido.jpg', 'rb') as fs1: data = fs1.read() print(type(data)) # <class 'bytes'> with open('吉多.jpg', 'wb') as fs2: fs2.write(data) except FileNotFoundError as e: print('指定的文件无法打开.') except IOError as e: print('读写文件时出现错误.') print('程序执行结束.') if __name__ == '__main__': main()
4.6、读写JSON文件
使用Python中的json模块就可以将字典或列表以JSON格式保存到文件中
import json def main(): mydict = { 'name': '骆昊', 'age': 38, 'qq': 957658, 'friends': ['王大锤', '白元芳'], 'cars': [ {'brand': 'BYD', 'max_speed': 180}, {'brand': 'Audi', 'max_speed': 280}, {'brand': 'Benz', 'max_speed': 320} ] } try: with open('data.json', 'w', encoding='utf-8') as fs: json.dump(mydict, fs) except IOError as e: print(e) print('保存数据完成!') if __name__ == '__main__': main()
json模块主要有四个比较重要的函数,分别是:
dump
- 将Python对象按照JSON格式序列化到文件中
dumps
- 将Python对象处理成JSON格式的字符串
load
- 将文件中的JSON数据反序列化成对象
loads
- 将字符串的内容反序列化成Python对象
五、使用经验
5.1、函数传参
单星号(*):*agrs;将所有参数以元组(tuple)的形式导入:
def foo(param1, *param2): print (param1) print (param2) foo(1,2,3,4,5) # 以上代码输出结果为: 1 (2, 3, 4, 5)
单星号的另一个用法是解压参数列表:
def foo(bar, lee): print bar, lee l = [1, 2] foo(*l) 1 2
双星号(**):**kwargs;双星号(**)将参数以字典的形式导入
def bar(param1, **param2): print (param1) print (param2) bar(1,a=2,b=3) # 以上代码输出结果为: 1 {'a': 2, 'b': 3}
单星号和双星号一起使用:
def foo(a, b=10, *args, **kwargs): print (a) print (b) print (args) print (kwargs) foo(1, 2, 3, 4, e=5, f=6, g=7) # 以上代码输出结果为: 1 2 (3, 4) {'e': 5, 'f': 6, 'g': 7}
5.2、其他
# python取整 int(-0.8) # 取整数部分 round(-0.4) # 四舍五入 math.floor(-0.8) # 向下取整 math.ceil(-0.8) # 向上取整 # 除法 / # 不管式子中的是int还是flot,结果返回小数 // # 向下取整。式子中都为int时返回int型;式子中有flot时返回flot型 % # 返回余数。式子中都为int时返回int型;式子中有flot时返回flot型
- 作者:AnJhon
- 链接:https://www.anjhon.top/article/2024569c-1091-499a-8fb6-f809744ad20c
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。