1. 一些跟数据结构有关的函数
1.1 copy()
这个东西理解起来特别容易,但是描述起来超级繁琐。
通过三个例子来说明:
例一:
lst1 = [1,2,[3,4,5],6,7]
lst2 = lst1
lst2 == lst1
# 返回True,是说这两个列表的内容是相同的
lst2[0] = 100
lst2 == lst1
# 改变了lst2的索引号为0的元素的值后,lst1和lst2的内容还是相同的。
lst1
[100,2,[3,4,5],6,7]
这个原因是,列表内元素,都是以引用地址的形式呈现的,大概就是[地址0,地址1,地址2…],用 = 来赋值的话,相当于复制了一个列表内的元素的引用地址,实际上这两个列表里的元素的地址都指向内存中的同一个位置。
也就是说,如果要通过lst1 里的引用地址来修改内容,修改的是lst1 和lst2 两个列表的引用地址共同指向的内存位置,所以,以 = 来“复制”列表的话,改其中一个,另一个也会跟着一起改。
例二:
lst3 = [1,2,[3,4],5]
lst4 = [1,2,[3,4],5]
lst3 == lst4
# 返回值为True,说明这两个列表内容是相同的
lst3[0] = 100
lst3 == lst4
# 返回值为False,说明这两个列表的内容现在不一样了
lst3
[100,2,[3,4],5]
lst4
[1,2,[3,4],5]
像这样,用 = 直接给列表定义内容,就是新在内存中创造了一个列表,lst3 和lst4 内元素的引用地址是不同的,指向的内存位置也是不同的,只不过这两个位置,储存的内容是一样的。
所以,通过其中一个列表的引用地址更改内容时,另一个列表不会随之变化。实际上这两个列表没有什么实际的联系,只能说,定义之后的内容是一样的。
例三:
lst5 = [1,2,[3,4],5]
lst6 = lst5.copy()
lst6
[1,2,[3,4],5]
# copy()可以复制一个列表
lst6[0] = 100
lst6 == lst5
# 返回值为False,就是说明这两个列表的内容是不一样的。
lst6[0] = 1
# 把刚刚改的元素改回原值
lst6[2][0] = 99
lst5 == lst6
# 返回值为True,说明这两个列表的内容是一样的,你说牛逼不
lst5
[1,2,[99,4],5]
这个copy() 也叫浅拷贝(听起来很low逼),影子拷贝(shadow copy,这个听起来牛逼)。
copy() 在复制的时候,遇到一些简单的元素,就复制其内容,但是给予不用的引用地址;遇到一些复杂的元素,例如列表等,就只复制引用地址,内容是不复制的。
复制的列表内的这个复杂元素,和原列表的这个元素一样,它们的引用地址指向同一个内存位置。
所以,当更改列表内简单元素时候,另一个列表不会随之变化,因为,更改的是不同内存位置上的内容。但是更改复杂元素时,实际上更改的是同一处内存位置上的内容,所以另一个会随之变化。
1.2 deepcopy()
首先要
import copy
它叫做深拷贝,它的效果就是,连着列表内复杂元素的内容一同拷贝,不会出现一改具改的情况。
用法,例:
lst10 = copy.deepcopy(lst11)
1.3 random 模块(好像和数据结构没什么关系)
据说计算机的随机数是伪随机数,有点不太懂。
首先,使用之前当然要:
import random
1.3.1 random.randint(start,stop)
在[start,stop] 这个闭区间内,随机生成一个数字,返回值是这个数字。
1.3.2 random.choice(seq)
从一个非空序列里面,随机选出一个元素。这个非空序列可以是列表,可以使可迭代对象。
返回值为元素值。
如果括号内的可迭代对象只有一个元素,那么选出的值就是这个元素。
1.3.3 random.randrange([start,]stop[,step])
从指定范围的range中,随机获取一个元素,返回值是这个元素。
用法和range() 一样。
注意,range() 和上面的范围,start、stop和step都必须是int 。
1.3.4 random.shuffle(lst)把
把指定的列表内的元素,顺序随机打乱。
就地修改,返回值为None。
2. 元组 tuple
tuple n.元组,数组
元组用() 来表示
a = (1,2,3,4)
b = (1,)
定义只有一个元素的元组,只用括号是不行的,因为括号是一个运算符号,改变运算的优先级用的,所以当有一个元素时,定义元组后面要加逗号。
元组是一个有序元素的集合,这个有序不是指元组内元素的内容有顺序,是指元组内元素的位置有顺序,和list 类似。
元组是一个不可变的对象,就是说一旦定义完成,就不能再修改了。严格来说不能在这个元组自身就地修改。可以当做一个属性为只读的列表
元组可以节省内存空间,我的理解是,对比于list来看,创建一个list的,需要开辟出比定义list时所需的更大的内存空间,因为不知道这个list会不会增加。但是元组不一样,元组一旦定义就无法修改,所以所需的内存空间是一定的。这样相对于list,就能节省内存空间。
2.1 元组的定义
谨记,Python里,赋值既定义。元组的定义有三种方法:
第一种,像上面一样直接定义元素:
t = ('a','fuck','xiaodaizi',666)
# 把元素直接填在()的里面
t1 = ('enter')
type(t1)
str
t2 = (5)
type(t2)
int
# 理由如上,()是个运算符,改变优先级的,定义元组时,这样不好使
t3 = (5,)
type(t3)
tuple
# 所以以这种方式定义一个元素的元组时,这个元素后面必须加个 ,
第二种,tuple(iteratable):
t = tuple(range(5))
t
(0,1,2,3,4)
type(t)
tuple
t1 = tuple([1,2,'fuck'])
t1
(1,2,'fuck')
type(t)
tuple
也就是说,在tuple()函数的括号中,放一个可迭代对象,可以把可迭代对象中的元素,依次放在元组里,产生一个新的元组。
注意,括号里只能放一个可迭代对象。
第三种,通过+ 和* 产生新的元组:
t = (1,2)
t1 = (3,4,5)
t + t1
(1,2,3,4,5)
t * 2
(1,2,1,2)
要注意的是,元组是不可变得,不存在增删改。这样的+ 和* 的操作,都不是就地修改,而是创建一个新的元组,可以用标识符在接住这个新元组。(接住这个动词觉得特别形象。)
2.2 元组的访问
说白了就是查看元组的内容。
tuple[ ],元组的标识符,后面加索引号:
t = (1,2,3,4,5,'fuck')
t[5]
'fuck'
# 这种是通过索引号来访问,返回元素的值
tuple.index(value,[start,[stopl]]) :
t.index(5)
4
# 通过值来查询,从左往右查找,查找到第一个符合要求的值,就结束,返回索引号
后面的[start,[stop]] 可以界定查找范围,可以只写start ,就是从索引号为start 的值开始查找,从自身这个值开始,查找到符合条件的第一个,返回。
也可以start 和stop 都写,从start 开始,在stop 结束,注意,这里是左闭右开区间,就是,如果stop 索引号位置的元素是第一个出现的想要查找的值,会报出没有查找到符合条件的值。
2.3 可以用于元组的一些函数
2.3.1 tuple.count(value)
查看这个tuple 里,值为value 的元素有多少个。
t = (1,2,3,4,4,4,5)
t.count(4)
3
2.3.2 len(tuple)
用法和前面用在list 的时候一样,返回tuple 的长度,这个长度也就是tuple 的元素个数。
2.3 namedtuple()
这是一个挺难用的函数,但是返回的结果很平易近人。
命名元组,是元组的一个子类(subclass) 。
我的理解是,通过这个函数,创造出一种模式,这种模式能给予元组一些提示的字符串,之后输出这个命名元组的时候,能显示这个命名元组中,每一个元素的相关信息。
2.3.1 namedtuple() 的使用格式
帮助里写道:’Returns a new subclass of tuple with named fields.’。
“返回一个新的,元素带有名称(提示信息)的元组子类”
首先,namedtuple() 是collections 模块下的一个函数,所以使用前要:
import collections
# 正常方法
# 这么导入模块之后,使用时要用加上模块名 a = collections.namedtuple()...
from collections import namedtuple
# 新学的方法,查阅了一下,貌似两个有很大不同,暂时有点没想通
# 这样使用时,不用加模块名 a = namedtuple()...
定义的格式:identifier = namedtuple(typename, field_names)
(其实括号里还有很多内容,不过先知道这两个就能正常使用了)
举个例子:
import collections
shape = collections.namedtuple('BWH', 'bust,waist,hip')
# 定义一个命名元组shape ,'BWH'是这个命名元组的类型,和值类型无关,是给人看的,就算是提示信息吧。
# 类型后面是,这个命名元组的元素都代表什么,也算是提示信息吧
# 其中元素名称用一个长字符串表示,不同的元素名称之间用' ' 或 , 隔开。
kloss = shape(86,58.5,86.5)
KimHyunA= shape(88.9,58.42,86.36)
# 前面的是标识符,shape是命名元组的标识符,相当于一种模式,后面是元素数据,这么赋值。给的值个数,要和定义命名元组时的个数相匹配,多或少都会报错
print(kloss)
BWH(bust=86, waist=58.5, hip=86.5)
# 打印的格式如上
KimHyunA.hip
86.36
# 也可以通过元素的名称来查询,某一个通过命名元组来赋值的标识符的某项元素