tags
type
status
date
slug
summary
category
password
icon

# 细碎语法

保留小数:'{:.2f}'.format(x)
列表元组互相转化:tuple(),list()
isinstance(x, dtype)判断变量类型
不定行读入:注意way1末尾有\n,不同电脑可能有差异,不建议用
判断变量是否为None,应写 p is None, p is not None,最好不要写 p == None, p != None
raise ExceptionName(str) 抛出异常,名为ExceptionName(默认是RuntimeError),提示信息为str,可以用except ExceptionName as hint捕获
输出占位符格式:print("xxx %d %d" %(a, b)) 无逗号
eval(str) 获取表达式的值,实现字符串到表达式的转换
f'My name is {name}' 大括号中的内容直接替换为对应表达式
y=copy.deepcopy(x) 深拷贝
堆:
dict.get(key) 方法在 key(键)不在字典中时,可以返回默认值 None 或者设置的默认值。dict[key] 在 key(键)不在字典中时,会触发 KeyError 异常。
调用cmd命令os.system(str)
打开文件

# python变量的指针本质

Python中所有可赋值的东西,即可以出现在赋值号"=" 左边的东西,都是指针
  • 单值、元组与字符串(不可变类型)
单值、字符串变量赋值后,地址会改变,如b = a即为将b指向a的存储地址
注:a is b可用于判断二者地址是否相同
notion image
实际上,同样值的变量指向同一个地址
notion image
对这类变量不用担心“改了a,b也跟着变”的情况
  • 列表
代码里写了几个列表,内存中实际的列表就有几个,如a = [[0]] * 2 + [[0]] * 2,实际上内存里有两个不一样的列表
notion image
更确切的,a[0] a[1]等也是指针
notion image
  • 函数传递
notion image
但是如果传入的是可变变量,如列表,则xy指向ab的实际内存,会对ab产生影响
notion image
在下例中,swap总第一行不影响ab实际内存,第二行则会影响
notion image
又例:
notion image

# 时间复杂度

  • python中O(1)的操作:
下标访问(列表、字符串、字典)、append、 pop、 len
用in判断元素是否在集合中或某关键字是否在字典
  • python中O(n)的操作:
用in判断元素是否在字符串、元组、列表
❗用in操作时尽量用集合和字典,否则容易超时
insert、 remove、 del
find、 rfind、 index、 count
max、 min
列表和元组加法
列表的切片,切几个复杂度就是多少

# python函数

'global'关键字用于声明变量是在所有函数外部(即“main”中)定义的变量
'nonlocal'变量用于声明变量是在函数的外围函数定义的变量,会一层一层往外找
如果不赋值(即变量不出现在等号的左边),则不需要以上两个声明
  • lambda函数
即没有名字的函数,命名方式为 lambda [args*]: result
例:add = lambda x, y : x + yadd(1, 2) = 3
例:a = [[1, 2], [2, 1]], sorted(a, key = lambda x : x[0]),即以每个元素的第0位为关键字排序
还可以与if相结合:lambda x:x+1 if x==1 else 0
  • 高阶函数
函数可以赋值给变量,也可以作为函数的参数和返回值
  • 闭包
闭包即带有自由变量的函数。在函数嵌套的情况下,内部的函数使用外部函数中的变量,并且外部函数返回了内部函数,我们将这个内部函数称之为闭包。
在这个例子中,f = fun(10)g = fun(20) 分别把10和20作为inside的“外部初值”,且这种外部初值不会在inside执行一次之后就消失,而是作为闭包的一部分被保存下来
闭包可以作为函数工厂(Function Factory):通过闭包可以创建一系列相似的函数,每个函数有不同的初始状态。
  • 函数的默认值
  • 不定参数
args和kwargs只是普通变量名。*表示用元组传入,**表示用字典传入。注意不指定变量的值2不能出现在指定变量值a=2的后面

# python类

  • 定义与基本语法
变量前加_可以实现隐藏
  • 继承
声明时加上(father) 声明父类,继承父类的所有变量和方法。需要注意的时,父类的初始化需要用super()函数调用,不会自动执行。子类中可以重新定义父类的方法,即:在寻找方法时先在子类中寻找,再去父类中寻找同名的方法
  • 类的运算
isinstance(x, A) 判断x是不是类型A的对象
默认情况下,默认情况下,自定义类只有__eq__比较运算符(其默认比较方式为a is b)(可以在__init__中改写A.__eq__ = None ,使得两个对象不能比较),而其他方法都被设置成了None
我们可以改写__lt__ (less to, <)__le__(less or equal, ≤)__gt__ (giant to, >)__ge__(giant or equal, ≥),如下
  • 默认情况下,自定义类的对象,可以作为集合元素或字典的键,被作为集合元素或字典键的,是对象的id,因此意义不大
    • 可以重新定义__hash__ 方法,使得对象可以作为集合元素或者字典的键
  • 迭代器
我们希望自己写的类也能这样子遍历,先要明白for究竟是怎么执行的,如下:
因此我们只需要改变类中__iter____next__ 方法即可,例如:
  • 其他的object方法
x.__len__()
len(x),一般用于求x的长度
x.__str__()
str(x), 将x转换成字符串
x.__contains__(y)
y in x,用于判断y在不在x里面
x.__getitem__(index)
x[index] 根据下标访问x的元素,下标未必是整数
x.__setitem__(index,item)
x[index] = item
x.__call__()
使对象可以像函数一样被调用,如x()

# Numpy

  • 基本类型:ndarray
    • 可以有多个dim,本质上是张量
      a.shape=(2, 3, 4),其中dim=0的元素是(3, 4)数组(最外面的中括号),dim=1的元素是(4)数组,dim=2的元素是数
      对某一个dim(或者axis)操作就是把这个dim对应的元素作为整体操作,如sum操作后的维度就是去掉被操作的那个维度(即,沿着哪个方向把长方体拍扁):
  • 维度操作
    • a.ndim获取轴的个数
      a.shape获取各个维度的长度,上例中返回(2,3,4)
      a.size元素总个数,上例中为2*3*4=24
      np.reshape(a, shape)/a.reshape(shape)调整维度(均不改变a!!)。注意这里不会进行深拷贝,改变返回后数组的元素,原数组对应元素的值也会改变
      a.T a.transpose() 对换所有维度,(2,3,4)→(4,3,2)
      a.swapaxes(x, y)对换两个轴
      np.expand_dims(a, axis=)在指定位置插入维度“1”
      切片操作的None也可以用于扩维。a[:,:,None,:]【逗号勿省略】即扩为(2,3,1,4)
      np.squeeze(a, axis=)在指定位置删除一个维度
  • 生成
    • np.empty(shape)未初始化的数组(里面是随机的数,不一定是0)
      np.zeros(shape) np.ones(shape) 全0/全1数组
      np.zeros_like(X) np.ones_like(X) 与X形状相同的数组
      np.rand(shape)等 随机
      np.arange 相当于range
      np.linspace(l, r, num)等差序列
      np.logspace(l, r, num)等比序列
  • 切片、索引
    • 上例中,a[:,:,1]a[...,1]等价,a[1]a[1,...]a[1,:,:]等价
      相应地,每个维度也可以替换为int数组(注意对应关系,不是每个逗号隔开对应一个坐标,而是。太难表述了)或者bool数组。如果同一个维度放了多个int,则会升维。bool数组不能放多个
      注意到,如果我们先定义了一个数组b,b自身的中括号会使得a[b]的结果与我们想要的并不同,如:
      我们本意是想取a[0][1],但是程序解析结果是a[[0, 1],:,:],于是会取成[a[0],a[1]]。本质上,是因为tuple下标和list下标的含义是不一样的,前者是分别在不同轴上取,后者是在同一个轴上取多个。这时就需要下面的函数了
      np.take_along_axis(a, indices, axis)
      indices必须与a同维度,但不必同大小。如取a的axis=1,b可以为(1, 2, 1),另两个维度会自动广播。最后的结果形状与a除了操作的轴长度有变化之外都相同。
      相应地,也可以往指定轴上填充一些数
      numpy.put_along_axis(aindicesvaluesaxis)
      indices与前面要求相同,values“长度”与indic对应,而其中每个元素应符合a去掉操作维度后的形状(或者能够被广播)
  • 广播
    • “前面”不足的维数自动升维,注意只能补足前面的维数
  • 统计
np.unique(a, return_index, return_inverse, return_counts) 去重
return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储
return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储
return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数
np.amin(a, axis=None, keepdims, initial, where)
axis: 可选参数,用于指定在哪个轴上计算最小值。如果不提供此参数,则返回整个数组的最小值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。
keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴。
np.amax np.mean np.sum等同理
  • 线性代数
numpy.dot() 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为向量点积);对于二维数组,计算的是两个数组的矩阵乘积;对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和: 
dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])。 注意,dot和@运算符不同。如果对3维张量进行运算,前者得到4维张量,后者得到3维张量(相当于在第1维进行for循环):

# ArgParse

第一项:若干个名字,可以是"version""--version""-v" 等,默认以第一个为args中的变量名。带-的为可选项。
help:当调用--h时显示
action:该参数后(可能)不再跟东西,而是见到这个参数就执行相应的action,比如store_true、count、append(要跟东西)
default:如果该参数没有输入就会返回None,为防止后续类型出错,赋予其默认值
type:指定参数后面跟的东西的类型
choice:指定参数后面跟的东西有哪些选项
nargs:这个参数后面跟几个东西,默认为1。*、+表示任意数量

# Pickle

Create portable serialized representations of Python objects.可以把程序中的对象存到文件中(包括变量类型),而不必担心具体的存储过程
pickle.dump(obj, f)把对象obj存到已经打开的文件f中(f是文件对象,不是路径)
pickle.load(f)把文件f中的对象读取并返回
 
微电子与电路基础C++