python总结
字符串
字符串属于不可变类型,对字符串的操作会产生新的字符串,原来的值并没有发生变化
字符串的运算
+
字符串的拼接*
重复字符串内容in
或not in
判断一个字符串中是否包含另一个字符串[]
和[:]
运算符从字符串取出某个字符或某些字符。
索引和切片
字符串的索引和切片操作跟列表、元组几乎没有区别,因为字符串也是一种有序序列,可以通过正向或反向的整数索引访问其中的元素。但是有一点需要注意,因为字符串是不可变类型,所以不能通过索引运算修改字符串中的字符。
s = 'abc123456'
n = len(s)
print(s[0], s[-n]) # a a
print(s[n-1], s[-1]) # 6 6
print(s[2], s[-7]) # c c
print(s[5], s[-4]) # 3 3
print(s[2:5]) # c12
print(s[-7:-4]) # c12
print(s[2:]) # c123456
print(s[:2]) # ab
print(s[::2]) # ac246
print(s[::-1]) # 654321cba
字符串的方法
s1 = 'hello, world!'
# 字符串首字母大写
print(s1.capitalize()) # Hello, world!
# 字符串每个单词首字母大写
print(s1.title()) # Hello, World!
# 字符串变大写
print(s1.upper()) # HELLO, WORLD!
s2 = 'GOODBYE'
# 字符串变小写
print(s2.lower()) # goodbye
# 检查s1和s2的值
print(s1) # hello, world
print(s2) # GOODBYE
```## 字符串
字符串属于不可变类型,对字符串的操作会产生新的字符串,原来的值并没有发生变化
### 字符串的运算
1. `+` 字符串的拼接
2. `*` 重复字符串内容
3. `in` 或 `not in` 判断一个字符串中是否包含另一个字符串
4. `[]`和`[:]`运算符从字符串取出某个字符或某些字符。
### 索引和切片
字符串的索引和切片操作跟列表、元组几乎没有区别,因为字符串也是一种有序序列,可以通过正向或反向的整数索引访问其中的元素。但是有一点需要注意,因为**字符串是不可变类型**,所以**不能通过索引运算修改字符串中的字符**。
```python
s = 'abc123456'
n = len(s)
print(s[0], s[-n]) # a a
print(s[n-1], s[-1]) # 6 6
print(s[2], s[-7]) # c c
print(s[5], s[-4]) # 3 3
print(s[2:5]) # c12
print(s[-7:-4]) # c12
print(s[2:]) # c123456
print(s[:2]) # ab
print(s[::2]) # ac246
print(s[::-1]) # 654321cba
字符串的方法
s1 = 'hello, world!'
# 字符串首字母大写
print(s1.capitalize()) # Hello, world!
# 字符串每个单词首字母大写
print(s1.title()) # Hello, World!
# 字符串变大写
print(s1.upper()) # HELLO, WORLD!
s2 = 'GOODBYE'
# 字符串变小写
print(s2.lower()) # goodbye
# 检查s1和s2的值
print(s1) # hello, world
print(s2) # GOODBYE
列表
列表是由一系列元素按特定顺序构成的数据序列,一个列表类型的变量,可以用来保存多个数据,可以使用[]
定义列表,列表中多个元素使用逗号分隔。
列表中可以包含重复元素,也可以包含不同类型的数据(但是不建议)
items3 = [100, 12.3, 'Python', True]
可以使用Python内置的list()
函数将其他序列变成列表。准确的说,list并不是一个普通的函数,而是创建列表的构造器。
items4 = list(range(1, 10))
items5 = list('hello')
print(items4) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(items5) # ['h', 'e', 'l', 'l', 'o']
列表运算符
-
+
两个列表的拼接,直接追加在列表尾部 -
*
实现列表的重复运算,将列表元素重复指定次数print(items6 * 3) # [45, 58, 29, 45, 58, 29, 45, 58, 29]
-
可以使用
in
或者not in
运算符判断一个元素在不在列表中 -
列表元素获取
[N - 1]
可以访问最后一个元素对于反向索引,
[-1]
可以访问列表中的最后一个元素,[-N]
可以访问第一个元素 -
如果希望一次性访问列表中的多个元素,我们可以使用切片运算。切片运算是形如
[start:end:stride]
的运算符,其中start
代表访问列表元素的起始位置,end
代表访问列表元素的终止位置(终止位置的元素无法访问),而stride
则代表了跨度,简单的说就是位置的增量,
import random
counters = [0] * 6
# 模拟掷色子记录每种点数出现的次数
for _ in range(6000):
face = random.randrange(1, 7)
counters[face - 1] += 1
# 输出每种点数出现的次数
for face in range(1, 7):
print(f'{face}点出现了{counters[face - 1]}次')
列表常用方法
-
添加和删除元素
-
添加
languages = ['Python', 'Java', 'C++'] languages.append('JavaScript') # 向列表中追加元素 languages.insert(1, 'SQL') # 向列表的指定位置插入元素
-
删除
languages = ['Python', 'SQL', 'Java', 'C++', 'JavaScript'] if 'Java' in languages: languages.remove('Java') # 从列表中删除指定元素 若出现多个该元素默认删除第一个 languages.pop() # 删除列表的最后一个元素 会返回被删除的元素 temp = languages.pop(1) # 删除指定位置元素 languages.clear() # 清空列表
-
-
元素位置与频次
items = ['Python', 'Java', 'Java', 'C++', 'Kotlin', 'Python'] print(items.index('Python')) # 0 print(items.index('Python', 1)) # 5 从索引位置1开始查找'Python' 差不到会报错。ValueError print(items.count('Python')) # 2 统计元素出现的频率
-
元素排序和反转
items = ['Python', 'Java', 'C++', 'Kotlin', 'Swift'] items.sort() # 排序 items.reverse() # 反转
-
列表生成式
items = [i for i in range(1, 100) if i % 3 == 0 or i % 5 == 0] print(items)
nums1 = [35, 12, 97, 64, 55] nums2 = [num ** 2 for num in nums1] print(nums2)
元组 tuple
元组是有序的序列,是不可变的,如果视图将元组中的元素修改会引发TypeError
错误, 所以不支持增删改等操作
元组类型支持的运算符跟列表是一样的
注意:
()
表示空元组- 如果元组中只有一个元素,需要加上一个逗号。
打包和解包操作
把多个用逗号分隔的值赋给一个变量时,多个值会打包成一个元组类型;
把一个元组赋值给多个变量时,元组会解包成多个值然后分别赋给对应的变量
# 打包操作
a = 1, 10, 100
print(type(a)) # <class 'tuple'>
print(a) # (1, 10, 100)
# 解包操作
i, j, k = a
print(i, j, k) # 1 10 100
元组和列表的比较
- 元组属于不可变类型,不可变类型更适合多线程环境,因为降低了并发访问变量的同步化开销
- 通常不可变类型在创建时间上优于对应的可变类型,
集合
集合需要满足以下要求:
-
无序性:一个集合中,每个元素的地位都是相同的,元素之间是无序的 不支持索引运算
-
互异性:不能存在相同的元素
-
确定性::给定一个集合和一个任意元素,该元素要么属这个集合,要么不属于这个集合,二者必居其一,不允许有模棱两可的情况出现。
支持
in
和not in
运算
说明:集合底层使用了哈希存储(散列存储)
创建集合
- 使用
{}
创建集合,{}
中至少有一个元素,否则就会认为是创建的空字典 - 使用
set()
函数创建set('hello')
集合中的元素必须是
hashable
类型,所谓hashable
类型指的是能够计算出哈希码的数据类型,通常不可变类型都是hashable
类型,如整数(int
)、浮点小数(float
)、布尔值(bool
)、字符串(str
)、元组(tuple
)等。可变类型都不是hashable
类型,因为可变类型无法计算出确定的哈希码,所以它们不能放到集合中例如:列表
集合的遍历
可以使用len
函数来获得集合元素个数
使用 for - in
变量元素
集合的运算
Python 为集合类型提供了非常丰富的运算,主要包括:成员运算、交集运算、并集运算、差集运算、比较运算(相等性、子集、超集)等。
-
成员运算
in
和not in
检查元素是否存在集合中 -
二元运算
set1 = {1, 2, 3, 4, 5, 6, 7} set2 = {2, 4, 6, 8, 10} # 交集 print(set1 & set2) # {2, 4, 6} print(set1.intersection(set2)) # {2, 4, 6} # 并集 print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8, 10} print(set1.union(set2)) # {1, 2, 3, 4, 5, 6, 7, 8, 10} # 差集 print(set1 - set2) # {1, 3, 5, 7} print(set1.difference(set2)) # {1, 3, 5, 7} # 对称差 print(set1 ^ set2) # {1, 3, 5, 7, 8, 10} print(set1.symmetric_difference(set2)) # {1, 3, 5, 7, 8, 10}
集合的方法
set1 = {1, 10, 100}
# 添加元素
set1.add(1000)
set1.add(10000)
print(set1) # {1, 100, 1000, 10, 10000}
# 删除元素
temp = set1.pop() # 随机删除一个元素并返回被删除的元素
set1.discard(10)
if 100 in set1:
set1.remove(100)
print(set1) # {1, 1000, 10000}
# 清空元素
set1.clear()
print(set1) # set()
字典
存放键值对
创建
创建字典可以使用{}
,字典中的元素是以键值对的形式存在
也可以使用dict()
函数生成字典
# dict函数(构造器)中的每一组参数就是字典中的一组键值对
person = dict(name='王大锤', age=55, height=168, weight=60, addr='成都市武侯区科华北路62号1栋101')
使用字典
len()
查看字典中有多少键值对- 获取字典元素
get()
方式,若没有指定的键是不会产生异常,而是返回None - 获取字典中的所有键
keys()
- 获取字典中所有的值
values()
- 将键和值组装成二元组
items()
update()
两个字典合并;x
跟y
相同的键对应的值会被y
中的值更新,而y
中有但x
中没有的键值对会直接添加到x
中pop
或popitem
方法从字典中删除元素,前者会返回(获得)键对应的值,但是如果字典中不存在指定的键,会引发KeyError
错误;后者在删除元素时,会返回(获得)键和值组成的二元组- 字典的
clear
方法会清空字典中所有的键值对
字典运算
- 成员运算 判断指定的键是否在字典中
- 索引运算 可以通过键访问对应的值或者向字典中添加新的键值对
字典中的键必须是不可变类型:整数,浮点数,字符串 ,元组
不能是list或set
函数
函数是对功能
# 用星号表达式来表示args可以接收0个或任意多个参数
# 参数列表中的**kwargs可以接收0个或任意多个关键字参数
# 调用函数时传入的关键字参数会组装成一个字典(参数名是字典中的键,参数值是字典中的值)
# 如果一个关键字参数都没有传入,那么kwargs会是一个空字典
def foo(*args, **kwargs):
print(args)
print(kwargs)
foo(3, 2.1, True, name='骆昊', age=43, gpa=4.95)
标准库函数
函数 | 说明 |
---|---|
abs |
返回一个数的绝对值,例如:abs(-1.3) 会返回1.3 。 |
bin |
把一个整数转换成以'0b' 开头的二进制字符串,例如:bin(123) 会返回'0b1111011' 。 |
chr |
将Unicode编码转换成对应的字符,例如:chr(8364) 会返回'€' 。 |
hex |
将一个整数转换成以'0x' 开头的十六进制字符串,例如:hex(123) 会返回'0x7b' 。 |
input |
从输入中读取一行,返回读到的字符串。 |
len |
获取字符串、列表等的长度。 |
max |
返回多个参数或一个可迭代对象中的最大值,例如:max(12, 95, 37) 会返回95 。 |
min |
返回多个参数或一个可迭代对象中的最小值,例如:min(12, 95, 37) 会返回12 。 |
oct |
把一个整数转换成以'0o' 开头的八进制字符串,例如:oct(123) 会返回'0o173' 。 |
open |
打开一个文件并返回文件对象。 |
ord |
将字符转换成对应的Unicode编码,例如:ord('€') 会返回8364 。 |
pow |
求幂运算,例如:pow(2, 3) 会返回8 ;pow(2, 0.5) 会返回1.4142135623730951 。 |
print |
打印输出。 |
range |
构造一个范围序列,例如:range(100) 会产生0 到99 的整数序列。 |
round |
按照指定的精度对数值进行四舍五入,例如:round(1.23456, 4) 会返回1.2346 。 |
sum |
对一个序列中的项从左到右进行求和运算,例如:sum(range(1, 101)) 会返回5050 。 |
type |
返回对象的类型,例如:type(10) 会返回int ;而 type('hello') 会返回str 。 |
随机验证码
import random
import string
ALL_CHARS = string.digits + string.ascii_letters
def generate_code(*, code_len=4):
"""
生成指定长度的验证码
:param code_len: 验证码的长度(默认4个字符)
:return: 由大小写英文字母和数字构成的随机验证码字符串
"""
return ''.join(random.choices(ALL_CHARS, k=code_len))
函数高级应用
装饰器
用一个函数装饰另外一个函数并为其提供额外的能力
创建模板
def 装饰器函数名称(func):
def wrapper(*args, **kwargs): # 带有装饰功能的函数,会执行被装饰的函数func
# 执行原函数前执行的内容
result = func(*args, **kwargs)
# 执行原函数后执行的内容
return result
return wrapper
例如:记录时间的装饰器
import random
import time
def record_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__}执行时间: {end - start:.2f}秒')
return result
return wrapper
@record_time # 使用装饰器
def download(filename):
print(f'开始下载{filename}.')
time.sleep(random.random() * 6)
print(f'{filename}下载完成.')
@record_time
def upload(filename):
print(f'开始上传{filename}.')
time.sleep(random.random() * 8)
print(f'{filename}上传完成.')
download('MySQL从删库到跑路.avi')
upload('Python从入门到住院.pdf')
# 调用装饰后的函数会记录执行时间
download('MySQL从删库到跑路.avi')
upload('Python从入门到住院.pdf')
# __wrapped__ 取消装饰器的作用不记录执行时间
download.__wrapped__('MySQL必知必会.pdf')
upload.__wrapped__('Python从新手到大师.pdf')
面向对象编程
类是抽象的,对象是具体的
封装: 隐藏一切可以实现的细节,只向外界暴露简单的调用接口
继承:父类 也叫超类,基类;super().__init__()
来调用父类初始化方法
多态
约定:
class Student:
def __init__(self, name, age):
self.__name = name # 双下划线表示私有属性
self._age = age # 单下划线表示受保护属性
def study(self, course_name):
print(f'{self.__name}正在学习{course_name}.')
stu = Student('王大锤', 20)
stu.study('Python程序设计')
print(stu.__name) # AttributeError: 'Student' object has no attribute '__name'
动态属性
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('王大锤', 20)
stu.sex = '男' # 给学生对象动态添加sex属性
如果不希望在使用对象时动态的为对象添加属性,可以使用__slots__
魔法
class Student:
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('王大锤', 20)
# AttributeError: 'Student' object has no attribute 'sex'
stu.sex = '男'
静态方法和类方法
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
@classmethod
def create_equilateral(cls, side_length):
"""创建等边三角形的工厂方法"""
return cls(side_length, side_length, side_length)
@property
def perimeter(self):
"""计算周长"""
return self.a + self.b + self.c
@property
def area(self):
"""计算面积"""
p = self.perimeter / 2
return (p * (p - self.a) * (p - self.b) * (p - self.c)) ** 0.5
# 使用静态方法 `is_valid` 来检查给定的边长能否构成三角形
if Triangle.is_valid(3, 4, 5):
print("可以构成三角形")
else:
print("不能构成三角形")
# 使用类方法来创建等边三角形
equilateral_triangle = Triangle.create_equilateral(5)
print(f'等边三角形周长: {equilateral_triangle.perimeter}')
print(f'等边三角形面积: {equilateral_triangle.area}')
t = Triangle(3, 4, 5)
print(f'周长: {t.perimeter}')
print(f'面积: {t.area}')
可以直接使用类名.方法名
的方式调用静态方法和类方法
区别:
类方法的第一个参数是类对象本身
静态方法没有这个参数
抽象类定义
from abc import ABCMeta, abstractmethod
class Employee(metaclass=ABCMeta):
"""员工"""
def __init__(self, name):
self.name = name
@abstractmethod
def get_salary(self):
"""结算月薪"""
pass
抽象类是不能被实现的类,旨在为子类提供一套接口约定
作用和使用场景
- 定义接口:
@abstractmethod
用于定义方法,这些方法在抽象基类中没有具体实现,但任何具体子类都必须实现这些方法。它确保所有子类遵循一种接口标准。 - 强制实现: 当你在抽象基类中定义了抽象方法,所有继承这个抽象基类的具体类都被要求提供对这些方法的实现。
- 无法实例化: 含有抽象方法的类不能被实例化。如果尝试实例化,会抛出
TypeError
。 - 抽象类中可以定义非抽方法,但是也要子类重写抽象类方法后,通过实例化的子类调用抽象类中的方法
文件操作
打开和关闭文件
open()
函数,可以打开文件,通过函数的参数指定文件名,操作模式,字符编码等信息
还可以使用with
上下午管理器语法在文件操作完成后自动执行文件对象的close
方法,
file = open('致橡树.txt', 'r', encoding='utf-8')
print(file.read())
file.close()
操作模式 | 具体含义 |
---|---|
'r' |
读取 (默认) |
'w' |
写入(会先截断之前的内容) |
'x' |
写入,如果文件已经存在会产生异常 |
'a' |
追加,将内容写入到已有文件的末尾 |
'b' |
二进制模式 |
't' |
文本模式(默认) |
'+' |
更新(既可以读又可以写) |
异常处理机制
所有的异常都是BaseException的子类型,有四个直接的子类,分别是:SystemExit
、KeyboardInterrupt
、GeneratorExit
和Exception
SystemExit
表示解释器请求退出KeyboardInterrupt
是用户中断程序执行(按下Ctrl+c
)GeneratorExit
表示生成器发生异常通知退出
file = None
try:
file = open('致橡树.txt', 'r', encoding='utf-8')
print(file.read())
except FileNotFoundError:
print('无法打开指定的文件!')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误!')
finally:
if file:
file.close()
自定义异常
class InputError(ValueError):
"""自定义异常类型"""
pass
def fac(num):
"""求阶乘"""
if num < 0:
raise InputError('只能计算非负整数的阶乘')
if num in (0, 1):
return 1
return num * fac(num - 1)
对象的序列化与反序列化
序列化: 序列化是将数据结构或对象转换为一种格式,可以用于存储或传输的过程。在 Python 中,常见的序列化格式包括 JSON、XML、Pickle 等。
反序列化:反序列化是将序列化的数据(通常是字符串或字节流)恢复成数据结构或对象的过程。这使得程序能够读取存储或传输的数据。
-
读取json数据
json.dumps()
函数
json模块四个比较重要的函数
dump
- 将Python对象按照JSON格式序列化到文件中dumps
- 将Python对象处理成JSON格式的字符串load
- 将文件中的JSON数据反序列化成对象loads
- 将字符串的内容反序列化成Python对象