NumPy

NumPy 是 Python 中用于科学计算的基本包。它是一个 Python 库,提供了一个多维数组对象、各种派生对象(比如屏蔽数组和矩阵) ,以及一系列用于数组快速操作的例程,包括数学、逻辑、形状操作、排序、选择、 i/o、离散傅里叶变换、基本线性代数、基本统计操作、随机模拟等等。

官网文档地址:https://numpy.org/

单纯学习 Numpy 会比较闷,因为 Numpy 是用于科学计算的。只是学习了各种 API 的使用,会很苦闷学来干啥,跟人工智能有什么关系?

安装 numpy 比较简单,直接使用命令安装即可:

pip install numpy

测试是否正常:

import numpy as np
print(np.__version__)

基础使用

基本数据类型

下表列举了常用 NumPy 基本类型。

名称 描述
bool_ 布尔型数据类型(True 或者 False)
int_ 默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc 与 C 的 int 类型一样,一般是 int32 或 int 64
intp 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8 字节(-128 to 127)
int16 整数(-32768 to 32767)
int32 整数(-2147483648 to 2147483647)
int64 整数(-9223372036854775808 to 9223372036854775807)
uint8 无符号整数(0 to 255)
uint16 无符号整数(0 to 65535)
uint32 无符号整数(0 to 4294967295)
uint64 无符号整数(0 to 18446744073709551615)
float_ float64 类型的简写
float16 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_ complex128 类型的简写,即 128 位复数
complex64 复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128 复数,表示双 64 位浮点数(实数部分和虚数部分)

每个内建类型都有一个唯一定义它的字符代码,如下:

字符 对应类型
b 布尔型
i (有符号) 整型
u 无符号整型 integer
f 浮点型
c 复数浮点型
m timedelta(时间间隔)
M datetime(日期时间)
O (Python) 对象
S, a (byte-)字符串
U Unicode
V 原始数据 (void)

numpy 有个 dtype 函数,用于定义变量类型,其定义如下:

class numpy.dtype(dtype, align=False, copy=False[, metadata])

比如这段代码定义了一个numpy 中 int32 类型的变量:

import numpy as np
a = np.dtype(dtype="int32")
print(a)

也可以使用短代码:

import numpy as np
a = np.dtype("i")
print(a)

等效代码:

import numpy as np
a = np.dtype(np.int32)
print(a)

运行代码后,都会打印:

int32

这个类型是 numpy 中的类型,不是 Python 中的类型,要注意区分。numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 np.bool_,np.int32,np.float32,等等。

因为 Python 是弱类型,没有 int32 a = ... 这种语法,所以为了明确定义这个变量是何种类型,需要使用类型的字符串名称。

这句话现在可以先不管,后面会在很多地方使用 dtype,用熟了就知道了。

要注意的是 np.dtype 是创建一个类型标识,本身并没有存储变量值。

示例:

import numpy as np

def test(object, dtype):
if dtype == np.int32:
print(f"{object} int32") elif dtype == np.int64:
print(f"{object} int64") elif dtype == np.str_:
print(f"{object} str_") a = 111
b = np.dtype(dtype="int32")
test(a, b) c = '111'
d = np.dtype(dtype="str")
test(c, d)

创建基本数组

Numpy 提供了一个多维数组对象、各种派生对象(比如屏蔽数组和矩阵) ,numpy 中最重要的对象是数组和矩阵。所以要学会 numpy ,最基本的是学会 numpy 数组。

numpy 创建数组的定义:

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

参数说明:

名称 描述
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度

创建一个基本数组:

import numpy as np
a = np.array([1, 2, 3])

创建多维数组

import numpy as np
a = np.array([[1, 2], [3, 4]])
print (a)

定义一个数组,然后生成多维数组:

import numpy as np
a = np.array([1, 2, 3, 4, 5], ndmin = 2)
# 相当于 np.array([[1, 2, 3, 4, 5]])
print (a) b = np.array([1, 2, 3, 4, 5], ndmin = 3)
# 相当于 np.array([[[1, 2, 3, 4, 5]]])
print (b) c = np.array([[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]], ndmin = 3)
# 相当于 np.array([[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]]])
print (c)

数组属性

由于 Python 是弱类型,所以想学习和了解细节的时候,会比较懵逼。因此,我们尽量在编写 Python 代码时,获取代码的一些文档注释。

如下面代码中,定义了一个数组:

import numpy as np
a = np.array([[1, 2], [3, 4]])
print (a)

numpy 的数组,其类型为 ndarray[Any, dtype],完整文档如下:

a: ndarray[Any, dtype] = np.array([[1,  2],  [3,  4]])

所以,要掌握 numpy 数组,实际上就是在了解 ndarray

ndarray 中比较重要的属性如下:

属性 说明
ndarray.ndim 秩,即轴的数量或维度的数量
ndarray.shape 数组的维度,对于矩阵,n 行 m 列
ndarray.size 数组元素的总个数,相当于 .shape 中 n*m 的值
ndarray.dtype ndarray 对象的元素类型
ndarray.itemsize ndarray 对象中每个元素的大小,以字节为单位
ndarray.flags ndarray 对象的内存信息
ndarray.real ndarray元素的实部
ndarray.imag ndarray 元素的虚部
ndarray.data 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。

回到之前提到过的 numpy.dtype,结合 numpy.array,其示例代码如下:

import numpy
import numpy as np a = np.array([1, 2])
print(a.dtype)
print(a) t = np.dtype(numpy.float64)
b = np.array(object=[1, 2], dtype=t)
print(b.dtype)
print(b)

如果我们不配置 dtype 参数,那么数组的 dtype 会以数组元素类型为依据。如果配置了 dtype,那么数组元素都会被转换为对应的类型,如 np.array(object=[1, 2], dtype='float64')

数组生成

zeros、ones、empty 数组生成

numpy.zeros

numpy.zeros 的作用是创建一个元素全部为 0 的数组。

其定义如下:

def zeros(shape, dtype=float, order='C', *, like=None, /)
参数 描述
shape 数组形状
dtype 数据类型,可选
order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。

创建一个全部由 0 填充的数组:

import numpy as np

# 长度为 2
a = np.zeros(2)
print(a)

np.zeros() 默认创建的数组是 float64 类型,如果需要自定义类型,可以使用 dtype:

import numpy as np

# 长度为 2
a = np.zeros(2,dtype=int)
print(a)

numpy.ones

ones 创建一个元素值均为 1 的数组。

其定义如下:

def ones(shape, dtype=None, order='C', *, like=None)

示例如下:

import numpy as np

# 长度为 2
a = np.ones(2,dtype=int)
print(a)

由于其 API 与 numpy.zeros 一致,因此不再赘述。

numpy.empty

创建一个指定长度的空数组,但是不会对内存区域进行初始化,所以其被分配的内存区域可能已经有值

其定义如下:

def empty(shape, dtype=None, order='C', *args, **kwargs)

示例:

import numpy as np

# 长度为 2
a = np.empty(2)
print(a)

由于其没有初始化内存,因此内存区域会残留数据。

其它说明

此外,还有三个对应的原型复制函数:

def empty_like(prototype, dtype=None, order=None, subok=None, shape=None
def zeros_like(prototype, dtype=None, order='K', subok=True, shape=None)
def ones_like(prototype, dtype=None, order='K', subok=True, shape=None)

它们的作用是根据数组类型,拷贝一个相同的结构,然后填充对应值。

如下示例,复制数组相同的结构,但是填充的值为 0。

import numpy as np

a = np.array([[1],[1]])
b = np.zeros_like(a)
print(b)

此外,这三个函数,可以传递元组,生成多维的数组(矩阵)。

import numpy
import numpy as np a = np.zeros(shape=(2, 3, 4), dtype=numpy.double)
print(a)

numpy.random

numpy.random 是一个类,不是一个函数,numpy.random 中有一些随机生成数组的函数。

以下是一些常用的 API:

#生成具有给定形状的均匀分布的随机样本,范围在[0, 1)之间。
numpy.random.rand(size) # 生成具有给定形状的标准正态分布(平均值为0,方差为1)的随机样本。随机样本取值范围是[0,1)。
numpy.random.randn(size) # 正态分布,指定均值和方差
numpy.random.normal(loc=0.0, scale=1.0, size=None) # 随机生成
numpy.random.random(size=None) # 从给定的上下限范围内生成随机整数。
numpy.random.randint(low, high=None, size=None, dtype=int) # 从给定的一维数组中生成随机样本。
numpy.random.choice(a, size=None, replace=True, p=None) # 随机打乱给定数组的顺序。
numpy.random.shuffle(x)

随机数值生成和正态分布生成示例如下:

import numpy as np

a = np.random.rand(10)
b = np.random.rand(10)
print(a)
print(b)
[0.39809428 0.83922059 0.10808865 0.00332159 0.75922001 0.26850704
0.04497839 0.59012908 0.0438718 0.59988563]
[0.78161896 0.91401858 0.10980276 0.89723959 0.06802148 0.18993732
0.10664519 0.14121531 0.27353601 0.56878734]

x1 = np.random.randint(10, size=6) # 一维数组
x2 = np.random.randint(10, size=(3, 4)) # 二维数组
x3 = np.random.randint(10, size=(3, 4, 5)) # 三维数组

对于其它 API,由于篇幅有限,不再赘述。

numpy.arange

numpy.arange 用于有规律地生成数组。

其定义如下:

numpy.arange([start, ]stop, [step, ]dtype=None, *, like=None)
参数 描述
start 起始值,默认为0
stop 终止值(不包含)
step 步长,默认为1
dtype 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。

numpy.arange 默认从 0 开始生成数组,间隔为 1。

比如,下面代码会生成一个元素值不超过 4 的数组,即范围是 [0,4)

import numpy as np

# 长度为 4
a = np.arange(4)
print(a)

arange(start, stop) 指定开始结束范围,但是依然步长为 1。

import numpy as np

# 长度为 4
a = np.arange(1,4)
print(a)

arange(start, stop, step) 自定义设置范围和步长。

import numpy as np

# 长度为 4
a = np.arange(1,10,3)
print(a)

numpy.linspace

numpy.linspace 可以使用线性间隔的方式生成数组:

np.linspace(0, 10, num=5)

num=5 的含义是从来的之间平均取得 5 个数值。

[ 0.
2.5
5.
7.5
10. ]

但是跟我们预料的结果可能不太一样,因为 linspace() 是包括起始点的,所以 0-10 其实个数是 11 个。

import numpy as np

# 长度为 4
a = np.linspace(0, 10, num=10)
print(a)

import numpy as np

# 长度为 4
a = np.linspace(0, 10, num=11)
print(a)

数组操作

数组排序

排序会返回数组的副本。

主要排序函数如下:

sort :按照大小排序

argsort:它是沿指定轴的间接排序,

lexsort:它是对多个键的间接稳定排序,

searchsorted, 它将查找排序数组中的元素。

partition, 分区,这是一个部分排序。

对于 numpy 的数组,请使用 numpy 的函数排序,不要使用 Python 自带的函数排序。

import numpy as np

# 长度为 4
a = np.random.rand(10) print(a) # 使用 Python 内置函数
print(sorted(a)) # 使用 numpy.sort
print(np.sort(a))

如上图所示,使用 Python 自带的函数,会导致精确度出现问题。

切片索引

可以使用 slice(start,stop,step) 函数或 [start:stop:step] 进行切片。

import numpy as np

a = np.arange(10)
print(a) # 索引范围是 2-7 ,间隔为2
# [0 1 2 3 4 5 6 7 8 9]
s1 = slice(2, 7, 2) # 索引范围是 2-8 ,间隔为2
# [0 1 2 3 4 5 6 7 8 9]
s2 = slice(2, 8, 2) print(a[s1])
print(a[s2])

等同于:

import numpy as np

a = np.arange(10)
print(a) print(a[2:7:2])
print(a[2:8:2])

对于二维数组,可以通过坐标点取值。

import numpy as np

x = np.array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11]]) # 左上角、右上角、左下角、右下角 四个点
a1 = np.array([[0, 0], [3, 3]])
a2 = np.array([[0, 2], [0, 2]]) y = x[a1, a2]
print(y)
[[ 0  2]
[ 9 11]]

取值时,跟一维数组一致,可以通过索引取值。

import numpy as np

x = np.array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11]]) y = x[1:2]
print(y)

数组还可以通过表达式取值,如 x>5x<5 等。

import numpy as np

x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print(x) print(x[x > 5])

详细的表达式操作方法,可以查阅官网文档,这里不再赘述。

数组运算符

numpy 数组,可以通过操作符直接操作。

如两个数组的值相加:

import numpy as np

a1 = np.array([1, 2, 3])
a2 = np.array([4, 5, 6]) a3 = a1 + a2
a4 = a1 * a2
print(a3)
print(a4)

得到:

[5 7 9]
[ 4 10 18]

广播规则

对于不同形状的数组(即维数不同),numpy 可以自动补全维数。

其规则约束如下:

  • 两个数组的形状相同

  • 维数比较少的数组,需要是一维数组。

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]) b = np.array([100, 100, 100])
print(a + b)

[						[
[1, 2, 3] + [100, 100, 100]
[4, 5, 6] + [100, 100, 100]
[7, 8, 9] + [100, 100, 100]
] ]

相加后:

[
[101 102 103]
[104 105 106]
[107 108 109]
]

但是要注意,如果两个数组的一个维中,元素个数不一致,则运算会报错。

import numpy as np

a1 = np.array([1, 2, 3])
a2 = np.array([4, 5, 6, 7]) a3 = a1 + a2
print(a3)

如果两个数组维度一致,但是形状不一样,维数少的数组必须是一维数组。

如下面代码会报错:

import numpy as np

a = np.array([[1, 2, 3],
[1, 1, 1],
[1, 1, 1]]) b = np.array([[1, 1, 1],
[2, 2, 2]])
print(a + b)

修改数组

Numpy 中包含了一些函数用于处理数组,大概可分为以下几类:

  • 修改数组形状
  • 翻转数组
  • 修改数组维度
  • 连接数组
  • 分割数组
  • 数组元素的添加与删除

修改数组的形状

主要有以下函数:

函数 描述
reshape 不改变数据的条件下修改形状
flat 数组元素迭代器
flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
ravel 返回展开数组

将一维数组,转换为二维数组,每个数组元素有 3 个,其示例如下:

import numpy as np

a = np.arange(6).reshape(2, 3)
b = np.array([0,1,2,3,4,5]).reshape(2, 3)
print(a)
print(b)
[[0 1 2]
[3 4 5]]
[[0 1 2]

其它几个函数可以使用以下示例表达:

import numpy as np

a = np.arange(10)
print(a) # 数组迭代器 .flat
for element in a.flat:
print(element) # 将数组转换为二维数组
b = a.reshape(2,5)
print("将数组转换为二维:")
print(b) print("将多维数组合并为一维:")
c = b.ravel()
print(c)
[0 1 2 3 4 5 6 7 8 9]
0
1
2
3
4
5
6
7
8
9
将数组转换为二维:
[[0 1 2 3 4]
[5 6 7 8 9]]
将多维数组合并为一维:
[0 1 2 3 4 5 6 7 8 9]

翻转数组

其常用函数定义如下:

函数 描述
transpose 对换数组的维度
ndarray.T self.transpose() 相同
rollaxis 向后滚动指定的轴
swapaxes 对换数组的两个轴

transposendarray.T 都可以将数组翻转,例如将 2x5 的数组翻转为 5x2

import numpy
import numpy as np a = np.arange(10).reshape(2,5)
print(a)
b = numpy.transpose(a)
c = a.T
print(b)
print(c)
[[0 1 2 3 4]
[5 6 7 8 9]]
[[0 5]
[1 6]
[2 7]
[3 8]
[4 9]]
[[0 5]
[1 6]
[2 7]
[3 8]
[4 9]]

rollaxisswapaxes 都有三个参数:

arr:数组
axis:要向后滚动的轴,其它轴的相对位置不会改变。取值范围为 [0, a.ndim]
start:默认为零,表示完整的滚动。会滚动到特定位置。取值范围为 [-a.ndim, a.ndim]

注意:二维只有 01 两个轴,三维有 012 三个轴。axis、start 都是填写轴的序号。

使用 print(a1.ndim) 可以打印数组的维数,即轴数。

swapaxes 用于指定交互两个轴的位置。

如:

import numpy
import numpy as np a1 = np.array([
[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]
]) b = np.swapaxes(a1, 0, 1) print(b)

原数组:

[[0, 0, 0, 0]
[1, 1, 1, 1]
[2, 2, 2, 2]
[3, 3, 3, 3]]

变换后的数组:

[[0 1 2 3]
[0 1 2 3]
[0 1 2 3]
[0 1 2 3]]

也可以理解成坐标系的 x 轴 和 y 轴,x 轴变成了 y 轴。

swapaxes 在更多维数组的情况下,有更多的轴,例如三维的 x、y、z 三个轴。这里不再赘述。

至于 numpy.rollaxis ,我也不会。

修改数组维度

其主要函数如下:

维度 描述
broadcast 产生模仿广播的对象
broadcast_to 将数组广播到新形状
expand_dims 扩展数组的形状
squeeze 从数组的形状中删除一维条目

连接数组

其主要函数如下:

函数 描述
concatenate 连接沿现有轴的数组序列
stack 沿着新的轴加入一系列数组。
hstack 水平堆叠序列中的数组(列方向)
vstack 竖直堆叠序列中的数组(行方向)

numpy.concatenate 将两个数组拼接成一个新的数组:

import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8]) c = np.concatenate((a, b))
print(c)

分割数组

其主要函数如下:

函数 数组及操作
split 将一个数组分割为多个子数组
hsplit 将一个数组水平分割为多个子数组(按列)
vsplit 将一个数组垂直分割为多个子数组(按行)

其使用方法比较简单,这里不再赘述。

增删数组元素

其主要函数如下:

函数 元素及描述
resize 返回指定形状的新数组
append 将值添加到数组末尾
insert 沿指定轴将值插入到指定下标之前
delete 删掉某个轴的子数组,并返回删除后的新数组
unique 查找数组内的唯一元素

其使用方法比较简单,这里不再赘述。

数组迭代

前面提到过 .flat

import numpy as np

# 这里是二维
a = np.arange(10).reshape(2,5) # 数组迭代器 .flat
for element in a.flat:
print(element)

.flat 会按照顺序打印每一个元素。

0
1
2
3
4
5
6
7
8
9

.nditer 也是如此。

import numpy as np

a = np.arange(10).reshape(2,5)

# 数组迭代器 .flat
for element in np.nditer(a):
print(element)

.nditer 可以控制遍历规则。

for x in np.nditer(a.T, order='C'),默认,行遍历。

for x in np.nditer(a, order='F'),列遍历。

import numpy as np

a = np.arange(10).reshape(2, 5)

# 数组迭代器 .flat
for element in np.nditer(a, order='F'):
print(element)
0
5
1
6
2
7
3
8
4
9

.nditer 可以控制迭代多维数组的维还是元素。

前面提到的代码,均是迭代逐个元素。

如果设置了 flags 参数,则可以迭代维。

import numpy as np

a = np.arange(10).reshape(2, 5)

# 数组迭代器 .flat
for element in np.nditer(a, order='F', flags=['external_loop']):
print(element)
原数组:
[[0 1 2 3 4]
[5 6 7 8 9]] 按照迭代方向 F:
[0 5]
[1 6]
[2 7]
[3 8]
[4 9]

Python 之 Numpy 框架入门的更多相关文章

  1. Python Flask Web 框架入门

    Python Flask 目录 本文主要借鉴 letiantian 的文章 http://www.letiantian.me/learn-flask/ 一.简介 二.安装 三.初始化Flask 四.获 ...

  2. [Python] Scrapy爬虫框架入门

    说明: 本文主要学习Scrapy框架入门,介绍如何使用Scrapy框架爬取页面信息. 项目案例:爬取腾讯招聘页面 https://hr.tencent.com/position.php?&st ...

  3. 比我的脸还干的gan货——Python Flask Web 框架入门

    Flask是一个轻量级的基于Python的web框架. 本文适合有一定HTML.Python.网络基础的同学阅读. 1. 简介 这份文档中的代码使用 Python 3 运行.是的,所以读者需要自己在电 ...

  4. Python爬虫Scrapy框架入门(0)

    想学习爬虫,又想了解python语言,有个python高手推荐我看看scrapy. scrapy是一个python爬虫框架,据说很灵活,网上介绍该框架的信息很多,此处不再赘述.专心记录我自己遇到的问题 ...

  5. Python selenium自动化测试框架入门实战--登录测试案例

    本文为Python自动化测试框架基础入门篇,主要帮助会写基本selenium测试代码又没有规划的同仁.本文应用到POM模型.selenium.unittest框架.configparser配置文件.s ...

  6. Python爬虫Scrapy框架入门(1)

    也许是很少接触python的原因,我觉得是Scrapy框架和以往Java框架很不一样:它真的是个框架. 从表层来看,与Java框架引入jar包.配置xml或.property文件不同,Scrapy的模 ...

  7. Python的Flask框架入门-Ubuntu

    全文请见tuts code:An Introduction to Python's Flask Framework Flask是Python一个小而强大的web框架.学起来简单,用起来也容易,能够帮你 ...

  8. Python爬虫Scrapy框架入门(2)

    本文是跟着大神博客,尝试从网站上爬一堆东西,一堆你懂得的东西 附上原创链接: http://www.cnblogs.com/qiyeboy/p/5428240.html 基本思路是,查看网页元素,填写 ...

  9. Python爬虫Scrapy框架入门(3)

    往往需要爬取的网页是呈一个树状结构.比如,需要先爬取一个目录,然后再在目录中选择具体的爬取目标.而目录和具体目标之间,网页结构不同,使得我们不能使用相同的爬取策略. 从之前的经验来看,我们对scrap ...

  10. Python云端系统开发入门——框架基础

    Django框架基础 这是我学习北京理工大学嵩天老师的<Python云端系统开发入门>课程的笔记,在此我特别感谢老师的精彩讲解和对我的引导. 1.Django简介与安装 Django是一个 ...

随机推荐

  1. 王道oj/problem23

    网址:oj.lgwenda.problem/23 代码: #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include<stri ...

  2. 天地图三维帮助文档(Cesium)

    https://blog.csdn.net/Tmraz/article/details/114977652

  3. filter() 函数的学习

    1.    filter() 函数 用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换.该接收两个参数, 第一个为函数,第二个为序列,序列的每个 ...

  4. 产品代码都给你看了,可别再说不会DDD(一):DDD入门

    这是一个讲解DDD落地的文章系列,作者是<实现领域驱动设计>的译者滕云.本文章系列以一个真实的并已成功上线的软件项目--码如云(https://www.mryqr.com)为例,系统性地讲 ...

  5. 《SQL与数据库基础》08. 多表查询

    目录 多表查询 多表关系 一对多 多对多 一对一 多表查询概述 分类 内连接 外连接 自连接 联合查询 子查询 分类 标量子查询 列子查询 行子查询 表子查询 案例 本文以 MySQL 为例 多表查询 ...

  6. Java单元测试及常用语句

    1 前言 编写Java单元测试用例,即把一段复杂的代码拆解成一系列简单的单元测试用例,并且无需启动服务,在短时间内测试代码中的处理逻辑.写好Java单元测试用例,其实就是把"复杂问题简单化, ...

  7. Nomad系列-Nomad网络模式

    系列文章 Nomad 系列文章 概述 Nomad 的网络和 Docker 的也有很大不同, 和 K8s 的有很大不同. 另外, Nomad 不同版本(Nomad 1.3 版本前后)或是否集成 Cons ...

  8. KRPano动态热点专用素材图50多个,加动态热点使用方法

    KRPano动态热点专用素材是一种特定形式的序列图,该序列图要求帧的水平和垂直的具体位置必须准确,否则图的动作将会出现错乱,KRPano不支持动态图.目前网上比较匮乏动态热点素材,在此亲手整理制作了5 ...

  9. windows 网络模拟工具分享

    [下载地址] Releases · jagt/clumsy · GitHub [介绍] 无需安装 无需篡改和代理 系统级限制,不针对单个程序,但可以针对单个IP 离线也可以限制,随停随用 界面简单 [ ...

  10. 洛谷P2433 小学数学 N 合一

    写完了这道题结果脑子断电把浏览器关了......打开一看 没保存 寄 传送门:[深基1-2]小学数学 N 合一 - 洛谷 第一题 第二题 第三题 这几道题没啥好说的,直接输出就彳亍了 cout < ...