Python基础
提示
对有一定的C语言基础,想学Python的同学,可以参考这篇文章。
1. 简介
Python 是一种高级编程语言,由 Guido van Rossum 在 1989 年创建,并于 1991 年首次公开发行。Python 以其简洁易读的语法、丰富的库和框架、强大的社区支持等特点,迅速成为了数据科学、机器学习、Web 开发、自动化脚本编写等多个领域的热门选择。
Python 的主要特点包括:
简洁易读:Python 采用缩进来表示代码块,语法简洁清晰,易于学习。
动态类型:Python 是动态类型的语言,这意味着你不需要在声明变量时指定其类型,Python 解释器会在运行时自动确定类型。
丰富的标准库:Python 拥有一个庞大的标准库,涵盖了文件处理、网络编程、数据库接口、图形界面开发、科学计算等多个方面。
强大的第三方库:除了标准库外,Python 还有大量的第三方库可供使用,如 NumPy、Pandas、Matplotlib 用于数据分析,Django、Flask 用于 Web 开发,TensorFlow、PyTorch 用于机器学习等。
面向对象:Python 支持面向对象编程,包括类、继承、多态等概念。
社区支持:Python 有一个庞大的开发者社区,提供了丰富的资源和帮助。
跨平台:Python 可以在多种操作系统上运行,包括 Windows、Linux、macOS 等。
脚本编写:Python 非常适合用于编写自动化脚本,可以快速完成一些简单的任务。
下面是一个简单的 Python 程序示例,用于打印 "Hello, World!":
print("Hello, World!")
要运行这个 Python 程序,你需要安装 Python 解释器。安装完成后,你可以将代码保存为 .py
文件,然后在命令行中运行它:
python hello.py
或者,如果你已经安装了 Python,并且将其添加到了系统的 PATH 环境变量中,你也可以直接在命令行中运行:
python
然后输入或粘贴代码:
print("Hello, World!")
按 Enter
键后,你将看到输出:
Hello, World!
Python 的应用领域非常广泛,从 Web 开发到数据科学,从网络爬虫到自动化运维,都可以看到 Python 的身影。由于其易读性和丰富的生态,Python 已经成为当今最受欢迎的编程语言之一。
2. 基础语法
注释
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 单行注释
'''
多行注释(单引号)
'''
"""
多行注释(双引号)
"""
规范
- 缩进:使用4个空格(或tab)
命名 | 说明 | 类比 | 示例 |
---|---|---|---|
前置单下划线 | 类对象和子类可访问 | protected | obj._xx |
前置双下划线 | 私有属性和方法,避免被子类覆盖 | private | obj._classname__xx |
前后双下划线 | 魔法函数 | __len__ | |
后置单下划线 | 避免与关键字冲突 | xx_ |
示例
# 斐波那契数列
a, b = 0, 1
while b < 1000:
print(b, end=',')
a, b = b, a+b
3. 数据类型
类型 | 说明 | 示例 |
---|---|---|
文本 | ||
str | 字符串 | "Hello World!" |
数值 | ||
int | 整数 | 1234567890 |
float | 浮点数 | 1.234567890 |
complex | 复数 | 3 + 4j |
布尔 | ||
bool | 布尔值 | True/False |
序列 | ||
list | 列表 | [1,2,3] |
tuple | 元组 | (1,2,3) |
range | 范围 | range(1,3) |
集合 | ||
set | 集合 | {1,2,3} |
frozenset | 不可变集合 | frozenset({1,2,3}) |
映射 | ||
dict | 字典 | {"name":"apaki", "age":18} |
二进制 | ||
bytes | 字节 | b"Hello World!" |
bytearray | 字节数组 | bytearray([1,2,3]) |
memoryview | 内存视图 | memoryview(b"Hello World!") |
可以使用type
来判断数据类型
type(1)
s = "Hello World!"
type(s)
字符串
字符串(String)是一种非常基础且重要的数据类型,用于表示文本数据。
字符串的定义
- 字符串是由0个或多个字符组成的有限序列。这些字符可以是英文字母、数字、特殊符号、中文字符等。
- 字符串可以使用单引号(')、双引号(")或三引号('''或""")来定义。例如:
text1 = "这是一个字符串"
text2 = '这也是一个字符串'
text3 = """这是一个
多行字符串"""
字符串的基本操作
- 访问字符串中的字符:使用索引(从0开始)来访问字符串中的特定字符。例如,
text1[0]
将返回字符串"text1"的第一个字符,即'这'。 - 字符串切片:使用冒号(:)来截取字符串的一部分。例如,
text1[1:3]
将返回字符串"text1"中从索引1到索引2(不包括索引3)的子串,即'是一'。 - 字符串连接:使用加号(+)可以将两个或多个字符串连接起来。例如,
text4 = text1 + text2
将创建一个新的字符串,内容为"这是一个字符串这也是一个字符串"。 - 字符串重复:使用乘号(*)可以重复字符串多次。例如,
text5 = text1 * 3
将创建一个新的字符串,内容为"这是一个字符串这是一个字符串这是一个字符串"。
# 字符串的拼接
3*'ab' + 'num' # 'abababnum'
3*'ab' 'num' # 'abnumabnumabnum'
# 下标
s = "Hello World!"
s[0] # 'H'
s[-1] # '!'
# 切片
s[1:3] # 'el'
s[:5] # 'Hello'
s[6:] # 'World!'
s[:] # 'Hello World!'
字符串的常用方法
- len():返回字符串的长度(即字符数)。
- lower()和upper():分别将字符串转换为小写和大写。
- strip()、lstrip()和rstrip():用于删除字符串开头和结尾的空格或指定字符。
- split():将字符串分割成子字符串,并返回一个包含子字符串的列表。
- join():将字符串列表连接成一个字符串。
- replace():替换字符串中的特定子字符串。
- find()和index():查找字符串中是否包含某个子字符串,并返回其位置。
- count():计算字符串中某个子字符串出现的次数。
- startswith()和endswith():检查字符串是否以指定的前缀或后缀开头或结尾。
- isdigit()、isalpha()、isalnum():用于检查字符串是否只包含数字、字母或数字字母组合。
- format():用于格式化字符串,将变量的值插入到字符串中。
- encode()和decode():用于在字符串和字节之间进行转换。
def default():
# ---------------------------------------------------------------------------------
ss = 'str_test ->> hello world! I am July Baker! this is a great idea!\
1... 2... 3... ok! (^.^)好的'
print(len(ss))
# ------------------------------------------------------------------
# 居中显示 -> 若设定的长度超过了字符串长度,默认空格填充
r = ss.center(128, '-')
print(r)
# 左对齐
r = ss.ljust(128, '<')
print(r)
# 右对齐
r = ss.rjust(128, '>')
print(r)
# 用0左填充
r = ss.zfill(128)
print(r)
# format
r = '{1} + 0x{0:02d} = {2:f}'.format(0x01, 2, 1+2)
print('format格式化的应用:', r)
# format_map
# ...
# ----------------------------------------------------------------
# 显示字符串中字串在范围内出现的不重叠次数
r = ss.count('..')
print('..出现的不重叠次数', r)
# 若字符串以指定后缀结尾,则返回True
r = ss.endswith('的')
print('是否以"的"结尾?', r)
#
r = ss.startswith('的')
print('是否以"的"开头?', r)
# 返回-1表示没有找到。若找到,则返回最小索引值
r = ss.find('july')
print('查找"july"', r)
r = ss.rfind('...')
print('rfind返回最高索引', r)
# 类似find,但找不到会报ValueError
r = ss.index('July')
print('查找"July"', r)
r = ss.rindex('...') # 类似rfind
# -----------------------------------------------------------------
# 以 bytes 对象形式返回字符串编码版本
r = ss.encode('utf_8')
print(type(r), r)
# 首字符变为大写,其他都变为小写
r = ss.capitalize()
print(r)
# 类似于lower(),但是功能更加夸张,可以查看python文件说明理解
r = ss.casefold()
print(r)
r = ss.lower()
print(r)
r = ss.upper()
print(r)
# 所有tab都被size个空格所代替
r = ss.expandtabs(16)
print(r)
# 所有单词首字母大小,类似于标题
r = ss.title()
print(r)
r = ss.swapcase()
print(r)
# ---------------------------------------------------------------------------------
# '好的list'isalpha() -> True
# 'asdf.123'isalpha() -> False
r = ss.isalpha()
print('是否都为字符?', r)
r = ss.isascii()
print('是否都为assic码(U+0000 =< x <= U+007F)?', r)
# 数字判断
r = '0123'.isdecimal()
print(r)
r = '1765'.isdigit()
print(r)
r = '123Ⅱ一二叁亿'.isnumeric()
print(r)
# ?
# r = ss.isidentifier()
# ?
# r = ss.maketrans()
# r = ss.translate()
# 好理解的就不打印了
r = ss.islower()
r = ss.isprintable()
r = ss.isspace()
r = ss.istitle()
# ----------------------------------------------------------------------------
# 返回删除前导字符的字符串副本
r = ss.lstrip('-> _tsre')
print(r)
r = ss.rstrip('好的()^. 123ok!')
print(r)
r = ss.strip('->_tsre好的()^. 123ok!')
print(r)
# -----------------------------------------------------------------------------
r = '-'.join('JulyBaker')
print(r)
# 从第一次出现'is'的地方分割为3-tuple
r = ss.partition('is')
print(r)
r = ss.rpartition('is')
print(r)
# 默认从空格分开,maxsplit=-1分割字符串全部(即没有次数限制),若指定maxsplit则分割指定次数
r = ss.rsplit()
print(r)
r = ss.split()
print(r)
r = ss.replace('...', '、')
print(r)
string = '''title
I am Bruce!
(^o^)'''
r = string.splitlines()
print(r)
列表
list
(列表)是一种非常常用的数据结构,用于存储有序的元素集合。这些元素可以是任何类型,包括整数、浮点数、字符串、列表(即嵌套列表)等。列表用方括号 []
来定义
创建列表
my_list = [1, 2, 3, 4, 5]
mixed_list = [1, 'two', 3.0, [4, 5, 6]]
访问列表元素
使用索引(从0开始)来访问列表中的元素。
print(my_list[0]) # 输出 1
print(my_list[-1]) # 输出 5,负索引从列表末尾开始计数
修改列表元素
通过索引直接修改列表中的元素。
my_list[0] = 10
print(my_list) # 输出 [10, 2, 3, 4, 5]
添加元素
- 使用
append()
方法在列表末尾添加元素。
my_list.append(6)
print(my_list) # 输出 [10, 2, 3, 4, 5, 6]
- 使用
insert()
方法在指定索引处插入元素。
my_list.insert(1, 'one')
print(my_list) # 输出 [10, 'one', 2, 3, 4, 5, 6]
删除元素
- 使用
del
语句删除指定索引处的元素。
del my_list[1]
print(my_list) # 输出 [10, 2, 3, 4, 5, 6]
- 使用
remove()
方法删除第一个匹配的元素。
my_list.remove(2)
print(my_list) # 输出 [10, 3, 4, 5, 6]
- 使用
pop()
方法删除并返回指定索引处的元素(如果不提供索引,则默认删除并返回最后一个元素)。
last_element = my_list.pop()
print(last_element) # 输出 6
print(my_list) # 输出 [10, 3, 4, 5]
列表切片
使用冒号(:
)来获取列表的子集。
print(my_list[1:4]) # 输出 [3, 4, 5]
列表长度
使用len()
函数来获取列表的长度。
print(len(my_list)) # 输出 4
列表连接
使用+
运算符来连接两个列表。
another_list = [7, 8, 9]
combined_list = my_list + another_list
print(combined_list) # 输出 [10, 3, 4, 5, 7, 8, 9]
列表乘法
使用*
运算符来重复列表。
repeated_list = my_list * 2
print(repeated_list) # 输出 [10, 3, 4, 5, 10, 3, 4, 5]
列表排序
使用sort()
方法对列表进行原地排序(不返回新列表),或使用sorted()
函数返回排序后的新列表。
my_list.sort()
print(my_list) # 输出 [3, 4, 5, 10]
sorted_list = sorted(another_list)
print(sorted_list) # 输出 [7, 8, 9]
元组
tuple
(元组)是另一种有序的元素集合,与列表非常相似,但元组是不可变的,即一旦创建后就不能修改其内容。元组通常用圆括号 ()
来定义(但在只有一个元素的元组中,需要在元素后面加上逗号 ,
以区分该元素和圆括号内的普通表达式)。
创建元组
my_tuple = (1, 2, 3, 4, 5)
single_element_tuple = (6,) # 注意这里的逗号,以区分整数6和元组(6)
访问元组元素
与列表相同,使用索引(从0开始)来访问元组中的元素。
print(my_tuple[0]) # 输出 1
print(my_tuple[-1]) # 输出 5
元组是不可变的
无法像list
那样修改元组中的元素。也无法使用append()
、insert()
、remove()
或pop()
方法来修改元组。
尽管元组是不可变的,但元组中的元素可以是可变的(如列表或其他元组),但你不能通过这些可变元素来“间接”修改元组本身。
b = (1,[2,3])
print(b) # (1, [2, 3])
# !注意:这里修改的不是 tuple 内容,而是他的元素 list 的内容
b[1][0] = 4
b[1][1] = 5
print(b) # (1, [4, 5]
元组连接
与列表一样,可以使用 +
运算符来连接两个元组。
another_tuple = (6, 7, 8)
combined_tuple = my_tuple + another_tuple
print(combined_tuple) # 输出 (1, 2, 3, 4, 5, 6, 7, 8)
元组切片
与列表相同,可以使用切片来获取元组的子集。
print(my_tuple[1:4]) # 输出 (2, 3, 4)
获取元组长度
使用 len()
函数来获取元组的长度。
print(len(my_tuple)) # 输出 5
元组乘法
与列表相同,你可以使用 *
运算符来重复元组。
repeated_tuple = my_tuple * 2
print(repeated_tuple) # 输出 (1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
元组作为字典的键
由于元组是不可变的,因此它们可以用作字典的键(而列表则不能)。
my_dict = {(1, 2): 'one_two', (3, 4): 'three_four'}
print(my_dict[(1, 2)]) # 输出 'one_two'
元组在需要存储一组相关值但不需要修改它们的情况下非常有用,例如表示坐标点、日期等。由于元组是不可变的,因此它们比列表更加轻量级,并且在某些情况下(如作为字典的键或作为集合的元素)是必需的。
集合
集合(set)是一种无序且元素唯一的可迭代数据类型。它提供了一种高效的方法来执行与成员资格相关的操作,如查找、添加和删除元素。集合中的元素可以是任何不可变类型(如整数、浮点数、字符串、元组等),但不能是列表或字典等可变类型。
创建集合
集合可以使用大括号 {}
或 set()
函数来创建。但是,请注意,如果使用大括号创建空集合,需要加上一个空格或者使用 set()
函数,因为大括号 {}
在没有元素的情况下会被解释为空字典。
# 使用大括号创建集合
my_set = {1, 2, 3, 4, 5}
# 使用set()函数创建集合
another_set = set([1, 2, 3, 4, 5])
# 创建空集合
empty_set = set() # 或者使用 empty_set = {},但通常不推荐这种方式,因为它可能导致混淆
集合操作
集合支持多种操作,包括添加元素、删除元素、检查成员资格、集合的并集、交集和差集等。
添加元素
使用 add()
方法向集合中添加一个元素,或者使用 update()
方法添加多个元素(可以是另一个集合或可迭代对象)。
my_set.add(6) # 添加单个元素
my_set.update([7, 8, 9]) # 添加多个元素
删除元素
使用 remove()
方法删除集合中的一个元素(如果该元素不存在,会引发 KeyError
),或者使用 discard()
方法(如果元素不存在,则什么也不做)。另外,还可以使用 pop()
方法随机删除并返回集合中的一个元素(如果集合为空,会引发 KeyError
),或者使用 clear()
方法清空集合。
my_set.remove(6) # 删除元素6
my_set.discard(7) # 尝试删除元素7,如果不存在则不报错
element = my_set.pop() # 随机删除并返回一个元素
my_set.clear() # 清空集合
检查成员资格
使用 in
关键字来检查一个元素是否存在于集合中。
if 5 in my_set:
print("5在集合中")
集合运算
union()
或|
:返回两个集合的并集。intersection()
或&
:返回两个集合的交集。difference()
或-
:返回第一个集合中存在但第二个集合中不存在的元素的集合(差集)。symmetric_difference()
或^
:返回两个集合的对称差集,即只存在于一个集合中的元素。
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
union_set = set1.union(set2) # {1, 2, 3, 4, 5, 6, 7, 8}
intersection_set = set1.intersection(set2) # {4, 5}
difference_set = set1.difference(set2) # {1, 2, 3}
symmetric_difference_set = set1.symmetric_difference(set2) # {1, 2, 3, 6, 7, 8}
集合的特性
- 集合中的元素是无序的。
- 集合中的元素是唯一的,重复的元素在集合中只会出现一次。
- 集合是可迭代的,因此可以使用循环来遍历集合中的元素。
集合的这些特性使得它们在处理需要快速进行成员资格检查、去重或执行集合运算的场景中非常有用。
def base():
r0 = set()
print("-> 空集", r0)
r1 = {1, 2, 3, 4}
r2 = {2, 3, 5, 6}
print("-> 集合r1 ", r1)
print("-> 集合r2 ", r2)
r = r1 & r2
print("交集 ", r)
r = r1 | r2
print("并集 ", r)
r = r1 - r2
print("相对补集/差集r1-r2 ", r)
r = r2 - r1
print("相对补集/差集r2-r1 ", r)
r3 = {1, 2}
print("-> 集合r3 ", r3)
print("r3是r1的子集?", r3.issubset(r1))
print("r3是r2的子集?", r3.issubset(r2))
r = r1 ^ r2
print("对称差集/差分 ", r)
r = (r1 | r2) - (r1 & r2)
print(r)
# ------------------------------------------
fr1 = frozenset({1, 2, 3, 4, 5})
# fr1.add(6) 失败
# frozenset得到的集合,不可修改
def base2():
r1 = {1, 2, 3, 4}
r2 = {2, 3}
r3 = {4, 5, 6}
print('4 in r1? ', 4 in r1)
print('5 not in r1? ', 5 in r2)
# isdisjoint没有交集返回True
print(r3.isdisjoint(r2))
print(r3.isdisjoint(r1))
# 判断子集 & 真子集 issubset
print('r2是r1的子集么? ', r2.issubset(r1))
print(r2 <= r1)
print(r2 < r1)
print('r2是r1的子集么? ', r1.issuperset(r2))
print(r1 >= r2)
print(r1 > r2)
# 交集,并集,差集...的其他表示方式
# 下面的方式仅仅作为计算,而不改变r1的值
r = r1.union(r2, r3)
print('r1,r2,r3的并集', r)
r = r1.intersection(r2, r3)
print('r1,r2,r3的交集', r)
r = r1.difference(r3)
print('r1 - r3差集', r)
r = r1.symmetric_difference(r3)
print('对称差分', r)
# 使用update的,会同步更新r1的值
r = r1.copy()
r.update(r2, r3)
print('r1,r2,r3的并集', r)
r = r1.copy()
r.intersection_update(r2, r3)
print('r1,r2,r3的交集', r)
r = r1.copy()
r.difference_update(r3)
print('r1 - r3差集', r)
r = r1.copy()
r.symmetric_difference_update(r3)
print('对称差分', r)
if __name__ == "__main__":
base()
base2()
字典
字典(dictionary)是一种可变容器模型,它存储键值对(key-value pair),并且每个键都是唯一的。字典类型用于存储和检索与键相关联的值。
创建字典
字典使用大括号 {}
来定义,其中每个键值对使用冒号 :
分隔,键值对之间使用逗号 ,
分隔。
# 创建一个空字典
empty_dict = {}
# 创建一个包含键值对的字典
my_dict = {
"key1": "value1",
"key2": "value2",
"key3": 3,
"key4": [1, 2, 3] # 值可以是任何类型,包括列表、元组等
}
print(my_dict.keys()) # 返回所有关键字列表
print(my_dict.values()) # 返回所有Value列表
print(my_dict.items()) # 返回所有键值对列表
# 利用字典推导式创建字典
d = {x: x**2 for x in range(1, 5)}
print(d)
访问字典中的值
通过键来访问字典中的值。
value1 = my_dict["key1"] # 获取与"key1"相关联的值
print(value1) # 输出: value1
修改字典中的值
通过重新给键赋值来修改字典中的值。
my_dict["key1"] = "new_value1" # 修改"key1"的值
添加键值对
如果键不存在于字典中,给它赋值将会添加一个新的键值对。
my_dict["key5"] = "value5" # 添加一个新的键值对
删除键值对
使用 del
语句或 pop()
方法来删除字典中的键值对。
# 使用 del 语句删除键值对
del my_dict["key2"]
# 使用 pop() 方法删除键值对,并返回被删除的值
value3 = my_dict.pop("key3")
print(value3) # 输出: 3
检查键是否存在
使用 in
关键字来检查字典中是否存在某个键。
if "key1" in my_dict:
print("key1 存在")
遍历字典
可以使用 for
循环来遍历字典的键、值或键值对。
# 遍历键
for key in my_dict:
print(key)
# 遍历值
for value in my_dict.values():
print(value)
# 遍历键值对
for key, value in my_dict.items():
print(key, value)
字典的特性
- 字典是可变的,可以添加、修改或删除键值对。
- 字典中的键必须是不可变的(如整数、浮点数、字符串、元组等),而值可以是任何类型。
- 字典是无序的,但可以通过
sorted()
函数和字典的items()
方法来获取有序的键值对列表。 - 字典的查找、添加和删除操作的时间复杂度通常是 O(1),因为字典内部通常使用哈希表来实现。
字典在Python编程中非常常见,它们通常用于存储需要快速查找的数据,如数据库记录、配置文件选项等。
# II. 循环遍历dt
d = {"name1": "Juli", "name5": "Baker", "name3": "Bryce", "name4": "Loski"}
print(type(d))
# 方法1:dict[key]
for key in d:
print("{}:{}".format(key, d[key]))
print('------------')
# 方法2:解包
for key, value in d.items():
print("{}:{}".format(key, value))
print('------------')
# 直接显示Key和Value
print(d.keys())
print(d.values())
# 按照key排序
ret = sorted(d.items()) # sorted默认给dict排序是按照key排序的
ret = sorted(d.items(), key=lambda d: d[0])
print(ret)
# 按照value排序
ret = sorted(d.items(), key=lambda d: d[1])
print(ret)
print(type(ret)) # sourted返回的是list
dd2 = dict(ret)
print(dd2) # dict转换一下即可
字节
'''
1-3 主要涉及Hex,Bytes,List之间的相互转换
这里的Hex指的是诸如 str("313233414234") (即相当于是2个字符表示一位十六进制数据)
则可定Hex不能有[^0-9A-Fa-f]数据
4-6 涉及到str 诸如"Hello world哈哈"
则这种情况会涉及到转码问题encoding=utf-8等
'''
# 1.0 hex <--> bytes
def hex2bytes(hh):
'''
str("31323334") -> b"1234"
'''
return bytes.fromhex(hh)
def bytes2hex(bb):
'''
b"1234" -> str("31323334")
'''
return bb.hex()
# 2.0 list <--> bytes
def list2bytes(ll):
'''
[0x31,0x32,0x33] -> b"123"
'''
return bytes(ll)
def bytes2list(bb):
'''
b"123" -> [0x31,0x32,0x33]
'''
return list(bb)
# 3.0 list <--> hex
def list2hex(ll):
'''
[0x31,0x32,0x33] -> str("313233")
'''
return bytes(ll).hex()
def hex2list(hh):
'''
str("313233") -> [0x31,0x32,0x33]
'''
bb = bytes.fromhex(hh)
return list(bb)
# 4.0 str <--> list
def str2list(ss):
'''
str("123ABC") -> [0x31,0x32,0x33,0x41,0x42,0x43]
str("我的世界")(本脚本为utf-8编码) -> [25105, 30340, 19990, 30028] (因为ord返回Unicode编码)
'''
return [ord(c) for c in list(ss)]
def list2str(ll):
'''
[0x31,0x32,0x33,0x41,0x42,0x43] -> str("123ABC")
'''
return ''.join([chr(i) for i in ll])
# 5.0 str <--> bytes
def str2bytes(ss):
'''
str("123ABC") -> b"123ABC"
'''
return bytes(ss, encoding='utf-8')
def bytes2str(bb):
'''
b"123ABC" -> str("123ABC")
'''
return str(bb, encoding='utf-8')
'''
其他各种转换便不再多写了,主要是因为有以上一些接口,
对于实际应用的时候,用到什么,相互直接一调用也能实现各种数据之前的相互转化了。
以后若再扩展,则必定是更加简洁/高效...的方式
'''
def py36_str_hex_bytes_test():
# ------------------------------------------------------
ll = [0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38]
print('[list] {} \t {}'.format(type(ll),ll))
bb = list2bytes(ll)
hh = list2hex(ll)
print('[list2bytes] {} \t {}'.format(type(bb),bb))
print('[list2hex] {} \t {}'.format(type(hh),hh))
ll2 = bytes2list(bb)
hh2 = bytes2hex(bb)
print('[bytes2list] {} \t {}'.format(type(ll2),ll2))
print('[bytes2hex] {} \t {}'.format(type(hh2),hh2))
ll3 = hex2list(hh)
bb2 = hex2bytes(hh)
print('[hex2list] {} \t {}'.format(type(ll3),ll3))
print('[hex2bytes] {} \t {}'.format(type(bb2),bb2))
ll4 = str2list("我的世界")
print('[str2list] {} \t {}'.format(type(ll4), ll4))
ss = list2str(ll4)
print('[list2str] {} \t {}'.format(type(ss), ss))
bb4 = str2bytes(ss)
print('[str2bytes] {} \t {}'.format(type(bb4), bb4))
ss4 = bytes2str(bb4)
print('[bytes2str] {} \t {}'.format(type(ss4), ss4))
# 若想将汉字也转为list形式,可以相互调用实现
bb5 = str2bytes("我的世界")
ll5 = bytes2list(bb5)
print('[汉字2list] {} \t {}'.format(type(ll5), ll5))
4. 变量
变量 | 说明 |
---|---|
_ | 临时变量,表示上一个计算结果 |
5. 运算符
算数运算
运算符 | 说明 | 示例 |
---|---|---|
+ | 加 | 1 + 2 |
- | 减 | 1 - 2 |
* | 乘 | 1 * 2 |
/ | 除 | 1 / 2 |
// | 整除(取整数) | 17 // 3 |
% | 取余 | 17 % 3 |
** | 幂 | 2 ** 3 |
关系运算符
运算符 | 说明 | 示例 |
---|---|---|
== | 等于 | 1 == 2 |
!= | 不等于 | 1 != 2 |
> | 大于 | 1 > 2 |
< | 小于 | 1 < 2 |
>= | 大于等于 | 1 >= 2 |
<= | 小于等于 | 1 <= 2 |
位运算符
运算符 | 说明 | 示例 |
---|---|---|
& | 按位与 | 1 & 2 |
| | 按位或 | 1 | 2 |
^ | 按位异或 | 1 ^ 2 |
~ | 按位取反 | ~1 |
<< | 左移位 | 1 << 2 |
>> | 右移位 | 1 >> 2 |
逻辑运算符
运算符 | 说明 | 示例 |
---|---|---|
and | 逻辑与 | x > 1 and x < 5 |
or | 逻辑或 | x < 1 or x > 5 |
not | 逻辑非 | not True |
赋值运算符
运算符 | 说明 | 示例 |
---|---|---|
= | 赋值 | a = 1 |
+= | 加法赋值 | a += 1 |
-= | 减法赋值 | a -= 1 |
*= | 乘法赋值 | a *= 1 |
/= | 除法赋值 | a /= 1 |
//= | 整除赋值 | a //= 1 |
%= | 取余赋值 | a %= 1 |
**= | 幂赋值 | a **= 1 |
&= | 按位与赋值 | a &= 1 |
` | =` | 按位或赋值 |
^= | 按位异或赋值 | a ^= 1 |
>>= | 右移位赋值 | a >>= 1 |
<<= | 左移位赋值 | a <<= 1 |
成员运算符
运算符 | 说明 | 示例 |
---|---|---|
in | 包含 | 1 in [1,2] |
not in | 不包含 | 1 not in [1,2] |
身份运算符
运算符 | 说明 | 示例 |
---|---|---|
is | 同一对象 | 1 is 2 |
is not | 不同对象 | 1 is not 2 |
6. 流程控制
Python 中的流程控制指的是控制程序执行的顺序和流程。这主要通过条件语句(如 if
)、循环语句(如 for
和 while
)以及异常处理语句(如 try/except
)来实现。下面我们将分别介绍这些流程控制结构。
条件语句
条件语句用于根据条件表达式的值来决定执行哪一部分代码。关键字if
, elif
, else
。
x = 10
if x > 0:
print("x 是正数")
elif x < 0:
print("x 是负数")
else:
print("x 是零")
循环语句
for
for
循环用于遍历可迭代对象(如列表、元组、字典、集合或字符串)的元素。
for i in range(5):
print(i)
c = dict(sape=4139, guido=4127, jack=4098)
for key, value in c.items():
print(key, value)
# 循环遍历序列时,可以使用枚举函数,在同一个时间检索位置和相应value
for i, v in enumerate([11, 22, 33, 44, 55]):
print(i, v)
# 若同时循环两个或者超过两个
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
# 倒序,可以使用 reversed()
for i in reversed(range(1,10,2)):
print(i)
while
while
循环用于在满足某个条件时重复执行一段代码。
i = 0
while i < 5:
print(i)
i += 1
循环控制语句
break
:用于立即退出循环。continue
:用于跳过当前循环的剩余部分,直接进入下一次循环。
3. 异常处理
异常处理用于在程序执行过程中捕获和处理异常。关键字 try
except
else
finally
try:
# 尝试执行的代码块
result = 10 / 0 # 这将引发一个 ZeroDivisionError 异常
except ZeroDivisionError:
# 当 ZeroDivisionError 异常被触发时执行的代码块
print("除数不能为零")
else:
# 当 try 块中的代码正常执行完毕时执行的代码块(可选)
print("没有异常发生")
finally:
# 无论 try/except 块中是否有异常发生,finally 块中的代码都会执行(可选)
print("这是 finally 块")
4. 传递控制
pass
:是一个空操作语句,用于在语法上需要语句,但程序不需要任何操作时。例如,在定义一个空函数或类的实现时。return
:用于从函数中返回一个值并退出函数。yield
:用于在生成器函数中返回一个值,并暂停函数的执行,直到下一次迭代。
7. 函数
函数是一个可以重复使用的代码块,用于执行特定的任务。你可以定义函数来封装一段代码,以便在程序的多个地方调用它,而无需重复编写相同的代码。
def fib(n):
print("# 斐波那契数列")
a, b = 0, 1
result = []
while b < n:
result.append(b)
a, b = b, a+b # a,b=b,a 相当于a和b交换数据
print(result)
# return result # (可选)带有函数返回值
带有默认参数的函数
def adjust(voltage, type="music", state='on'):
print(type, "音量:", voltage, "开启?", state)
带有可变参数的函数
def calc_sum(*args):
ax = 0
for n in args:
ax = ax + n
return ax
# ret = calc_sum(1,2,3,4,5)
a = (1,2,3,4,5)
ret = calc_sum(*a) # 和上面的传参方式本质上是一样的
print(ret)
带有关键字参数的函数
闭包
闭包是一个函数对象,它返回了一个包含自由(未绑定到特定对象的变量)的函数。
# -------------------------------------
"""
“闭包(Closure)”的程序结构
注意:
返回函数不要引用任何循环变量,或者后续会发生变化的变量。
"""
def calc2_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum #返回求和函数
ret = calc2_sum(*a)
print(ret)
print(ret())
print('')
装饰器
装饰器(Decorator)是一个函数,它接受一个函数作为参数并返回一个修改后的函数。
"""
装饰器
函数调用前后添加内容,但又不希望修改原函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)
"""
def log(func):
def wrapper(*args, **kw):
print('[ start time ] ' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# return func(*args, **kw)
func(*args, **kw)
print('[ end time ] ' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
return wrapper
# 装饰器
@log
def test_fun():
print('test_fun ok!')
test_fun()
print('当前函数名称:' + test_fun.__name__)
print('')
生成器
生成器(Generator)是一种特殊的函数,它返回一个迭代器。
"""
# 列表生成式,直径生成会直接占用大量空间(若数据较大的话)
a = [x*x for x in range(5)]
# 而此时,生成器的优势便体现出来了
1.0 生成器
留个问题:
send和next的区别
"""
def disp(a):
print(a)
for i in a:
print(i,end=' ')
print('\n')
# 创建generator方式二
# 针对相对复杂一些的逻辑,将函数返回直接作为生成器
def fib(max):
n, a, b = 0, 0, 1
while n < max:
# print(b,end=' ')
#执行过程中,遇到yield就中断。直到next之后才继续执行
yield b
a, b = b, a + b
n = n + 1
# 创建generator方式一
a = (x*x for x in range(5))
# print(next(a))
disp(a)
a = fib(6)
# print(next(a))
disp(a)
迭代器
迭代器(Iterator)是一种对象,它返回一个序列中的元素。
"""
注意:list,str等可迭代,但其本质不是迭代器。
但可以通过iter转换。
Iterator对象表示的是一个数据流
"""
a = fib(6)
# 以下代码和disp中的某些代码
# 在本质上是同一种行为
while True:
try:
print(next(a),end=' ')
except StopIteration:
# 遇到StopIteration就退出循环
print('\n')
break
print(type(a))
b = [1,2,3,4,5]
print(type(b))
c = iter(b)
print(type(c))
偏函数
import functools
def int2(x,base=2):
return int(x,base)
print(int2('10010'))
# 偏函数的用法,不用再重新定义一个函数
# 直接采用这种方式将原函数的某些参数固定
# 方便后续调用
int2 = functools.partial(int,base=2)
print(int2('10010'))
8. 类
类是用于定义对象(也称为实例)的属性和方法的结构。每个对象都是其类的实例,并可以访问类定义中定义的属性和方法。
对象是类的实例。当你创建一个类并定义它之后,你可以创建这个类的多个对象,每个对象都有自己的属性和方法。
#! python
# -----------------------------------
# Class
# ----------------------------------
class Complex:
# 类变量,属于类本身,而不是类的实例
r = 0.0
i = 0.0
#str = [] #1.0 str 观察现象哦~
# 小结:放在这里,在追加的时候,不同的对象也会叠加
# 初始化方法,当创建类的实例时自动调用
# 相当于C++ 的构造函数
def __init__(self,real,imag):
# 实例变量,属于类的实例
#self.r = real
#self.i = imag
self.str = [] #2.0 str 观察现象哦~
#小结:放在这里,不同的对象,各自追加自己的,不叠加
# 实例方法,需要通过类的实例来调用
def change(self,real,imag):
self.r = real
self.i = imag
self.str.append("{0:.2f} + {1:.2f}j".format(self.r,self.i))
print("--------------")
def real(self):
return self.r
def imag(self):
return self.i
def show(self):
print( "{0:.2f} + {1:.2f}j".format(self.r,self.i) )
# 相当于C++的 运算符重载
def __add__(self,c):
s = Complex(0.0,0.0)
s.r = self.r + c.r
s.i = self.i + c.i
return s
def __sub__(self,c):
s = Complex(0.0,0.0)
s.r = self.r - c.r
s.i = self.i - c.i
return s
def __mul__(self,c):
s = Complex(0.0,0.0)
s.r = self.r * c.r - self.i * c.i
s.i = self.r * c.i + self.i * c.r
return s
def __truediv__(self,c):
s = Complex(0.0,0.0)
denomi = c.r*c.r + c.i*c.i
s.r = (self.r * c.r + self.i * c.i)/denomi
s.i = (self.i * c.r - self.r * c.i)/denomi
return s
# 创建一个Complex的实例
c = Complex(3,5)
d = Complex(7,9)
c.change(2,4)
c.show()
print(c.str)
d.change(8,6)
d.show()
print(d.str)
c.show()
print(c.str)
c.change(1,2)
print(c.str)
c.show()
d.show()
print("------------------")
s = c + d
s.show()
c.show()
d.show()
s = c - d
s.show()
c.show()
d.show()
s = c * d
s.show()
c.show()
d.show()
s = c / d
s.show()
c.show()
d.show()
__init__
方法是一个特殊的方法,称为类的构造器或初始化方法。当创建类的新实例时,它会自动被调用。这个方法用于设置实例的初始状态。
self
是对实例本身的引用,它代表了类的实例。在类的方法中,第一个参数总是 self
(除了静态方法和类方法)。当调用实例方法时,Python会自动将实例作为第一个参数传递给方法。
类还可以有类方法(使用 @classmethod
装饰器)和静态方法(使用 @staticmethod
装饰器)。类方法通常用于修改类状态或与类本身进行交互,而不是与实例进行交互。静态方法与类无关,它们只是简单地附加到类上,通常用于组织代码。
"""
# 这种方式是初学类常用的方式
class Student(object):
def score(self):
return self._score
def set_score(self,value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s = Student()
s.set_score(100)
print(s.score())
s.set_score(200)
print(s.score())
"""
# 但是以上的类定义方式,再调用的时候
# 通过方法复制,毕竟要写很多的代码
# 不如直接操作变量and复制来的更加便捷 (优势1)
# 并且以下的方式,还保留着对于输入参数的判定 (优势2)
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self,value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s = Student()
# print(dir(s))
s.score = 100
print(s.score)
s.score = 200
print(s.score)
继承
继承允许我们创建一个类(称为子类或派生类),该类继承另一个类(称为父类或基类)的属性和方法。子类可以添加新的属性或重写父类的方法,也可以继承父类的所有属性和方法。
在Python中,所有的类都直接或间接地继承自一个内置的基类,这个基类就是object
。从Python 3开始,object
是所有类隐式继承的基类,即使你没有在类定义中明确指定。在Python 2中,需要显式地从object
继承以实现新式类(new-style classes),但在Python 3中,所有的类都是新式类,因此不再需要显式地从object
继承。
object
类提供了一些基本的方法,如__init__
(用于初始化对象)、__str__
(用于返回对象的字符串表示)和__repr__
(用于返回对象的官方字符串表示,通常用于调试)等。但是,这些方法在object
类本身中并没有实现具体的功能,它们只是作为占位符或钩子(hooks),供子类覆盖(override)以实现特定的行为。
下面是一个简单的示例,展示了如何显式地从object
继承(尽管在Python 3中这是不必要的):
"""
自定义的类表现的和list,dict等没有什么区别,
主要是因为动态语言的"鸭子类型"
不需要强制继承某个接口
"""
class Fib(object):
def __init__(self,max):
self.a = 0
self.b = 1
self.max = max
# 结合next实现可迭代对象
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.b > self.max:
raise StopIteration()
else:
return self.a
# 类的下标访问 & 切片等操作的实现
def __getitem__(self, n):
# 下标访问实现
if isinstance(n, int):
a, b = 0, 1
# 考虑到下标从0开始,且为了和iter结果保持一致
# 因此采用n+1的方式
for x in range(n+1):
a, b = b, a + b
return a
# 切片实现
if isinstance(n, slice):
start = n.start
stop = n.stop
if start is None:
start = 0
a, b = 0, 1
ll = []
for x in range(stop):
a, b = b, a + b
if x >= start:
ll.append(a)
return ll
def disp(a):
print(a)
for i in a:
print(i,end=' ')
print('\n')
a = Fib(10000)
disp(a)
print(a[5])
print(a[5:8])
Python自带枚举类,可以用来定义枚举类型。
from enum import Enum, EnumMeta, unique
def disp(data):
if isinstance(data, EnumMeta):
for name, member in data.__members__.items():
print(name + ' => ', member, ',', member.value)
print('--------------------------------')
else:
print(type(data))
# 获得Month的枚举类
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
# value 是从1开始的
disp(Month)
"""
可以派生出自定义类,见下
"""
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
disp(Weekday)
# 其他操作 or 调用方式
print(Weekday.Sun.value)
day = Weekday.Mon
print(day)
day = Weekday['Tue']
print(day)
day = Weekday(3)
print(day)
# day = Weekday.Sun
if day == Weekday.Sat or day == Weekday.Sun:
print('Yes,放假了')
else:
print('工作中...')
重载
重载允许我们创建多个方法,这些方法具有相同的名称,但使用不同的参数列表。Python 不会检查参数列表是否匹配,而是根据调用方法时传递的参数数量和类型来选择要调用的方法。
多态
多态允许我们使用相同的名称调用方法,而不管实例是什么类型。Python 不会检查参数列表是否匹配,而是根据调用方法时,传递给方法的参数数量和类型来选择要调用的方法。
9. 模块
模块(Module)是一个包含Python定义和语句的文件。模块可以定义函数、类和变量。模块也可以包含可执行的代码。模块文件通常以.py
为扩展名。
模块的主要目的是将相关的代码组织在一起,以便在其他Python程序中重用。一旦模块被定义,就可以在其他的Python脚本中通过import
语句来使用它。
定义模块: 创建一个
.py
文件,并在其中编写Python代码。这个文件就是一个模块。使用模块: 在其他Python脚本中,你可以使用
import
语句来导入模块。例如,如果你有一个名为my_module.py
的模块,你可以这样导入它:import my_module
然后,你可以通过模块名来访问模块中的函数、类或变量:
result = my_module.some_function(arguments)
从模块中导入特定的部分: 你可以使用
from ... import ...
语法来只导入模块中的特定部分。例如:from my_module import some_function, some_class
之后,你可以直接调用这些函数或类,而不需要使用模块名作为前缀:
result = some_function(arguments) instance = some_class()
模块的执行: 当Python解释器首次导入一个模块时,它会执行模块中的代码。但是,如果模块已经被导入过,那么再次导入时,模块中的代码不会被重新执行(除非模块被显式地重新加载)。
模块搜索路径: 当Python尝试导入一个模块时,它会按照一个特定的搜索路径来查找该模块。这个搜索路径由一系列目录组成,通常包括当前工作目录、PYTHONPATH环境变量中指定的目录以及Python的安装目录等。
内建模块: Python的标准库中包含了很多内建模块,这些模块提供了许多常用的功能和工具,如文件操作、网络编程、数据处理等。你可以直接使用这些模块,而不需要自己编写相应的代码。
第三方模块: 除了内建模块外,还有许多第三方模块可供使用。这些模块通常由Python社区开发,提供了各种扩展功能和工具。你可以通过pip等包管理工具来安装和使用这些模块。
模块文档: 为了提供模块的使用说明和API参考,你可以在模块文件的顶部添加文档字符串(docstring)。这些文档字符串可以使用Python的内置
help()
函数来查看。模块和包: 当模块的数量变得很多时,可以将它们组织成包(Package)。包是一个包含多个模块的目录,该目录必须包含一个名为
__init__.py
的文件(即使该文件是空的)。通过包,你可以更好地组织和管理你的代码。
10. 文件操作
文件操作是一个常见的任务,用于读取、写入、修改和删除文件。Python提供了内置的open()
函数来打开文件,并返回一个文件对象,该对象具有一系列的方法来进行文件操作。
读取文件
# 使用 'with' 语句可以确保文件在使用完毕后被正确关闭
with open('filename.txt', 'r') as file: # 'r' 表示读取模式
content = file.read() # 读取整个文件内容
print(content)
# 也可以逐行读取
with open('filename.txt', 'r') as file:
for line in file:
print(line, end='') # end='' 用于避免每行末尾的换行符被打印两次(在Windows中)
写入文件
# 写入文件时,如果文件不存在,则创建它;如果文件已存在,则内容会被覆盖
with open('filename.txt', 'w') as file: # 'w' 表示写入模式
file.write('Hello, World!')
# 追加内容到文件末尾
with open('filename.txt', 'a') as file: # 'a' 表示追加模式
file.write('\nAnother line of text.')
二进制模式
当处理非文本文件(如图片、视频等)时,应使用二进制模式('b'
)。
# 读取二进制文件
with open('image.jpg', 'rb') as file:
binary_content = file.read()
# 写入二进制文件
with open('output.jpg', 'wb') as file:
file.write(binary_content)
上下文管理器(with语句)
使用with
语句可以确保文件在使用完毕后被正确关闭,即使在处理文件时发生异常也是如此。这是一种推荐的做法,因为它可以简化代码并减少出错的可能性。
文件对象的常用方法
read(size)
:从文件中读取指定字节数的内容。如果省略size参数或size为负,则读取整个文件。readline()
:从文件中读取一行内容。readlines()
:从文件中读取所有行,并返回一个包含这些行的列表。write(str)
:将字符串写入文件。writelines(sequence)
:将一个字符串序列写入文件。序列中的每个元素后面都不会添加换行符,除非元素本身包含换行符。seek(offset, whence)
:移动文件读取/写入的指针位置。offset表示偏移量,whence表示偏移的基准位置(0表示文件开头,1表示当前位置,2表示文件末尾)。tell()
:返回当前文件读取/写入的指针位置。close()
:关闭文件。通常不需要手动调用,因为with
语句会自动关闭文件。
检查文件是否存在
可以使用os.path.exists()
函数来检查文件是否存在。
import os
if os.path.exists('filename.txt'):
print('文件存在')
else:
print('文件不存在')
根据具体的需求,可能还需要处理更复杂的文件操作,如读取和写入特定格式的数据(如CSV、JSON等),或者使用更高级的文件处理库(如csv
模块、json
模块等)。