dtype=int
本文最后更新于4 天前,其中的信息可能已经过时,如有错误请发送邮件到184874483@qq.com
import numpy as np

N, M, P = map(int, input().split())
print(np.zeros((N, M, P), dtype=int))
print(np.ones((N, M, P), dtype=int))

为什么 numpy.zeros((N, M, P)) 里面要写“双层括号”

这个问题本质上是在问:

为什么不是 numpy.zeros(N, M, P),而是 numpy.zeros((N, M, P))

关键原因只有一句话:

zeros() 需要的不是 3 个分开的数字,而是 1 个“形状 shape 参数”。这个 shape 参数本身要写成一个元组。


先看最外层括号和里层括号分别在干什么

这句代码:

numpy.zeros((N, M, P))

其实可以拆成两层来看。

第一层括号:函数调用的括号

最外面这一层:

zeros(...)

表示“调用函数”。

也就是说,你在调用 numpy.zeros 这个函数,并把某个参数传进去。


第二层括号:元组 tuple 的括号

里面这一层:

(N, M, P)

表示一个元组,也就是一个“形状说明”。

它告诉 NumPy:

“我要创建一个 3 维数组,它的形状是 N x M x P。”

所以:

numpy.zeros((N, M, P))

真正的意思是:

“调用 zeros 函数,并把 (N, M, P) 这个形状作为一个整体传进去。”


为什么不能写成 numpy.zeros(N, M, P)

因为这样写时,Python 会把它理解成:

numpy.zeros(第1个参数, 第2个参数, 第3个参数)

也就是说,你传了 3 个独立参数。

numpy.zeros() 的第一个核心参数应该是:

shape

它希望拿到的是一个整体的形状,而不是 3 个散开的数字。

所以二维、三维这种情况,一般都要写成元组:

numpy.zeros((2, 3))
numpy.zeros((2, 3, 4))
numpy.ones((4, 5))

那为什么一维数组有时候不用双层括号

比如你会看到:

numpy.zeros(5)

这也能运行。

因为一维数组的 shape 可以直接写成一个整数 5,表示长度为 5。

也就是说:

numpy.zeros(5)

相当于创建:

[0. 0. 0. 0. 0.]

但如果是二维、三维,就必须把形状整体写出来:

numpy.zeros((2, 3))
numpy.zeros((2, 3, 4))

所以你可以这样记:

一维

shape 可以直接写一个数

numpy.zeros(5)

二维及以上

shape 通常写成元组

numpy.zeros((2, 3))
numpy.zeros((2, 3, 4))

你可以把它理解成“地址”或者“规格说明”

比如你去定做一个盒子:

  • 长 2
  • 宽 3
  • 高 4

这三个数字必须作为“一组规格”一起交给工厂。

不能今天给个 2,明天给个 3,后天给个 4。

NumPy 这里也是一样:

(2, 3, 4)

就是这一组规格。


dtype=int 到底是什么意思

dtype 是:

data type

也就是“数据类型”。

它是在告诉 NumPy:

这个数组里的元素,要用什么类型来保存。

例如:

numpy.zeros((2, 2), dtype=int)

意思是:

“创建一个 2×2 的全 0 数组,并且这些 0 要按整数类型存储。”


为什么不写 dtype=int 时会输出浮点数

因为 numpy.zeros()numpy.ones() 的默认类型通常是浮点数,也就是 float

例如:

import numpy as np

print(np.zeros((2, 2)))

输出一般会是:

[[0. 0.]
 [0. 0.]]

你会看到是 0.,不是 0

这个 0. 表示它是浮点数。

同理:

print(np.ones((2, 2)))

输出一般是:

[[1. 1.]
 [1. 1.]]

加上 dtype=int 后会发生什么

import numpy as np

print(np.zeros((2, 2), dtype=int))
print(np.ones((2, 2), dtype=int))

输出会变成:

[[0 0]
 [0 0]]
[[1 1]
 [1 1]]

这时候就不再显示小数点了,因为元素类型变成了整数。


dtype 常见可以改成哪些类型

下面是最常见的几种。

1. dtype=int

整数类型

import numpy as np

print(np.zeros((2, 3), dtype=int))
print(np.ones((2, 3), dtype=int))

输出:

[[0 0 0]
 [0 0 0]]
[[1 1 1]
 [1 1 1]]

2. dtype=float

浮点数类型

import numpy as np

print(np.zeros((2, 3), dtype=float))
print(np.ones((2, 3), dtype=float))

输出:

[[0. 0. 0.]
 [0. 0. 0.]]
[[1. 1. 1.]
 [1. 1. 1.]]

这其实就是默认情况。


3. dtype=bool

布尔类型

import numpy as np

print(np.zeros((2, 3), dtype=bool))
print(np.ones((2, 3), dtype=bool))

输出:

[[False False False]
 [False False False]]
[[ True  True  True]
 [ True  True  True]]

因为在布尔世界里:

  • 0 对应 False
  • 1 对应 True

4. dtype=complex

复数类型

import numpy as np

print(np.zeros((2, 2), dtype=complex))
print(np.ones((2, 2), dtype=complex))

输出通常类似:

[[0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j]]
[[1.+0.j 1.+0.j]
 [1.+0.j 1.+0.j]]

这个在初学阶段不常用,但你知道它存在就行。


5. 更精确的类型写法

你还会看到这些:

dtype=np.int32
dtype=np.int64
dtype=np.float32
dtype=np.float64

这表示更具体的类型。

比如:

import numpy as np

a = np.zeros((2, 2), dtype=np.int32)
b = np.ones((2, 2), dtype=np.float64)

它们和简单写 intfloat 的区别在于:

占用多少字节、精度多高,是更细的控制。

初学阶段先会用:

dtype=int
dtype=float
dtype=bool

就够了。


zerosones 这两个函数“还有哪些输出”

这里你要分清一件事:

zeros()ones() 决定的是“值”

  • zeros() 生成全 0
  • ones() 生成全 1

dtype 决定的是“这些值用什么类型显示和存储”

所以你看到的输出变化,其实主要来自 dtype

比如同样是“全 1”:

整数版

np.ones((2, 2), dtype=int)

输出:

[[1 1]
 [1 1]]

浮点版

np.ones((2, 2), dtype=float)

输出:

[[1. 1.]
 [1. 1.]]

布尔版

np.ones((2, 2), dtype=bool)

输出:

[[ True  True]
 [ True  True]]

也就是说,值本质上还是“1”,只是显示形式和存储方式不同。


这个函数还能怎么修改

你现在最需要掌握的修改点有两个:

第一,改形状 shape

比如:

np.zeros(5)
np.zeros((2, 3))
np.zeros((2, 3, 4))

这会生成不同维度、不同大小的数组。


第二,改数据类型 dtype

比如:

np.zeros((2, 2), dtype=int)
np.zeros((2, 2), dtype=float)
np.zeros((2, 2), dtype=bool)

这样可以改变输出样子和内部存储类型。


一个最清楚的对比示例

你可以直接看这一组:

import numpy as np

print(np.zeros((2, 3)))
print(np.zeros((2, 3), dtype=int))
print(np.zeros((2, 3), dtype=bool))

print(np.ones((2, 3)))
print(np.ones((2, 3), dtype=int))
print(np.ones((2, 3), dtype=bool))

你会发现:

  • 默认是浮点数
  • dtype=int 变整数
  • dtype=bool 变布尔值

初学者最容易混淆的点

第一种混淆:把双层括号看成“多余括号”

其实不是多余,而是:

  • 外层:函数调用
  • 内层:shape 元组

第二种混淆:以为 zeros 只能生成整数 0

不是。

zeros 生成的是“数值为 0 的数组”,但这个 0 可以是:

  • 整数 0
  • 浮点数 0.
  • 布尔值 False
  • 复数 0+0j

要看 dtype 怎么定。


第三种混淆:以为 dtype=int 是“把形状变成整数”

不是。

dtype=int 改的是数组里元素的类型,不是数组的大小,不是数组的维度。

比如:

np.zeros((2, 3), dtype=int)

这里:

  • (2, 3) 是形状
  • int 是元素类型

这两件事完全不同。


本节小结

你可以把这道题的核心记成三句话。

1. zeros()ones() 需要一个 shape

shape 表示数组的形状。

一维可以写:

np.zeros(5)

二维、三维通常写:

np.zeros((2, 3))
np.zeros((2, 3, 4))

2. 双层括号不是重复

np.zeros((N, M, P))
  • 外层括号:调用函数
  • 内层括号:写元组,表示形状

3. dtype 决定元素类型

dtype=int
dtype=float
dtype=bool

它决定你看到的是:

  • 0 / 1
  • 0. / 1.
  • False / True

一个小练习

你可以自己先试着判断下面每句代码会输出成什么类型:

import numpy as np

print(np.zeros((2, 2)))
print(np.zeros((2, 2), dtype=int))
print(np.ones((2, 2), dtype=bool))

提示你只判断“输出里会看到什么风格”:

  • 0. 还是 0
  • 1 还是 True

为什么 numpy.zeros(shape) 里的 shape 常写成元组,而不是普通整数

这一节可以专门作为你前面那道题的补充说明。很多初学者一开始都会把这里看得有点模糊:一会儿看到 numpy.zeros(3),一会儿又看到 numpy.zeros((3, 2)),再加上题目里还常写成 shape = tuple(map(int, input().split())),就很容易混在一起。

其实这里真正要弄明白的是:shape 不是某一个数字本身,而是“数组形状的描述”。


先说结论:shape 不一定非得是元组

这句话要先说清楚,不然容易记错。

numpy.zeros(shape) 里的 shape

  • 可以是一个普通整数
  • 也可以是一个元组

比如下面两种写法都合法:

import numpy as np

print(np.zeros(3))
print(np.zeros((3, 2)))

所以严格来说,不是“必须是元组”。

更准确的说法应该是:

当你要表示多维数组时,shape 通常要写成元组;当你只表示一维数组时,写普通整数也可以。


shape 到底是什么

shape 可以理解成:

数组每一维有多大。

比如:

(3,)

表示一维数组,有 3 个元素。

(3, 2)

表示二维数组,有 3 行 2 列。

(3, 3, 3)

表示三维数组,外层有 3 块,每块里有 3 行,每行有 3 个元素。

所以 shape 不是“某一个数字”,而是“这个数组长什么样”。


为什么普通整数只能自然表示一维

我们先看这个例子:

import numpy as np
print(np.zeros(3))

这里的 3 表示:

“请给我一个长度为 3 的一维数组。”

输出大致是:

[0. 0. 0.]

这很好理解,因为一维数组只需要一个数字就够了。

你可以把它想成:

  • 一维数组:只要说长度是多少
  • 二维数组:要说行和列分别是多少
  • 三维数组:要说每一层、每一行、每一列分别是多少

所以:

  • 一维时,一个整数就够
  • 多维时,一个整数不够,必须同时描述多个维度的大小

这就是为什么二维、三维、四维时,通常要写元组。


为什么多维要用元组来描述

看下面几个例子:

import numpy as np

print(np.zeros((3, 2)))
print(np.zeros((2, 2, 2)))

这里的 (3, 2)(2, 2, 2),本质上是在告诉 NumPy:

  • 第一维多大
  • 第二维多大
  • 第三维多大
  • ……

一个整数只能表示一个值,而元组可以一次装下多个值。

所以:

np.zeros(3)

只是在说:

“做一个长度为 3 的一维数组。”

而:

np.zeros((3, 2))

是在说:

“做一个 3 行 2 列的二维数组。”

而:

np.zeros((3, 2, 2, 2))

是在说:

“做一个四维数组,每一维大小分别是 3、2、2、2。”


为什么题目里更适合统一写成元组

像你做的这道题,输入可能是:

3 2

也可能是:

3 3 3

还可能是:

3 2 2 2

这就说明:

维度个数不固定。

既然维度个数不固定,那最合适的办法就不是写死成:

N, M, P = ...

而是把整行输入全部收起来,统一变成一个“形状描述”。

这时候元组就特别合适。

例如:

  • 输入 3 2,变成 (3, 2)
  • 输入 3 3 3,变成 (3, 3, 3)
  • 输入 3 2 2 2,变成 (3, 2, 2, 2)

然后统一交给:

np.zeros(shape)
np.ones(shape)

这样程序就不需要提前知道到底是二维、三维还是四维了。


一个很容易混淆的点:3(3,) 的关系

这个地方非常值得单独讲清楚。

在 NumPy 里:

np.zeros(3)

np.zeros((3,))

效果是一样的,都是创建长度为 3 的一维数组。

因为:

  • 3 表示一维长度为 3
  • (3,) 表示形状是一个只有 1 个维度的元组,这个维度大小是 3

也就是说,一维时,这两种写法都可以。

但是注意一个很关键的 Python 语法点:

(3)

这不是元组,这只是整数 3

真正的单元素元组要写成:

(3,)

后面的逗号不能少。

这是初学者非常容易踩的坑。

你可以记一句:

不是括号让它变成元组,而是逗号让它变成元组。


为什么这道题里不直接用整数,而要用 tuple(...)

因为这道题不是固定一维。

如果你只写:

shape = int(input())

那只能接收一个数字,比如 3

可题目给的是一整行空格分隔的数字:

3 2

或者:

3 3 3

这显然不是一个单独整数,而是一组维度信息。

所以必须把这一组数字收集起来。

而收集成元组,就是最自然、最规范的写法。


shape = tuple(map(int, input().split())) 这一整串到底在做什么

这句代码看起来长,但其实就是四步连起来写了。

shape = tuple(map(int, input().split()))

我们一点点拆开看。


第一步:input()

input()

作用是从键盘读入一整行内容。

假设用户输入的是:

3 2 2 2

那么 input() 读到的是一个字符串:

'3 2 2 2'

注意,它现在还是字符串,不是数字。


第二步:.split()

input().split()

作用是按空格切开。

于是:

'3 2 2 2'.split()

会变成:

['3', '2', '2', '2']

这里得到的是一个字符串列表。

也就是说,里面每一项还是字符串。

不是整数。


第三步:map(int, ...)

map(int, input().split())

这一部分的作用是:

把前面列表里的每个字符串,逐个转成整数。

也就是:

  • '3' 变成 3
  • '2' 变成 2
  • '2' 变成 2
  • '2' 变成 2

所以逻辑上就相当于得到了:

3, 2, 2, 2

这里你可以先把 map 理解成:

“让 int() 对每个元素都做一次转换。”


第四步:tuple(...)

tuple(map(int, input().split()))

最后这一步是把前面那些转换后的整数收集成一个元组。

于是就得到:

(3, 2, 2, 2)

这个元组就正好可以作为 shape 传给 NumPy。


把这句完整地翻译成人话

shape = tuple(map(int, input().split()))

可以翻译成一句非常直白的话:

把用户输入的一整行数字按空格拆开,把每一项从字符串变成整数,再整体收成一个元组,作为数组的形状。


用几个例子彻底看懂这句代码

例 1:输入是 3 2

执行过程是:

input()              -> '3 2'
split()              -> ['3', '2']
map(int, ...)        -> 3, 2
tuple(...)           -> (3, 2)

最终:

shape = (3, 2)

例 2:输入是 3 3 3

执行过程是:

input()              -> '3 3 3'
split()              -> ['3', '3', '3']
map(int, ...)        -> 3, 3, 3
tuple(...)           -> (3, 3, 3)

最终:

shape = (3, 3, 3)

例 3:输入是 3 2 2 2

执行过程是:

input()              -> '3 2 2 2'
split()              -> ['3', '2', '2', '2']
map(int, ...)        -> 3, 2, 2, 2
tuple(...)           -> (3, 2, 2, 2)

最终:

shape = (3, 2, 2, 2)

为什么不用列表,而常用元组

这个地方也可以顺手补充一下。

其实 NumPy 在很多情况下也能接受列表,比如:

np.zeros([3, 2])

很多时候也能运行。

但在“表示 shape”这件事上,元组更常见,原因主要有两个。

第一,元组更像“固定的结构说明”。
shape 一般只是拿来描述数组形状,不是后面要频繁修改的数据,所以元组很合适。

第二,教材、官方示例、题目答案里,几乎都习惯用元组。
所以你跟着这个习惯写,最稳。

对于初学阶段,你可以先记成:

shape 的标准写法优先用元组。


这道题的最终标准写法

所以像这道题,最推荐写成:

import numpy as np

shape = tuple(map(int, input().split()))
print(np.zeros(shape, dtype=int))
print(np.ones(shape, dtype=int))

这里的思路非常统一:

先把输入处理成一个形状元组,再把这个形状元组交给 zerosones


你以后怎么判断该用整数还是元组

你可以用一个很简单的判断办法。

如果你想创建的是一维数组,只需要一个长度,那么整数就够了:

np.zeros(5)

如果你想创建的是二维及以上数组,或者题目输入的维度个数不固定,就应该用元组:

np.zeros((3, 2))
np.zeros((3, 3, 3))
np.zeros((3, 2, 2, 2))

尤其是像题目这种“输入一整行维度”的情况,几乎就是在提示你应该写:

shape = tuple(map(int, input().split()))

本节小结

这一节最重要的有四句话。

第一,shape 不一定非得是元组。
一维数组时,普通整数也可以。

第二,多维数组通常要用元组。
因为一个整数只能表示一个维度,而元组可以同时表示多个维度。

第三,np.zeros(3)np.zeros((3,)) 都表示一维长度为 3。
(3) 不是元组,(3,) 才是单元素元组。

第四,题目里写:

shape = tuple(map(int, input().split()))

本质上就是:
把整行输入的所有数字读进来,转成整数,再收成一个形状元组。


小练习

你可以先自己判断下面三句代码里,shape 最后分别是什么。

题目

shape = tuple(map(int, "4".split()))
shape = tuple(map(int, "2 3".split()))
shape = tuple(map(int, "2 1 3".split()))

提示

你可以按这个顺序去想:

先看 split() 后变成什么。
再看 map(int, ...) 后每个元素变成什么。
最后看 tuple(...) 收成什么。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇