深度学习预备知识储备(python numpy)
目录
python
变量的使用
运算符使用
字典与集合
字典
集合
字符串操作
格式化输出与数据类型转换
格式化输出
简单数据类型转换
循环
for循环语法
while循环语法
if分支语句
1.if…else…语句
2.if…elif…else语句
3.if嵌套
4.if语句
5.三目运算符
函数
定义函数
函数的参数
函数的返回值
列表与元组
列表的应用场景
列表的创建
列表的常见操作
元组的创建
元组的常见操作
高阶函数
函数的作用域
函数的嵌套调用
高阶函数示例
查阅文档
查找模块中的所有函数和类
查找特定函数和类的用法
查阅官方文档
numpy
创建数组
创造一维数组
创造二维数组
创造全0数组
创建全1数组
创建全空数组
创建有连续序列的数组
创建有连续间隔的数组
创建随机数组
改变数组形状
数组运算
数组与标量之间的运算
数组与数组之间的运算
广播机制
常用的数学函数
索引和切片
索引
切片
数组的堆叠
垂直堆叠
水平堆叠
深度堆叠
沿新轴堆叠
连接
保存与加载数组
保存和加载单个数组
保存和加载多个数组
保存和加载数组到文本文件
python
变量的使用
什么是变量,存储数据的容器,使用变量有没有什么讲究:
1、严格区分大小写
2、见名知意
3、不能使用关键字和内置函数
import keyword
print(keyword.kwlist)
import builtins
print(dir(builtins))
4、不能以数字开头
5、不能使用特殊字符 包含空格
6、只能用字母数字下划线组成
运算符使用
这里简单介绍一下概念,就不举具体的例子了。
运算符类型
1、算术运算符
+(加)
-(减)
*(乘)
/(除)
//(整除)
%(取模)
**(幂)
2、比较运算符
==(等于)
!=(不等于)
>(大于)
<(小于)
>=(大于等于)
<=(小于等于)
3、赋值运算符
=(赋值)
+=(加后赋值)
-=(减后赋值)
*=(乘后赋值)
/=(除后赋值)
//=(整除后赋值)
%=(取模后赋值)
**=(幂后赋值)
4、逻辑运算符
and(逻辑与)
or(逻辑或)
not(逻辑非)
5、成员运算符
in(在序列中)
not in(不在序列中)
6、身份运算符
is(是同一个对象)
is not(不是同一个对象)
运算符的应用场景
算术运算符:用于执行基本的数学运算,如加法、减法、乘法和除法。在处理数值数据、进行计算和算法实现时必不可少。
比较运算符:用于比较两个值,判断它们是否相等、不等、大于、小于等。在条件判断、排序、搜索等操作中经常使用。
赋值运算符:用于将值赋给变量,是变量初始化和值更新的基本工具。复合赋值运算符(如 +=、-=)可以简化代码,使表达式更加简洁。
逻辑运算符:用于组合多个条件,进行逻辑与(and)、逻辑或(or)和非(not)运算。在编写复杂的条件语句和循环时非常有用。
成员运算符:用于检查对象是否存在于序列(如字符串、列表、元组)中。在数据处理和集合操作中经常使用。
身份运算符:用于比较两个对象的内存地址,即它们是否是同一个对象。在处理可变数据类型和不可变数据类型时,以及在进行对象比较时非常有用。
字典与集合
在 Python 中,字典(dict
)和集合(set
)是两种常用的数据结构,它们都基于哈希表实现,能够高效地进行元素的查找、插入和删除操作。
字典
字典是一种由键值对(key-value
)组成的集合,其中每个键(key
)是唯一的,不可变类型(如字符串、数字、元组等),而值(value
)可以是任意类型。字典使用大括号 {}
表示,键和值之间用冒号 :
分隔,键值对之间用逗号 ,
分隔。
创建字典的方式:
# 直接创建
d1 = {'name': 'Alice', 'age': 30, 'gender': 'female'}
# 使用 dict() 函数
d2 = dict(name='Alice', age=30, gender='female')
# 使用可迭代对象
d3 = dict([('name', 'Alice'), ('age', 30), ('gender', 'female')])
常规操作:
访问元素: 使用键访问对应的值。
print(d1['name']) # 输出:Alice
添加或修改元素: 直接通过键进行赋值。
d1['email'] = 'alice@example.com' # 添加新键值对
d1['age'] = 31 # 修改已有键的值
删除元素: 使用 del
关键字或 pop()
方法。
del d1['gender'] # 删除键为 'gender' 的键值对
age = d1.pop('age') # 删除并返回键为 'age' 的值
遍历字典: 可以遍历键、值或键值对。
for key in d1:
print(key, d1[key]) # 输出键和值
for key, value in d1.items():
print(key, value) # 输出键和值
集合
集合是一个无序且不重复的元素集合,主要用于成员测试和消除重复元素。集合使用大括号 {}
表示,元素之间用逗号 ,
分隔。
# 直接创建
s1 = {1, 2, 3, 4}
# 使用 set() 函数
s2 = set([1, 2, 3, 4])
注意: 创建空集合时,必须使用 set()
,因为 {}
会被认为是空字典。
常用操作:
添加元素: 使用 add()
方法。
s1.add(5) # s1 变为 {1, 2, 3, 4, 5}
删除元素: 使用 remove()
或 discard()
方法。
s1.remove(2) # s1 变为 {1, 3, 4, 5}
s1.discard(10) # 不会报错,即使元素不存在
集合运算: 支持并集、交集、差集等操作。
s2 = {3, 4, 5, 6}
union_set = s1.union(s2) # 并集:{1, 3, 4, 5, 6}
intersection_set = s1.intersection(s2) # 交集:{3, 4, 5}
difference_set = s1.difference(s2) # 差集:{1}
字符串操作
字符串的定义是什么
字符串是编程语言中最常用的数据类型,它用于表示文本数据。
在Python中,字符串是用单引号或双引号括起来的文本。
访问字符串中的值—–>索引
什么叫做索引(下标)
索引是用来访问字符串中的值的一种方式。
索引指的是通过指定字符串中的某个位置来访问该位置上的值。
怎么去理解索引
就像你在家里的书架上找书,你可能会根据书的顺序来快速找到你想看的那本书,
而不会一本一本地翻找。索引就是帮助我们在数据结构中快速找到元素的一种方式。
索引从0开始
索引最大范围是字符串长度减1
索引语法: str[index]
字符串中的切片
切片语法:
str[起始索引:结束索引:步长]
字符串常用操作方法
1、spilt()
可以指定一个字符串作为参数,将字符串按照指定的参数进行切片,并返回一个列表
"""split方法的使用"""
numbers = input('请输入两个数字并以,分割然后计算出两数的和:')
#使用 split() 方法将输入的字符串按逗号分割,返回一个列表
numberlist = numbers.split(',')
print(numberlist)
#初始化 sum_ 变量,用于存储数字之和
sum_ = 0
#遍历分割后的列表,将每个元素转换为整数并累加到 sum_ 中
for i in numberlist:
sum_+= int(i)
print(sum_)
如果用户输入的字符串中包含非数字字符,或者输入的格式不符合要求(例如缺少逗号或输入了多个逗号),在执行 int(i)
时会引发 ValueError
异常。
2、replace()
可以指定两个参数,第一个参数为要替换的字符串,第二个参数为替换为的字符串
"""replace方法的使用"""
demostr = 'my name is cat. I am not only handsome but also talented'
'''需求:将demostr中的a字母全部转成大写 并形成一个新的字符串'''
newdemostr = demostr.replace('a','A')
print(newdemostr)
3、strip()
可以指定一个字符串作为参数,表示去除字符串两端的指定字符串
'''strip方法的使用'''
var = " hello and python and hello world "
var2 = "@hello and python@ and@ hello world@"
print(var)
print(var.strip()) # 删除两侧空格
print(var2.strip('@')) # 删除两侧@符号
print(var2.strip('@').replace('@',''))
"""
var2.strip('@').replace('@',''):该表达式首先使用 strip('@') 移除 var2 两端的 @ 符号,得到 'hello and python@ and@ hello world'。然后,replace('@', '') 方法将字符串中所有的 @ 符号替换为空字符串,即删除所有的 @ 符号,最终结果为 'hello and python and hello world'。
"""
print(var2.replace('@',''))
"""
var2.replace('@',''):replace('@', '') 方法直接将 var2 中的所有 @ 符号替换为空字符串,即删除所有的 @ 符号,结果为 'hello and python and hello world'
"""
4、join()
可以指定一个字符串作为参数,将字符串中的每个元素使用指定的字符串进行连接
'''join方法的使用'''
字符或⼦串.join(多字符串组成的序列)
list1 = ["hello", "python", "i", "love", "you"]
t1 = ("hello", "python", "i", "love", "you")
set1 = {"hello", "python", "i", "love", "you"}
list1 = ['1', '2', '3', '4', '5']
list2 = [1, 2, 3, 4, 5] # str()<==>int() age = '18' int(age) str(i)
print("__".join(list1)) # 将列表转化为字符串,并且使用指定符号隔开
print("__".join(list2)) # 将列表转化为字符串,并且使用指定符号隔开
print(",".join(t1)) # 将元组转化为字符串,并且使用指定符号隔开
print("|".join(set1)) # 将集合转化为字符串,并且使用指定符号隔开
其中的一个输出位
'1__2__3__4__5'
格式化输出与数据类型转换
格式化输出
格式化输出的意义:格式化输出可以让我们的代码更加易读,更加直观,同时也能简化代码编写和维护工作。
格式化输出函数的使用:format()函数的使用,f表达式的使用。
name = "小明"
age = 18 # ------'18'
hobby = "打游戏"
"""常规拼接使用"""
print("大家好,我是" + name + ",今年" + str(age) + "岁,喜欢" + hobby)
"""format的使用"""
# 1、不带编号
print("大家好,我是{},今年{}岁,喜欢{}".format(name,age,hobby))
# 2、带数字编号
print("大家好,我是{2},今年{0}岁,喜欢{1}".format(age,hobby,name))
# 3、附带关键字
print("大家好,我是{name},今年{age}岁,喜欢{hobby}".format(age=age,name=name,hobby=hobby))
"""f表达式的使用"""
print(f"大家好,我是{name},今年{age}岁,喜欢{hobby}")
print(f"大家好,我是{name},今年{age}岁,喜欢{hobby}")
简单数据类型转换
1、首先需要对两种数据类型有认知:
整数类型: int
实例: a = 1
表示:它代表一个数学上的自然数。
用途:可以用于数学运算,如加法、减法、乘法、除法等。
字符串类型:str
实例: a = '1'
表示:它是由一个或多个字符组成的序列,在这里是字符'1'。
用途:通常用于表示文本信息,如名字、地址、消息等。字符串不能直接用于数学运算。
……
2、数据类型的转换:
int()
str()
int()<====>str()
……
3、如何检测变量的数据类型
type()
"""
需求:
要求用户从控制台输入两个数字,
并对这两个数字进行求和运算,
最后将结果在控制台输出
"""
number1 = input('请输入第一个数字:')
print(number1,type(number1))
number2 = input('请输入第二个数字:')
print(number2,type(number2))
result = int(number1) + int(number2)
print('两个数字的和为:',result)
print(type(result))
循环
for循环语法
就用几个实例来理解
for i in 'Python':
print(i)
输出0~9
for i in range(10):
print(i)
输出1~100
for i in range(1, 101):
print(i)
输出1~100,每次跳过一个数字
for i in range(1, 101, 2):
print(i)
"""计算1到100的偶数和"""
sum_even = 0
for i in range(1, 101):
if i % 2 == 0:
sum_even += i
print(sum_even)
for i in range(0, 101, 2):
# print(i)
sum_even += i
print(sum_even)
"""九九乘法表"""
for i in range(1, 10): # 123456789
for j in range(1, i+1,1): # (1,1)---(1,2)
print(f"{j}x{i}={i*j}", end='\t')
print()
while循环语法
也用几个实例来理解
"""
计算1-100的和
"""
num = 1
result = 0
while num <= 100:
result += num
num += 1 # 改变你的循环条件
print(result)
"""计算1-100偶数和"""
num = 1
result = 0
while num <= 100:
# 判断num是否能整除2,如果可以,则和result相加
if num % 2 == 0:
result += num
num += 1
print(result)
"""break的使用"""
i = 1
while i <= 10:
print(f'子弹打了{i}发')
if i == 5:
print('枪坏了 打不出来了 强制停止射击')
break
i += 1
"""continue的使用"""
i = 1
while i <= 10:
print(f'子弹打了{i}发')
if i == 5:
print(f'第{i}发子弹是哑弹')
i += 1
continue
i += 1
time.sleep(1)
print(1)
print()
print(2)
"""九九乘法口诀表"""
j = 1
# 外循环
while j <= 9:
i = 1
# 内循环
while i<=j:
print(f'{i}*{j}={i*j}',end='\t')
i += 1
print() # 换行
j += 1
if分支语句
1.if…else…语句
"""
使用if-else结构检查一个数字是奇数还是偶数
"""
x = 7
if x % 2 == 0:
print("x 是一个偶数")
else:
print("x 是一个奇数")
2.if…elif…else语句
print()
"""
使用 if-elif-else 结构根据分数评定等级
"""
score = 85
if score >= 90:
print("等级是 A")
elif score >= 80:
print("等级是 B")
elif score >= 70:
print("等级是 C")
else:
print("等级是 D")
3.if嵌套
age = 25
citizenship = "CHINA"
# 外层的 if 语句
if age >= 18:
print("您已经成年。")
# 嵌套的 if 语句
if citizenship == "CHINA":
print("您是中国公民,有投票权。")
else:
print("您不是中国公民,没有投票权。")
else:
print("您还未成年。")
4.if语句
print()
"""
检查一个数字是否为正数
"""
x = -10
if x > 0:
print("x 是一个正数")
5.三目运算符
print()
"""
三目运算符,也称为条件表达式,是一种在单个表达式中简化 if-else 逻辑的方法。
语法:
value_if_true if condition else value_if_false
condition 是判断条件,这里是 x > y
value_if_true 是当条件为真时返回的值,这里是 x
value_if_false 是当条件为假时返回的值,这里是 y
因此,如果 x 大于 y,max_value 将被赋值为 x 的值;否则,max_value 被赋值为 y 的值
"""
x = 10
y = 5
max_value = x if x > y else y
print(max_value) # 输出:10
函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。我们已经知道Python提供了许多内建函数,比如print() input()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义函数
def 函数名():
"""
函数文档字符串
"""
代码1
代码2
......
函数如何去进行调用:定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。函数必须调用才会进行执行
调用方式: 函数名()
函数的参数
在 Python 中,函数参数 是指在定义和调用函数时,用于传递数据的变量。根据使用场景,函数参数分为两种:形式参数 和 实际参数。
1. 形式参数(形参)
形式参数是在定义函数时,在函数名后面的括号中指定的参数。它们相当于占位符,用于指示函数在调用时需要哪些输入。例如:
def func(a, b):
# 函数体
pass
在上述函数定义中,a
和 b
就是形式参数。它们在函数定义阶段并没有具体的值,只有在函数被调用时才会被赋予实际的值。
这里再举一个例子
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 输出:8
在上述代码中:add
函数定义了两个形式参数 a
和 b,
调用 add(3, 5)
时,实际参数 3
和 5
分别传递给了形式参数 a
和 b,
函数内部使用 a
和 b
进行计算,并返回结果。
2.实际参数(实参)
实际参数是在调用函数时,传递给函数的具体值。这些值对应于函数定义中的形式参数。例如:
func(10, 20)
在这个调用中,10
和 20
就是实际参数。它们被传递给函数 func
,分别赋值给形式参数 a
和 b
。
需要注意的是,形参和实参的绑定关系仅在函数调用时生效,函数执行完毕后,这种绑定关系就会解除。
3.参数的传递方式
在 Python 中,参数的传递方式取决于实际参数的类型:
不可变类型(如整数、字符串、元组):采用值传递,即传递的是值的副本。在函数内部修改形参的值,不会影响到实参。
def modify(x): #定义函数 modify
x = x + 1 #在函数内部,执行 x = x + 1,即将 x 的值增加 1
print("Inside function:", x)#然后,打印函数内部的 x 值
a = 10
modify(a) #调用函数 modify(a),将变量 a 的值(即 10)作为参数传递给函数 modify
print("Outside function:", a)
输出
Inside function: 11
Outside function: 10
在这个例子中,a
的值在函数调用前后没有变化。
可变类型(如列表、字典):采用引用传递,即传递的是对象的引用。在函数内部修改形参,会影响到实参。
def modify(lst):#定义函数 modify(lst),该函数接受一个列表参数 lst
lst.append(4)#在函数内部,调用 lst.append(4),将数字 4 添加到列表 lst 的末尾
print("Inside function:", lst)#打印函数内部的列表内容
my_list = [1, 2, 3]#在函数外部,创建一个列表 my_list,包含元素 [1, 2, 3]
modify(my_list)#调用函数 modify(my_list),将 my_list 作为参数传递给函数
print("Outside function:", my_list)#函数执行后,打印函数外部的列表 my_list 的内容。
输出
Inside function: [1, 2, 3, 4]
Outside function: [1, 2, 3, 4]
当 my_list
被传递给函数 modify
时,lst
和 my_list
都引用同一个列表对象。因此,在函数内部对 lst
的修改(如使用 append
方法添加元素)会直接影响到 my_list
。这就是为什么在函数内部和外部打印的列表内容都是 [1, 2, 3, 4]
。
函数的返回值
return:我们创建函数都只是为我们做一些事,做完了就结束。但实际上,有时还需要对事情的结果进行获取。
这里举一个例子:现在有一个列表 li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 要求取这个列表中所有数的平均值然后与5进行比较 如果平均值大于5 返回True 否则返回False
def compare_average(numbers):
"""
计算列表中所有数的平均值,并与5进行比较。
如果平均值大于5,返回True;否则返回False。
"""
if not numbers:
raise ValueError("列表不能为空")
average = sum(numbers) / len(numbers)
return average > 5
# 示例列表
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 调用函数并打印结果
result = compare_average(li)
print(result) # 输出:True
"""
numbers 是函数 compare_average 的参数名称。当您调用 compare_average(li) 时,
列表 li 被传递给函数,numbers 就引用了 li。在函数内部,numbers 被用于计算平均
值并与 5 进行比较
"""
compare_average
函数首先检查传入的列表是否为空,如果为空,抛出 ValueError
异常,提示列表不能为空。如果列表不为空,计算列表元素的平均值,并将其与 5 进行比较,返回比较结果。在示例列表 li
中,元素的平均值为 5.5,大于 5,因此函数返回 True
。
列表与元组
列表的应用场景
思考:如果⼀个班级100位学⽣,每个⼈的姓名都要存储,应该如何书写程序?声明100个变量吗?
答:列表即可, 列表⼀次性可以存储多个数据。
student1 = 'xxx'
student2 = 'xxx'
student3 = 'xxx'
.....
student99 = 'xxx'
student100 = 'xxx'
students = [student1, student2, student3, ..., student100]
列表的创建
列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。
列表的数据项不需要具有相同的类型创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。实例:
list1 = ['Google', 'Runoob', 1997]
list2 = [1, 2, 3, 4, 5 ]
list3 = ["a", "b", "c", "d"]
list4 = ["a", 1, "b", 2, "c", 3]
列表的常见操作
"""定义列表"""
fruits = ['banana', 'apple', 'watermelon', 'jackfruit']
print(fruits)
li_test = list(range(0,5))
print(li_test)
"""列表常见操作"""
print(fruits[0])
#这行代码输出列表 fruits 的第一个元素,即 'banana'。在 Python 中,列表的索引从 0 开始。
print(fruits[0:3])
#这行代码使用切片操作,输出列表中从索引 0 到 2 的元素(不包括索引 3)
fruits.append('cherry')
#append() 方法在列表的末尾添加一个元素 'cherry'
print(fruits)
#remove() 方法删除列表中第一个匹配的元素 'banana'
fruits.remove('banana')
#这行代码将列表中第一个元素(索引 0)的值由 'apple' 修改为 'pear'
print(fruits)
fruits[0] = 'pear'
print(fruits)
li = [1,1,1,1,2,3,5,6,6,7,7,7,8]
print(li.count('1'))
"""
count() 方法统计列表中指定元素出现的次数,注意列表的元素是整数,而'1' 是字符串, 因此li.count('1') 的结果为 0,如果需要统计整数 1 的出现次数,应使用 li.count(1),结果为 4
"""
for i in li:
print(i)
li2 = [1,1,1,1,1,[1,1,1,2],3,5,6,7,8]
print(li2.count(1),'count')
"""
在这个列表 li2 中,count() 方法统计元素 1 在顶层列表中出现的次数。虽然嵌套列表 [1, 1, 1, 2] 中也包含 1,但 count() 方法不会递归统计嵌套列表中的元素。因此,li2.count(1) 的结果为 5,表示元素 1 在顶层列表中出现了 5 次。输出结果为:5 count
"""
元组的创建
元组与列表类似,不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开。
实例:
tup1 = ( 'Google', 'Runoob', 1997, 'Python' )
tup2 = (1, 2, 3, 4, 5, 6, 7 )
tup3 = ( "a", "b", "c", "d" )
tuple()
元组的常见操作
'''定义元组'''
tup = (1,2,3,4,5)
print(tup)
tup2 = tuple(range(0,5))
print(tup2)
"""元祖的常用操作"""
print(tup[0])
new_tup= tup[0:3]
print(new_tup)
tup3 = tup+tup2
print(tup3)
del tup
print(tup,'111')
和列表的操作都差不多,所有就不详细介绍了。
列表与元组的区别
列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。
元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。
高阶函数
函数的作用域
所谓作用域是指函数内部变量可以访问和使用的代码区域。
在一个程序中并不是所有的变量在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
1、Local(局部作用域):这是函数内部的作用域。在函数内部定义的变量只在函数内部可见和使用。
当函数调用结束时,局部变量会被销毁。
2、Enclosing(嵌套作用域):如果一个函数是在另一个函数内部定义的,
那么这个内部函数可以访问外部函数的变量。
这个外部函数的作用域对于内部函数来说就是嵌套作用域。
3、Global(全局作用域):这是包含所有代码的最外层作用域。
在全局作用域中定义的变量可以在程序的任何地方访问,除非在局部作用域中有同名的变量。
4、Built-in(内置作用域):这是Python内置的函数和变量,例如print()、len()等。
它们在任何地方都可用,除非被其他作用域中的同名变量覆盖。
通俗一点的去理解作用域
1、局部作用域:
就像是你的卧室,你可以在你的卧室里放你的衣服、玩具等个人物品。
这些物品只能在你卧室里用,别人不能随便拿。
同样,局部作用域里的变量只能在对应的函数内部使用和修改。
2、全局作用域:
就像是家里的客厅,大家都可以在这里放东西,也可以在这里找到别人放的东西。
客厅里的东西家里的每个人都能用。
全局作用域里的变量在整个程序中都能访问和修改。
3、嵌套作用域:
想象一下,如果你的卧室里有个小书桌,书桌上放了一些文具。
这些文具只能在书桌上用,但是因为书桌在卧室里,卧室里的东西也能用到。
嵌套作用域就是指一个作用域里嵌套了另一个作用域,里面的作用域可以访问外面作用域的变量。
4、内置作用域:
这就像是家里的工具箱,里面有很多工具,比如锤子、螺丝刀等。
这些工具是买房子时自带的,你可以在家里的任何地方使用这些工具。
内置作用域里的变量(比如Python的内建函数)在任何作用域里都能直接使用。
作用域的优先级
在函数内部查找变量时,会按照 Local、
Enclosing、
Global
Built-in
的顺序依次查找。如果找不到变量,就会报错。
"""函数的作用域"""
y = 10 # 定义全局变量 y
def func():
global y # 声明在函数内部使用全局变量 y
y = 5 # 修改全局变量 y 的值
print('y1 =', y)
func()
print('y2 =', y) # 输出函数外部的 y 值
global
关键字用于在函数内部声明对全局变量的引用,使得在函数内对该变量的修改会影响全局作用域中的变量值。在上述代码中,函数 func()
内部通过 global y
声明 y
为全局变量,并将其值修改为 5,导致全局变量 y
的值也被修改。输出都为5.
b = 5
def mytest1():
b = 6
def mytest2():
nonlocal b # nonlocal 关键字用于在嵌套函数内部使用变量
b = 7
print(b, id(b))
mytest2()
b = 7
print(b, id(b))
mytest1()
这段代码展示了 nonlocal
的用法,主要用于在嵌套函数中修改外层函数的局部变量。全局变量 b
值为 5,mytest1
中定义了自己的局部变量 b
为 6。mytest2
使用 nonlocal
将 mytest1
的局部变量 b
修改为 7,但全局变量 b
不受影响。因此,最终打印结果中,全局变量 b
输出为 5,而嵌套函数修改后的局部变量 b
输出为 7。
函数的嵌套调用
函数的嵌套调用指的是在一个函数的内部调用另一个函数。
"""函数的嵌套调用"""
def fun1():
print("我是函数1")
def fun2():
print("我是函数2")
fun1() # 在fun2中调用fun1
print("我继续执行函数2")
fun2()
输出结果
我是函数2
我是函数1
我继续执行函数2
运行流程是:首先调用 fun2
,输出“我是函数2”;接着在 fun2
中调用了 fun1
,fun1
执行时输出“我是函数1”;fun1
执行完毕后,返回到 fun2
,继续执行剩余的代码,最后输出“我继续执行函数2”。整个流程是从外层函数到内层函数,再返回到外层函数的执行顺序。
高阶函数示例
一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数满足其一则为高阶函数。
"""高阶函数"""
def func():
print("定义一个普通函数")
def high_level(func):
print("定义一个高阶函数")
# 在函数内部,通过传入的函数参数调用
func()
high_level(func)
定义一个高阶函数
定义一个普通函数
运行时,首先调用高阶函数 high_level
,它先打印“定义一个高阶函数”;接着在 high_level
内部调用了传入的函数 func
,func
执行后打印“定义一个普通函数”。整个流程展示了高阶函数可以接收另一个函数作为参数并在内部调用它的特性。最终输出两句话,依次是高阶函数和普通函数的内容。
def func():
print("定义一个普通函数")
def high_level(func):
print("定义一个高阶函数")
return func
#return func() 这个是直接返回函数调用,递归函数就是如此
high_level(func)()
高阶函数返回函数之后在调用func函数
这段代码的目的是展示高阶函数的 返回值为一个函数 的用法,并且动态调用返回的函数。
运行时,首先调用高阶函数 high_level(func)
,打印“定义一个高阶函数”。然后,high_level
返回了传入的函数 func
,接着立即调用返回的 func()
,执行 func
中的代码,打印“定义一个普通函数”。整个过程展示了高阶函数返回一个函数并调用该函数的流程。
high_level(func)
:
执行 high_level
,打印 "定义一个高阶函数"。
返回值是传入的函数 func
(函数本身,而不是执行结果)
high_level(func)()
:
输出 "定义一个普通函数"。
返回的 func
被立即调用,相当于执行 func()
。
输出结果:
定义一个高阶函数
定义一个普通函数
查阅文档
查找模块中的所有函数和类
import module_name
print(dir(module_name))
可以使用 Python 内置的 dir()
函数来列出模块的所有属性,包括函数、类和变量。
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_mx_nd_np', 'beta', 'chisquare', 'choice', 'exponential', 'gamma', 'gumbel', 'logistic', 'lognormal', 'multinomial', 'multivariate_normal', 'normal', 'pareto', 'power', 'rand', 'randint', 'randn', 'rayleigh', 'shuffle', 'uniform', 'weibull']
通常我们会忽略以双下划线(__
)开始和结束的函数,因为它们是 Python 中的特殊对象和方法(例如 __init__
、__str__
等),用于 Python 的内部机制和类操作。这些方法一般不需要直接调用或操作。
此外,以单下划线(_
)开始的函数通常是模块的内部函数或属性,通常不希望被外部代码直接调用或访问。因此,在大多数情况下,我们也可以忽略这些函数。
剩余的函数名或属性名,则可能代表该模块的主要功能。例如,如果模块名为 random
,且其中有一些函数名不以 __
或 _
开头,可以推测这些函数可能与生成随机数有关。通过这些函数名,可以推测模块提供了多种生成随机数的方法,并且这些方法可以从不同的统计分布中进行采样。这是通过函数名的直观提示来推测模块功能的常见做法。
查找特定函数和类的用法
help()
是一个内置函数,可以帮助你查找特定函数或类的文档说明,提供其用法、参数、返回值等信息。
import module_name
help(module_name.function_name) # 查看函数的用法
help(module_name.ClassName) # 查看类的用法
查阅官方文档
Python 和第三方库通常都有在线的官方文档,可以查阅文档来了解特定函数或类的详细用法。比如:3.13.1 Documentation
numpy
创建数组
创造一维数组
import numpy as np
data=np.array([1,2,3])
print(data)
创造二维数组
import numpy as np
data=np.array([1,2,3],[4,5,6])
print(data)
创造全0数组
shape属性代表形状 shape(2,5) 就代表创建2行5列的全零数组。
全零数组可以用作初始值或占位符,假设我们要读取一个尺寸为(255,255,255)的图片,我们可以创建一个相同维度的全零数组,然后将图片读入该数组进行填充。这样做的好处是,我们可以直接将原始图像数据存储在全零数组中,而无需担心数据溢出或其他问题。
import numpy as np
data=np.zeros(shape=(3,4))
#创建3行4列的二维数组
print(data)
创建全1数组
创建全1数组的用途是初始化一个具有特定形状和大小的数组,其中所有元素都设置为1。在处理一些数学问题或算法时,全1数组可以用作初始值或占位符。
例如,假设我们要计算一个矩阵与自身的转置相乘的结果,我们可以创建一个与输入矩阵相同维度的全1数组,然后将输入矩阵读入该数组进行填充。这样做的好处是,我们可以直接将原始矩阵数据存储在全1数组中,而无需担心数据溢出或其他问题。
import numpy as np
data=np.ones(shape=(3,4))
#shape代表形状,比如我这里创建的就是3行4列的2维数组
print(data)
创建全空数组
import numpy as np
data=np.empty(shape=(3,4))
#shape代表维度,比如我这里创建的就是3行4列的2维数组
print(data)
创建有连续序列的数组
import numpy as np
data=np.arange(10,18.2)
#10到18的数据,步长为2
print(data)
数组从10开始步长为2,所以创建出来数组元素就是10,12,14,16
创建有连续间隔的数组
也可以称为线性等分向量(linear space),在一个指定区间内按照指定的步长,将区间均等分,生成的是一个线段类型的数组。生成的线性间隔数据中,是有把区间的两端加进去的。
import numpy as np
#创建线段型数据
data=np.linspace(1,10,20)#开始端为1,结束端为10,且分成20个数据,生成线段
print(data)
创建随机数组
创建随机数组的用途是初始化一个具有特定形状和大小的数组,其中所有元素都是随机生成的。在处理一些需要模拟随机数据的情况时,随机数组可以用作占位符或测试数据。
import numpy as np
data=np.random.rand(3,4)
#np.random.rand 函数生成的随机数是服从 [0, 1) 区间内均匀分布的
print(data)
NumPy 的 np.random
模块还提供了许多其他随机数生成函数,如 np.random.randn()
(生成标准正态分布的随机数)、np.random.randint()
(生成指定范围内的随机整数)等。这些函数丰富了我们在模拟、数据分析和科学计算中的随机数需求。
import numpy as np
data=np.random.randint(2,5,size=(4,5))
print(data)
#这段代码使用NumPy库创建了一个4行5列的随机整数数组,其中每个元素的值在2到5之间
改变数组形状
1.reshape
方法:该方法返回一个改变形状后的新数组,但不改变原数组的数据。需要注意的是,新的形状必须与原数组的元素总数一致。
import numpy as np
arr = np.arange(6) # 创建包含0到5的数组
reshaped_arr = arr.reshape((2, 3)) # 将数组重塑为2行3列
print(reshaped_arr)
[[0 1 2]
[3 4 5]]
2.resize
方法:与 reshape
类似,但 resize
会直接修改原数组的形状。如果新形状的元素数量大于原数组,resize
会重复填充原数组的数据以适应新大小。
import numpy as np
arr = np.array([1, 2, 3, 4])
arr.resize((2, 3)) # 将数组调整为2行3列
print(arr)
[[1 2 3]
[4 1 2]]
在此示例中,resize
方法将原数组扩展为新的形状,并重复填充原数据。
3.flatten
方法:该方法返回一个一维数组,包含原数组中的所有元素。返回的是原数组的副本,修改该副本不会影响原数组。
import numpy as np
arr = np.array([[1, 2], [3, 4]])
flat_arr = arr.flatten()
print(flat_arr)
[1 2 3 4]
在此示例中,flatten
方法将二维数组展平为一维数组。
4.transpose
方法:用于交换数组的维度,返回一个新的视图。对于二维数组,transpose
等效于矩阵的转置操作。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
transposed_arr = arr.transpose()
print(transposed_arr)
[[1 4]
[2 5]
[3 6]]
在此示例中,transpose
方法将原数组的行和列进行了互换。
数组运算
数组与标量之间的运算
NumPy 允许对数组中的每个元素与一个标量进行加、减、乘、除等操作。例如:
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr + 2) # 输出: [3 4 5 6]
print(arr * 3) # 输出: [3 6 9 12]
数组与数组之间的运算
当两个数组形状相同时,可以进行逐元素的加、减、乘、除等操作。例如:
import numpy as np
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([10, 20, 30, 40])
print(arr1 + arr2) # 输出: [11 22 33 44]
print(arr1 * arr2) # 输出: [10 40 90 160]
广播机制
当两个数组形状不同,但满足特定条件时,NumPy 会自动扩展其中一个数组的形状,使其与另一个数组兼容,从而进行逐元素运算。例如:
import numpy as np
a = np.arange(3).reshape(3, 1)
b = np.arange(2).reshape(1, 2)
a, b
(array([[0.],
[1.],
[2.]]),
array([[0., 1.]]))
由于a
和b
分别是3×1和1×2矩阵,如果让它们相加,它们的形状不匹配。 我们将两个矩阵广播为一个更大的3×2矩阵,如下所示:矩阵a
将复制列, 矩阵b
将复制行,然后再按元素相加。
常用的数学函数
NumPy 提供了丰富的数学函数,可以对数组进行各种元素级的操作。例如:
import numpy as np
arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr)) # 输出: [1. 2. 3. 4.]
print(np.log2(arr)) # 输出: [0. 2. 3.169925 4. ]
在上述示例中,np.sqrt(arr)
计算数组中每个元素的平方根,np.log2(arr)
计算以 2 为底的对数。
索引和切片
在 Python 中,索引 和 切片 是用于访问和操作序列(如列表、元组、字符串等)中元素的基本方法。
索引
索引用于访问序列中的单个元素。Python 的索引从 0 开始,即第一个元素的索引为 0,第二个元素的索引为 1,依此类推。此外,Python 还支持负索引,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
如下所示,我们可以用[-1]
选择最后一个元素,可以用[1:3]
选择第二个和第三个元素:
X[-1], X[1:3]
除读取外,我们还可以通过指定索引来将元素写入矩阵。
1,直接索引修改单个元素:可以使用行索引和列索引直接访问并修改矩阵中的特定元素。
import numpy as np
# 创建一个 3x3 的矩阵
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 修改第二行第三列的元素为 99
matrix[1, 2] = 99
print(matrix)
[[ 1 2 3]
[ 4 5 99]
[ 7 8 9]]
2.切片操作批量修改元素:使用切片可以一次性修改矩阵中的多个元素。
import numpy as np
# 创建一个 4x4 的矩阵
matrix = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]])
# 将第二行和第三行的所有元素修改为 0
matrix[1:3, :] = 0
print(matrix)
[[ 1 2 3 4]
[ 0 0 0 0]
[ 0 0 0 0]
[13 14 15 16]]
3.布尔索引条件修改元素:通过布尔索引,可以根据条件修改矩阵中的元素。
import numpy as np
# 创建一个 3x3 的矩阵
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 将矩阵中所有大于 5 的元素修改为 -1
matrix[matrix > 5] = -1
print(matrix)
[[ 1 2 3]
[ 4 5 -1]
[-1 -1 -1]]
切片
在 Python 中,切片 是一种强大的工具,用于从序列(如列表、元组、字符串)或数组中提取子集。对于一维和多维数组,切片的用法有所不同。以下将分别介绍它们的用法。
1.一维数组的切片
一维数组的切片与 Python 列表的切片方式相似。切片的基本语法为:
array[start:stop:step]
#start:起始索引,包含该位置的元素,默认为 0。
#stop:结束索引,不包含该位置的元素,默认为数组的长度。
#step:步长,默认为 1。
例如,使用 NumPy 创建一个一维数组并进行切片:
import numpy as np
arr = np.array([0, 1, 2, 3, 4, 5, 6])
# 获取索引 2 到 5 的元素
slice1 = arr[2:6]
print(slice1) # 输出: [2 3 4 5]
# 获取前四个元素
slice2 = arr[:4]
print(slice2) # 输出: [0 1 2 3]
# 获取从索引 3 开始的所有元素
slice3 = arr[3:]
print(slice3) # 输出: [3 4 5 6]
# 每隔一个元素取一个
slice4 = arr[::2]
print(slice4) # 输出: [0 2 4 6]
# 反转数组
slice5 = arr[::-1]
print(slice5) # 输出: [6 5 4 3 2 1 0]
2.多维数组的切片
对于多维数组,切片操作需要为每个维度指定切片参数,使用逗号分隔。以下是一个二维数组的示例:
import numpy as np
# 创建一个 3x3 的二维数组
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 获取第 1 行的所有元素
slice1 = matrix[0, :]
print(slice1) # 输出: [1 2 3]
# 获取所有行的第 2 列
slice2 = matrix[:, 1]
print(slice2) # 输出: [2 5 8]
# 获取第 1 行到第 2 行,第 2 列到第 3 列的子矩阵
slice3 = matrix[0:2, 1:3]
print(slice3)
# 输出:
# [[2 3]
# [5 6]]
#matrix[0, :] 表示获取第 1 行的所有元素。
#matrix[:, 1] 表示获取所有行的第 2 列。
#matrix[0:2, 1:3] 表示获取从第 1 行到第 2 行(不包含第 3 行),以及从第 2 列到第 3 列(不包含第 4 列)的子矩阵。
需要注意的是,NumPy 的切片操作返回的是原数组的视图(view),这意味着对切片的修改会影响原数组。如果需要对数据进行独立的副本操作,可以使用 copy()
方法。
数组的堆叠
在 Python 的 NumPy 库中,数组的堆叠是指将多个数组按照特定的轴组合成一个新的数组。这对于数据的组织和处理非常有用。以下是常见的数组堆叠方法:
垂直堆叠
np.vstack:沿垂直方向(行)堆叠数组。要求被堆叠的数组在列数(第二维度)上相同。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
result = np.vstack((a, b))
print(result)
[[1 2]
[3 4]
[5 6]]
水平堆叠
np.hstack:沿水平方向(列)堆叠数组。要求被堆叠的数组在行数(第一维度)上相同。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5], [6]])
result = np.hstack((a, b))
print(result)
[[1 2 5]
[3 4 6]]
深度堆叠
np.dstack:沿第三个轴(深度)堆叠数组。适用于堆叠二维数组,结果是一个三维数组。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
result = np.dstack((a, b))
print(result)
[[[1 5]
[2 6]]
[[3 7]
[4 8]]]
沿新轴堆叠
np.stack:沿新轴堆叠数组。可以通过参数 axis
指定新轴的位置。所有被堆叠的数组必须具有相同的形状。
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
result = np.stack((a, b), axis=0)
print(result)
[[1 2 3]
[4 5 6]]
连接
np.concatenate:沿现有的轴连接数组。通过参数 axis
指定连接的轴。被连接的数组在除连接轴外的其他维度上必须具有相同的形状。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
result = np.concatenate((a, b), axis=0)
print(result)
[[1 2]
[3 4]
[5 6]]
axis=0
:沿着第一个轴(通常是行)进行连接。此时,被连接的数组在除第一个轴外的其他维度上必须具有相同的形状。
axis=1
:沿着第二个轴(通常是列)进行连接。此时,被连接的数组在除第二个轴外的其他维度上必须具有相同的形状。
axis=None
:当 axis
设置为 None
时,所有输入数组会在连接之前被展平为一维数组,然后进行连接。
保存与加载数组
保存和加载单个数组
np.save
和 np.load
:用于将单个数组保存为以 .npy
为扩展名的二进制文件,并从中加载数组。
import numpy as np
# 创建一个示例数组
arr = np.array([1, 2, 3, 4, 5])
# 保存数组到文件
np.save('array.npy', arr)
# 从文件加载数组
loaded_arr = np.load('array.npy')
print(loaded_arr)
上述代码将数组 arr
保存到当前目录下的 array.npy
文件中,然后加载该文件并打印内容。
保存和加载多个数组
np.savez
和 np.load
:用于将多个数组保存到一个以 .npz
为扩展名的压缩文件中,并从中加载数组。
import numpy as np
# 创建示例数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# 保存多个数组到一个文件
np.savez('arrays.npz', arr1=arr1, arr2=arr2)
# 从文件加载数组
data = np.load('arrays.npz')
print(data['arr1'])
print(data['arr2'])
在此示例中,arr1
和 arr2
被保存到同一个 arrays.npz
文件中。加载后,可以通过指定数组名称来访问各个数组。
保存和加载数组到文本文件
np.savetxt
和 np.loadtxt
:用于将数组保存为文本文件(如 .txt
或 .csv
),并从中加载数组。
import numpy as np
# 创建一个示例二维数组
arr = np.array([[1.5, 2.3, 3.1],
[4.2, 5.8, 6.4]])
# 保存数组到文本文件
np.savetxt('array.txt', arr, delimiter=',')
# 从文本文件加载数组
loaded_arr = np.loadtxt('array.txt', delimiter=',')
print(loaded_arr)
参数 delimiter
用于指定分隔符,即在保存数组到文本文件时,元素之间的分隔字符。默认情况下,delimiter
的值是一个空格 ' '
。如果希望使用其他分隔符(例如逗号、制表符等),可以通过设置 delimiter
参数来实现。
如果需要节省存储空间,可以使用 np.savez_compressed
函数,将数组以压缩格式保存到 .npz
文件中。
作者:失败尽常态523