Python 速通¶
建立在熟悉c/cpp的基础之上,面向ML/DL的需要学习Python
基本变量类型¶
str int float bool
所有的基本变量可以通过str(123)这样的写法进行类型转换
转换成bool为False的条件是数字为0,或者其他类型为空
另外还有None,表示"空"(类似c/cpp的NULL/nullptr),判断用is None
字符串¶
用单双三引号包裹
f字符串:允许插入{}作为参数
print()中
分割和连接
str1 = "hello world"
str1.split() # ['hello', 'world'] - 分词,非常常用
str1.strip() # 去除首尾空白
",".join(["a","b"]) # 'a,b' 拼接
转义字符\n \t也同样支持
数字¶
int和float
除法4/3的结果和c/cpp不一样,会返回浮点数
//整除 %取余
布尔类型¶
首字母大写,是True和False而不是c/cpp的true
and or not 对应 c/cpp 的 && || !
& | 在py中仍是按位与/或(和c/cpp一样),不要混用于逻辑判断
高级变量类型¶
set tuple dict list 作为容器,内部可以储存任意类型的数据
这几个类型可以任意转换
转换成字典需要用dict1 = dict(zip(keys, vals))通过zip将键列表和值列表配对
len(a)获取长度
set 集合¶
a = {1,2,3}
内部的元素无序、不可重复
由于字典的使用频率比集合高很多,所以a = {}这样的创建默认是字典,需要的话使用a = set()创建空集合
tuple 元组¶
a = (1,2,3) 或者省略a = 1,2,3
可以使用下标访问
元组的解包
a,b = 1,2 可以实现快速赋值(1,2被视作一个元组)
a,b = b,a 交换变量 (b,a临时创建一个元组然后再解包)
a,b,_ = (1,2,3) 最后一个值被抛弃,个数要匹配
a,b,*c = (1,2,3,4) c为一个列表,储存剩余的值
list 列表¶
a = [1,2,3,4,5,6]
类似cpp的vector动态数组而非链表,但其中储存的实际上是指针
可以使用下标访问,另外python的下标支持负数
+被重载为添加元素,*是复制自己添加到结尾
切片
b = a[start : end : step]
左闭右开,从下标start处开始,每隔step选取一个元素,一直到end下标之前一个元素,得到切片后的新列表(拷贝)
常用方法
a = [1,2,3]
a.append(4) # [1,2,3,4] - 末尾添加(常用)
a.extend([5,6]) # [1,2,3,4,5,6] - 合并列表
a.insert(0, 0) # [0,1,2,3,4,5,6] - 指定位置插入
a.pop() # 弹出并返回末尾元素
a.pop(0) # 弹出并返回指定位置元素
a.remove(3) # 删除第一个匹配的值
注意引用问题:列表是可变对象,直接赋值只是引用拷贝
列表推导式
dict 字典¶
a = {'a':1, 'b':10}
和cpp的unordered_map基本一致,哈希表
使用del a['a']删除元素
用.values() .keys() .items()得到值 键 键值对(打包成元组),用于循环遍历或者类型转换
字典/集合推导式(和列表推导式类似)
a = [1,2,2,3,4]
d = {x: x**2 for x in a} # {1:1, 2:4, 3:9, 4:16} - 字典推导
s = {x**2 for x in a} # {1, 4, 9, 16} - 集合推导(自动去重)
高级类型的通用语法¶
in 运算符:检查成员是否存在,可用于list/dict/set/str
any() / all():检查可迭代对象中是否有任意/全部元素为True
any([True, False, False]) # True
all([True, True, True]) # True
# 结合推导式使用很常见
any(x > 5 for x in [1,3,5]) # False
all(x > 0 for x in [1,3,5]) # True
is vs ==¶
==比较值,is比较内存地址(是否是同一个对象)
a = [1,2,3]
b = [1,2,3]
a == b # True(值一样)
a is b # False(不同对象)
# 特别要注意 None 的判断:用 is
x = None
x is None # 推荐写法
for 遍历循环¶
range():生成整数序列,常用于指定次数的循环
enumerate():同时获取下标和值
zip():并行遍历多个列表
如果需要循环的是字典,用.values() .keys() .items()遍历值 键 键值对(打包成元组)
a = {"a":1, "b":2, "c":3}
for tmp in a.items():
print(tmp) #tmp是元组
for key,val in a.items():
print(f"{key} = {val}")
函数¶
可以返回多个值,会打包成一个元组再返回
可以输入任意数量的参数,写成(*para)即可,会将传入的任意数量参数打包成元组;这一项必须在函数参数列表的最后
可以传入任意数量的键值对参数:
可变/不可变对象¶
- 不可变:int float str tuple(函数内修改会创建新对象)
- 可变:list dict set(函数内的修改在原对象上进行)
# 经典坑:用可变对象作为默认参数
def bad_append(x, lst=[]): # 默认列表只创建一次!
lst.append(x)
return lst
bad_append(1) # [1]
bad_append(2) # [1,2] ← 不是[2]!
# 正确做法
def good_append(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
类¶
类名默认是首字母大写的
成员¶
__init__类似于c/cpp的构造函数,但是要写出self作为第一个参数,这个类似于c/cpp的this指针
不同于c/cpp,python对大部分成员的声明是在__init__里完成的
class Dog:
def __init__(self, name, age):
#实例变量(每个对象独有)
self.name = name
self.age = age
self.speed = 10
#私有变量(名称修饰)
self._secret = "secret"
#类变量(静态成员)
species = "Canis familiaris"
python没有访问限制相关的关键字,而是用命名_val约定为私有,但是不限制访问
继承¶
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "Some sound"
def move(self):
return f"{self.name} moves"
class Dog(Animal): #继承
def __init__(self, name, breed):
super().__init__(name) #调用父类构造函数
self.breed = breed
def speak(self): #自动覆盖
return "Woof!"
def fetch(self):
return f"{self.name} fetches"
导入模块¶
import numpy # 导入整个模块,用 numpy.array()
import numpy as np # 起别名(ML/DL中最常见),用np.array()
from numpy import array # 只导入特定函数,直接 array()
with 文件读写¶
# 自动管理资源释放,无需手动close
with open("data.txt", "r") as f: # r读 w写 a追加
content = f.read() # 全部读取
lines = f.readlines() # 按行读取为列表
# ML中常用with读数据
with open("train.txt", "r", encoding="utf-8") as f:
for line in f:
process(line.strip())
main¶
让一个 .py 文件既能被导入(复用函数/类),又能直接运行测试代码:
# my_utils.py
def add(a, b):
return a + b
if __name__ == '__main__':
# 只有直接运行 python my_utils.py 时才会执行
print(add(3, 5)) # 测试代码
实践相关¶
传入参数,如果是自定义类型,自行声明参数才有自动补全:
class Solution:
def __init__(self,N,K):
self.N = N
self.K = K
self.start_state = (N, N, 0)
def getStartState(self):
return self.start_state
def isGoalState(self, state):
return state == (0,0,1)
def getSuccessors(self, state):
return get_successors(state, self.N, self.K)
def DFS(problem: Solution):
#这样子就打problem就可以按Tab补全