不可变对象和可变对象
- 不可变对象:对象对应内存中的值不会变,因此如果指向该对象的变量被改变了,Pyhton则会重新开辟一片内存,变量再指向这个新的内存,包括int、float、str、tuple(元组)等。
例:1
2
3
4
5
6a = 1
b = a
b = 2
print(a)
# result: a = 1 - 可变对象:对象对应内存中的值可以改变,因此变量改变后,该对象也会改变,即原地修改,如list、dictionary、set等。
1
2
3
4
5
6a = [1]
b = a
b.append(2)
print(a)
# result: a = [1,2]
注:
1 | a = [1] |
这里的变量a没有发生任何变化因为变量b指向了一个新的内存,详见下列代码进行对比:
1 | a = [1] |
1 | a = [1] |
浅拷贝和深拷贝
- 浅拷贝:使用copy()函数,拷贝了list最外围,而list内部的对象仍然是引用。
- 深拷贝:使用deepcopy()函数,list内外围均为拷贝,因此前后的变量完全隔离,而非引用。
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import copy
a = [1,2,3,[1,2,3]]
b = a #变量内外部都是引用
c = copy.copy(a) #浅拷贝,内部是引用
d = a[:] #同上
e = copy.deepcopy(a) #深拷贝,内外部都完全隔离不是引用
a.append(4)
a[3].append(4)
print(b)
print(c)
print(d)
print(e)
'''
result:
[1, 2, 3, [1, 2, 3, 4], 4]
[1, 2, 3, [1, 2, 3, 4]]
[1, 2, 3, [1, 2, 3, 4]]
[1, 2, 3, [1, 2, 3]]
'''
局部变量和全局变量
- 局部变量是无法修改全局变量的。想要实现局部修改全局变量,通常有两种办法,增加globa等关键字,或者使用list和dict等可变对象的内置函数。
例:1
2
3
4
5
6
7a = 1
def local():
a = 2 #局部变量,可以看做为新的变量
local()
print(a)
# result: 11
2
3
4
5
6
7
8
9
10
11a = 1
b = [1]
def local():
global a #使用global关键字,表明在局部使用的是全局的a变量
a = 2
b.append(2) #对于可变对象,使用内置函数则会修改全局变量
local()
print(a)
print(b)
# result: 2,[1,2]
高阶函数
- abs(): 返回数字的绝对值
例:1
2
3print(abs(-1))
# result: 1 - map(): 可以将一个函数映射作用到可迭代的序列中,并返回函数输出的序列
例:1
2
3
4
5
6def f(x):
return x + 1
result = list(map(f,[1,2,3])) #python3中输出前需要转化为list
print(result)
# reuslt: [2, 3, 4] - reduce(): 输入的函数需要传入两个参数。reduce()的过程是先使用输入函数对序列中的前两个元素进行操作,得到的结果再和第三个元素进行运算,直到最后一个元素。
例:1
2
3
4
5
6
7from functools import reduce
def f(x, y):
return x*10+y
result = reduce(f, [1, 2, 3, 4])
print(result)
#result: 1234 - filter(): 通过输入函数对可迭代序列进行过滤,并返回满足过滤条件的可迭代序列
例:1
2
3
4
5
6def is_odd(n):
return n % 2 == 0
result = list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
print(result)
#result: [2, 4, 6, 10] - sorted(): 函数可以完成对可迭代序列的排序。与列表本身自带的sort()函数不同,这里的sorted()函数返回的是一个新的列表。sorted()函数可以传入关键字key来指定排序的标准,参数reverse代表是否反向。
例:1
2
3
4result = list(sorted([3, 5, -87, 0, -21], key=abs, reverse=True)) # 绝对值排序,并且为反序
print(result)
#result: [-87, -21, 5, 3, 0] - 对于一些简单逻辑函数,可以使用lambda匿名表达式来取代函数的定义,类似于def
例:1
2add = lambda x,y: x + y
print(add(1,2))
迭代器与生成器
- 迭代器(iterator): 不要求事先准备好整个迭代过程中所有的元素,可以使用next()来访问元素。Python中的容器,如list、dict和set等,都属于可迭代对象,对于这些容器,我们可以使用iter()函数封装成迭代器。
例:上面的例子证明了迭代器之间相互独立1
2
3
4
5
6x = [1,2,3,4,5,6]
y = iter(x)
z = iter(x)
print(next(y),next(z))
#result: 1 1 - 生成器(generator):是迭代器的一种,可以控制循环遍历的过程,实现一边循环一边计算,并使用yield来返回函数值,每次调用到yield会暂停。生成器迭代的序列可以不是完整的,从而可以节省出大量的内存空间。
例:斐波那契数列1
2
3
4
5
6
7
8
9
10
11
12
13def fibonacci():
a = [1, 1]
while True:
a.append(sum(a)) # 往列表里添加下一个元素
yield a.pop(0) # 取出第0个元素,并停留在当前执行点
result = []
for x in fibonacci():
if x > 10:
break # 仅打印小于10的数字
result.append(x)
print(result)
#result: [1, 1, 2, 3, 5, 8] - 还可以使用”()”创建生成器
例:1
2
3
4a = (x for x in range(1,10))
print(next(a))
#result: 1
money money money~ money money~
- 本文链接:http://yoursite.com/2020/08/07/DL_P5/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues