Python一些知识
2021/4/27 20:28:18
本文主要是介绍Python一些知识,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
不定期写一些学到的Python小知识
1 关于字典中键的一些了解
1.1 字典的查找过程
- 通过hash函数将key计算为哈希值;
- 通过哈希值确定一个位置,这个位置是一个存放着可能存在冲突的元素的数组(即“桶”,bucket),每个元素都是一个键值对,理想情况下,这个数组里只有1个元素;
- 遍历这个数组,找到目标key,返回对应的value。
代码如下:
def lookup(d, key): h = hash(key) cl = d.dath[h] for pair in cl: if key == pair[0]: return pair[1] else: raise KeyError, 'Key %s not found." % key
在字典查询的hash函数应满足两个原则:
- 如果两个key产生了不同的hash值,那么这两个key对象是不相等的;---- 这个保证能从字典中查找到需要的正确的元素
- 如果两个key产生相同的hash值,那么这两个key对象是相等的;---- 这个保证了查询效率
1.2 字典key要满足的要求
要作为字典的key,对象必须要支持__hash__函数,并且满足上面两个原则
1.3 LIst对象为什么不能作为key?
-
list对象不支持__hash__函数
-
list对象实现__hash__函数有两种实现方式:基于id和基于内容,然而两种方式对于list对象来说都有一定的副作用,所以Python规定内置的list对象不能作为字典的key。
-
tuple对象可以作为字典的key,tuple对象就是基于内容实现的__hash__函数,但是若tuple中有元素是可变对象,一人不可以作为字典的key。
-
用户自定义的类型可以作为字典的key,默认的
hash(object)
是id(object)
,默认的cmp(object1, object2)
是cmp(id(object1), id(object2))
。特别注意的是,用户自定义类型是可变的,但依然可以作为字典的key。因为一般来说id比内容更重要,可以基于id来hash。若内容比id重要,可以在定义类的时候重载__hash__函数和__cmp__函数。
2 赋值/浅拷贝/深拷贝
2.1 几个概念
- 变量:是一个系统表的元素,拥有指向对象的连接空间
- 对象:被分配的一块内存,存储其所代表的值
- 引用:是自动形成的从变量到对象的指针
- 类型:属于对象,而非变量
- 不可变对象:一旦创建就不可修改的对象,包括字符串/元组/数值类型
(该对象所指向的内存中的值不能被改变。当改变没某个变量时,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新地址,变量再指向这个新的地址。) - 可变对象:可以改变的对象,包括列表/字典/集合
(该对象所指向的内存中的值可以改变。变量改变后,实际上是所指的值直接发生改变,并没有发生复制行为,也没有开辟新的地址,也就是原地改变)
2.2 区别
- 赋值:只是复制了新对象的引用,不会开辟新的内存空间。
并不会产生一个独立的对象单独存在,只是将原有的数据块打上一个新的标签,所以当其中一个标签被改变时,数据块就会发生变化,另一个标签也会随之改变。 - 浅拷贝:创建新的对象,其内容都是原对象的引用。
浅拷贝分两种情况讨论:
(1)当浅复制的值是不可变对象是和“赋值”一样,对象的id值与浅复制原来的值相同。
(2)当浅复制的值是可变对象时会产生一个“稍微有点依赖的对象”存在:- 第一种情况:复制的对象中无复杂的子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也不会影响原来的值。原来的id值与浅复制的id值不同。
- 第二种情况:复制的对象中有复杂子对象,如果不改变其中复杂子对象,浅复制的值改变与原来的值改变互不影响。但是改变复杂子对象,浅复制的值改变与原来的值改变会互相影响。
- 深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。
所以改变原有被复制对象不会对已经复制出来的新对象产生影响。不过对于不可变对象来说,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。
3. 列表生成式/生成器/迭代器
3.1 列表生成式
#### 三种格式 ## 1 [x * x for x in range(1, 11)] ## 2 [x * x for x in range(1, 11) if x % 2 == 0] ## 3 [x * x if x % 2 == 0 else -x for x in range(1, 11)]
3.2生成器
通过列表生成器会占用很大的内存空间,而生成器可以是我们一边循环一边生成想要的数据。
创建方法:
## 1. g = (x * x for x in range(1, 11)] next(g) # 通过next()来获取每一个生成值 ## 2.利用yield将函数转换成关键字 def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n += 1 return 'done' ## 3.捕获原来函数的返回值 g = fib(6) while True: try: x = next(g) print('g', x) except StopIteraction as e: print('Generator return value:', e.value) break
3.3 迭代器
区分两个概念:
- 可以直接作用与
for
循环的对象统称为可迭代对象:Iterable
。 - 可以被
next()
函数调用并不断返回下一个值的对象成为迭代器:Iterator
。
list
, tuple
, dict
, set
, str
, 生成器, 带yield
的函数,这些虽然都是Iterable
,但只有生成器是Iterator
。要想将其他的数据类型也变成Iterator
,可以使用iter()
函数。
这篇关于Python一些知识的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-25Python编程基础:变量与类型
- 2024-11-25Python编程基础与实践
- 2024-11-24Python编程基础详解
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南
- 2024-11-16`PyMuPDF4LLM`:提取PDF数据的神器