Python的数据结构(二)

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
# 也可以通过元素的名称来查询,某一个通过命名元组来赋值的标识符的某项元素

猜你喜欢

转载自blog.csdn.net/LittleHuang950620/article/details/81460584