感觉自己学的 Python 基本是翻译 C++,开坑
虽然标题带个 1,但是不一定会有下集的样子(
Python 基础
字符串
Python 里可以用 + 来拼接字符串,像这个样子:
s1 = 'me'
s2 = 'w'
s3 = s1 + 'o' + s2
print(s3)
# output:
# meow
Python 里字符串可以单引号还可以双引号,用单引号的话打双引号就不用转义了,反之同理,同时可以用列表的方法对它切片(左开右闭,有负数是倒着取,但是不能同时用正负来切)
s1 = "m'eo'wme"
s2 = 'ow"me"ow'
print(s1[:4] + s2[-4:])
# output:
# m'eoe"ow
然后一个比较神奇的是三单引号和三双引号,作用有点像 C++ 的 raw
,不过也不完全是,因为转义符还是有用的,它们并不会和不同类型的引号冲突。
s1 = '''meo'w'm
e"o"w'''
s2 = """meo'''w\nme'''ow"""
print(s1, s2)
# output:
# meo'w'm
# e"o"w meo'''w
# me'''ow
对字符串进行一些格式化:
s1 = 'meOw meoWmeow'
print(s1.upper())
print(s1.lower())
print(s1.title())
# output:
# MEOW MEOWMEOW
# meow meowmeow
# Meow Meowmeow
因为 print
自带换行,有时需要过滤字符串两边的空白字符:
s1 = '\tmeow \n'
print(s1)
print(s1.lstrip())
print(s1.rstrip())
print(s1.strip())
# output:
# meow
#
# meow
#
# meow
# meow
IO
print
的其他参数:end
, sep
, file
, flush
print('meow', end='') # end 是输出所有后附加的字符,默认为换行符
print('me', 'ow', sep='_') # sep 是输出逗号隔开的项时,中间插入的符号,默认为空格
print('meow', file=open('meow.txt', 'w')) # 用来输出至文件,另一种文件输出方法见后
print('meow', flush=True) # 置为 True 时立刻输出缓冲区所有内容,默认为 False
几种 print
格式化:
num = 114514
s1 = 'me'
s2 = 'ow'
print(s1 + s2 + str(num))
print(num, s1, s2)
print('{1}, {2}{2} {0}.'.format(num, s1, s2)) # 用对应位置替换
print('%s, %s%s %d.' % (s1, s2, s2, num)) # 和 C 的 printf 差不多
print(f'{s1}, {s2} {s2 + str(num)}.') # 直接塞表达式进去
# output:
# meow114514
# 114514 me ow
# me, owow 114514.
# me, owow 114514.
# me, ow ow114514.
附赠一个用来做标题效果的,会把相应文本放在居中位置,给定长度的剩余部分用给定符号填充:
print('meowmeow'.center(20, '+'))
# output:
# ++++++meowmeow++++++
可以用 ANSI 转义码给输出加颜色,具体建议百度
Python 的输入 input
默认是字符串型,所以有时输入时要进行强转,用 split
来同时输入多个用空格分隔的值,这里的 map
(映射)和 C++ 里不是一个东西,相当于对 input().split()
这个列表中每个元素使用函数 int
后,返回由对应函数值组成的列表
a, b = input().split()
c, d = map(int, input().split())
print(a + b)
print(c + d)
# input:
# 12 34
# 56 78
# output:
# 1234
# 134
然后 input
可以接收一个字符串参数,作为接受输入之前的提示语,学过 Py 的舍友上 C 语言课的时候为这个事情困惑了很久,然后之前 print
的格式化其实是对字符串参数进行了格式化,所以这里也可以用,比如:
for i in range(1, 4):
tmp = input(f'Input #{i}: ')
文件输入例:读取文件输出至终端
file_name = '12/12.py'
with open(file_name, 'r') as file_obj:
for line in file_obj:
print(line.rstrip())
另一种写法是这样的,因为 lines 是列表,可以随机访问某一行
file_name = '12/12.py'
with open(file_name, 'r') as file_obj:
lines = file_obj.readlines()
for line in lines:
print(line.rstrip())
文件输出:
(与 print
不同,这里的 write
不会自己换行)
file_name = 'meow.txt'
with open(file_name, 'w') as file_obj:
file_obj.write('meow\n')
file_obj.write('meow\n')
json 存储数据:
import json
file_name = 'meow.json'
meow = [3, 5, 7]
# 存入
with open(file_name, 'w') as file_obj:
json.dump(meow, file_obj)
# 读取
with open(file_name, 'r') as file_obj:
meowmeow = json.load(file_obj)
print([i for i in meowmeow])
迭代器
迭代是以某种遍历方式将对象中元素依次取出,python 的 for ... in ...
用的就是迭代的方法
迭代器有 iter
和 next
两个方法,调用前者创建对象的一个迭代器,调用后者获得迭代器的下一个值并向后迭代,for
里就是这样不断迭代的
想要定义一个可迭代的对象,需要给它写 __iter__
和 __next__
两个方法 (家人们谁懂啊就因为这俩玩意的下划线在 markdown 会变成奇怪的东西回去把全文函数变量名一个一个改成代码段),其他事情就可以交给 for
做了
比如说写一个算斐波那契数列的就是:
class Fib:
def __init__(self, n):
self.n = n
def __iter__(self):
self.x = 0
self.y = 1
return self # 这是规定的
def __next__(self):
t = self.y
self.y = self.x + self.y
self.x = t
self.n -= 1
if self.n >= 0:
return t
else:
raise StopIteration
meow = Fib(9)
for i in meow:
print(i, end=' ')
# output:
# 1 1 2 3 5 8 13 21 34
生成器
用 for
生成器表达式生成列表:
a = [f'meow{i}' for i in range(1, 9, 3)]
print(a)
tmp = [1, 9, 3]
for i in range(*[j for j in tmp]):
print(i, end=' ')
# output:
# ['meow1', 'meow4', 'meow7']
# 1 4 7
列表前加 *
可以把列表解成独立的元素,可以当作参数传递
对于字典加 *
得到所有的 key
,加 **
得到所有的 value
用 yield
写生成器函数:
生成器是一种特殊的迭代器,下例用了它可迭代的性质,生成器函数每次在 yield
返回后,下次调用它会从上次 yield
的位置开始,以下是算菲波纳契数列的例子
def func(n):
x = 0
y = 1
while n > 0:
t = y
y = x + y
x = t
n -= 1
yield t
for i in func(10):
print(i, end=' ')
# output:
# 1 1 2 3 5 8 13 21 34 55
类型标注
声明时用,虽然很像 C++,但其实没有实际作用,只是一种注释,得搭配编辑器的提示使用,例如:
meow:int = 3.43 # 仍然会赋成 3.43
meow:list[str] = ['me', 'ow'] # vscode 的提示只看最后一个
meow:tuple[int, float, str] = (114514, 2.33, 'meow')
def meow(me:int, ow:float = 2.33)->str:
pass # sth
NumPy
提供了很多矩阵运算相关的功能,可能有用……
常用运算
对位的加减乘除,指对,三角,双曲,开根,绝对值,上下取整.
加减乘除、指对中如果给一个数 x
作为参数,等价于给一个全 x
矩阵
加减乘除是直译,其他函数名都和 C++ 的一样
四舍五入 np.round()
但是 NumPy 不自带高精,要注意溢出的问题,有时需要手动指定数据类型
import numpy as np
a = np.array([1, 2], dtype=int64)
矩阵 / 线性代数相关
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[1, 2, 4], [3, 4, 6]])
c = np.array([[1, 3], [2, 4], [3, 5]])
d = np.array([[1, 3], [4, 5]])
res = a + b # 加法
res = 3 * a # 数乘
res = a * b # 对应位置相乘
res = np.dot(a, c) # 矩阵乘法
res = np.transpose(res) # 转置
res = np.linalg.inv(d) # 矩阵求逆
res = np.linalg.det(d) # 行列式
res = np.linalg.matrix_rank(a) # 秩
res = np.linalg.eig(d) # 特征值和特征向量
# 解线性方程组
# 10x - y - 2z = 72
# - x + 10y - 2z = 83
# - x - y + 5z = 42
A = np.array([[10, -1, -2], [-1, 10, -2], [-1, -1, 5]])
b = np.array([72, 83, 42])
res = np.linalg.solve(A, b)
print(res)
统计计算
求和 np.sum()
均值 np.mean()
方差 np.var()
标准差 np.std()
最值 np.min()
np.max()
中位数 np.median()
百分位数 np.percentile()
可选参数 axis
:按哪个轴做,置 None 表示对全局做
数据生成
import numpy as np
a = np.zeros((3, 3)) # 全 0
a = np.ones((3, 4, 5)) # 全 1
a = np.random.rand(2, 3) # 均匀分布随机数 [0, 1)
a = np.random.randn(3, 4, 5) # 正态分布随机数
# 以上的参数为尺寸
a = np.random.randint(2, 3564) # 随机整数
# 参数是随机的范围
np.random.shuffle(a) # 随机打乱,似乎只能用于一维数组
数据操作
a = np.reshape(a, (6, 1)) # 重新切分(总个数需相同)
c = np.concatenate((a, b), axis=None) # 数组连接
# 参数 axis: 按哪个轴连接,置 None 为拍成一维再连接
c = np.split(a, (1, 3, 5,), axis=1) # 数组分割
# 第二个参数如果写成数组,就是按这些下标的位置依次切割,若是一个数,就是平均分成给定份
# 参数 axis: 按哪个轴分割(看成连接的逆)
c = np.sort(a, axis=0) # 数组排序
d = np.argsort(a, axis=1) # 返回排序索引(排序后各数在原数组的下标)
# 参数 axis: 按哪个轴排序,置 None 为拍成一维再排序
c = np.partition(a, kth=(0, 5), axis=1) # 部分排序,类似于 kth_element
d = np.argpartition(a, kth=-4, axis=1) # 部分排序索引
# 参数 kth: 这些位置的数要求在正确的位置上,其他数与这些数没有逆序对,置负数即定位最大的若干个
# 参数 axis: 同 sort
其他
Python 的数组赋值和 C++ 里头直接赋值相当于赋指针,不能单独修改,复制数组时要用 copy()
以上提到的许多函数似乎都有被封装到类里,func(a, ...)
能写成 a.func(...)
这样子