Python一些知识

Python一些知识,第1张

概述不定期写一些学到的Python小知识  1关于字典中键的一些了解1.1字典的查找过程通过hash函数将key计算为哈希值;通过哈希值确定一个位置,这个位置是一个存放着可能存在冲突的元素的数组(即“桶”,bucket),每个元素都是一个键值对,理想情况下,这个数组里只有1个元素;遍历这个

不定期写一些学到的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 StopI@R_404_6704@ction as e:		print('Generator return value:', e.value)		break
3.3 迭代器

区分两个概念:

可以直接作用与for循环的对象统称为可迭代对象:I@R_404_6704@ble。可以被next()函数调用并不断返回下一个值的对象成为迭代器:I@R_404_6704@tor

List, tuple, dict, set, str, 生成器, 带yIEld的函数,这些虽然都是I@R_404_6704@ble,但只有生成器是I@R_404_6704@tor。要想将其他的数据类型也变成I@R_404_6704@tor,可以使用iter()函数。

总结

以上是内存溢出为你收集整理的Python一些知识全部内容,希望文章能够帮你解决Python一些知识所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1187007.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存