您的位置:首页 > 理论基础 > 数据结构算法

记录一下python的数据结构

2016-10-20 22:16 309 查看

记录一下python的数据结构

1 list

\>>> classmates = ['bob','mike']

\>>> classmates[0] # 从0开始索引

\>>> classmates[-1] # 直接获取最后一个元素;以此类推,[-2]为倒数第二个元素

####python中的数据索引和matlab的相左,python从0到元素个数最后一位的前一位,而matlab则是从1到元素个数的最后一位

\>>> classmates,append('adam') #末尾追加元素

\>>> classmates.insert(1,'jack') #索引插入

\>>> classmates.pop() #除去末尾元素

\>>> classmates.pop(i) #索引删除

\>>> classmates[1] = 'sarah' # 索引赋值

\>>> school = ['classmates1','classmates2',['mike','jack']]

\>>> school[2][1]
=  'mike'


2 array

标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间。

此外Python还提供了一个array模块,array对象和列表不同,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。

NumPy的诞生弥补了这些不足,NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。

所以使用前,需要`import numpy as np`

\>>> a = np.array([1,2,3,4])
\>>> b = np.array([[1,2,3][4,5,6]])

\#上面例子中的参数序列的元素都是整数,因此所创建的数组的元素类型也是整数,并且是32bit的长整型。
\#可以通过dtype参数在创建时指定元素类型:

\>>> np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)

= array([[  1.,   2.,   3.,   4.],
[  4.,   5.,   6.,   7.],
[  7.,   8.,   9.,  10.]])

\>>> np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.complex)

= array([[  1.+0.j,   2.+0.j,   3.+0.j,   4.+0.j],
[  4.+0.j,   5.+0.j,   6.+0.j,   7.+0.j],
[  7.+0.j,   8.+0.j,   9.+0.j,  10.+0.j]])

\>>> a.shape
= (4,)

\>>> b.shape
= (2,3)

\>>> b.shape = 3,2 # 对b进行调整
\>>> b
= ([[1,2][3,4][5,6]])

\>>> b.shape = 2,-1
\>>> b
= ([[1,2,3][4,5,6]])

\>>> d = a.reshape((2,2)) #创建1个改变了尺寸的新数组,且a和d共享内存,改变其中一个元素,会同时修改另一个

\>>> a = np.arange(10)
\>>> a
= [0,1..,8,9]

\>>> np.arange(0,1,0.1) #arange函数类似于range函数,通过指定开始值、终值和步长来创建一维数组,当然也是不包括终值的
= array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

\>>> np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6)
= array([[ 0,  1,  2,  3,  4,  5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])

\>>> a[5] #用整数做下标
\>>> a[3:5] #用范围做下标获取数组切片,包括a[3]但不包括a[5]
= array([3,4])

\>>> a[:5]
array([0,1,2,3,4])

\>>> a[:-1] #用法同list

\>>> a[2:4] = 100,101 # 索引修改值

\>>> a[1:-1:2] #第三个参数表示步长
= array([1, 3, 5, 7])

\>>> a[::-1] #数组头尾颠倒,省略范围的开始和结束
= array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

\>>> a[5:1:-2] #步长为负,则起始点要大于结束点
= array([5, 3])

\>>> b = a[3:7] #通过索引产生的新数组b,和a共享数据空间


3 tuple

tuple和list很像,但是tuple一旦初始化就不能修改。

\>>> classmates = ('Michael', 'Bob', 'Tracy')


classmates这个tuple就不能改变了;

tuple没有append(),insert()这样的方法;

其他获取元素的方法和list是一样的,可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素;

因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

>>> t = (1, 2) #定义一个tuple时,tuple的元素就必须被确定下来

>>> t

= (1, 2)

>>> t = () #定义一个空的tuple

>>> t

= ()

>>> t = (1,) #定义只有1个元素的tuple,需要加逗号

>>> t

= (1,)

>>> t = (‘a’, ‘b’, [‘A’, ‘B’]) # 将元素定义为list,尽管tuple指向不能变,但是list的指向可以改变,那tuple的内容就可以改变了

>>> t2 = ‘X’

>>> t2 = ‘Y’

>>> t

= (‘a’, ‘b’, [‘X’, ‘Y’])

4 dict

python内置,在其他语言中称为map

使用键-值(key-value)存储

优点是查找速度非常快

>>> d = {‘Michael’: 95, ‘Bob’: 75, ‘Tracy’: 85}

>>> d[‘Michael’]

= 95

>>> d[‘Adam’] = 67 #通过key值放入数据

>>> d[‘Adam’]

= 67

>>> ‘Thomas’ in d #通过in判断来key是否存在

= False

>>> d.get(‘Thomas’) #dict提供get方法,如果key不存在,可以返回None,或者自己指定的value:

>>> d.get(‘Thomas’, -1)

= -1

>>> d.pop(‘Bob’) #删除key用pop(key)方法,对应的value也会从dict中删除

>>> d

= {‘Michael’: 95, ‘Tracy’: 85}

>>> D.has_key(key) #有该键返回TRUE,否则FALSE

>>> D.keys() #返回字典键的列表

>>> D.values() #返回字典键的列表

>>> D.items()

>>> D.update(dict2) #增加合并字典

>>> D.popitem() #得到一个pair,并从字典中删除它;已空则抛异常

>>> D.clear() #清空字典,同del dict

>>> D.copy() #拷贝字典

>>> D.cmp(dict1,dict2) #比较字典(优先级为元素个数、键大小、键值大小): 第一个大返回1,小返回-1,一样返回0

#dictionary的复制

>>> dict1 = dict #别名,指向同一个字典

>>>dict2=dict.copy() #克隆,指向不同的字典

注意:

dict内部存放的顺序和key放入的顺序没有关系;

dict和list比较:

dict查找和插入的速度极快,不会随着key的增加而增加;

dict需要占用大量的内存,内存浪费多;

list查找和插入的时间随着元素的增加而增加;

list占用空间小,浪费内存很少。

dict的key必须是不可变对象;因为dict根据key来计算value的存储位置(哈希算法)。要保证hash的正确性,作为key的对象就不能变。python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的。

dict的value可以是任意类型

5 set

set类似于dict,是一组不重复的key的集合,但不存储value。

\>>> s = set([1, 2, 3])#要创建一个set,需要提供一个list作为输入集合
\>>> s
= set([1, 2, 3]) #传入的参数[1, 2, 3]是一个list,显示的set([1, 2, 3])只是告诉你这个set内部有1,2,3这3个元素,显示的[]并不表示这是一个list

\>>> s = set([1, 1, 2, 2, 3, 3])
\>>> s
= set([1, 2, 3])#重复元素在set中自动被过滤

\>>> s.add(4) #通过add(key)方法可以添加元素到set中
\>>> s
= set([1, 2, 3, 4])
\>>> s.add(4)
\>>> s
= set([1, 2, 3, 4])

\>>> s.remove(4) #通过remove(key)方法可以删除元素
\>>> s
= set([1, 2, 3])

\>>> s1 = set([1, 2, 3]) #set可以看成数学意义上的无序和无重复元素的集合
\>>> s2 = set([2, 3, 4])#因此,两个set可以做数学意义上的交集、并集等操作
\>>> s1 & s2
= set([2, 3])
\>>> s1 | s2
= set([1, 2, 3, 4])


注意:

set的原理和dict一样

唯一区别仅在于set没有存储对应的value

set同样不可以放入可变对象(比如list),因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”

6 string

计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。

最早的计算机采用8个比特(bit)作为一个字节(byte),一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。

比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。

由于计算机是美国人发明的,所以最早只有127个字母被编码到计算机里:大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码。

所以,中国制定了GB2312编码,用来把中文编进去。

但全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国的标准不可避免地出现了冲突,所以在多语言混合的文本中,显示出来会有乱码。

Unicode应运而生。

Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。

Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(非常偏僻的字符,就需要4个字节)。

现代操作系统和大多数编程语言都直接支持Unicode。

ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。

字母A用ASCII编码是十进制的65,二进制的01000001;

如果把ASCII编码的A用Unicode编码,只需要在前面补0就可以,因此,A的Unicode编码是00000000 01000001。

尽管统一成Unicode编码,乱码问题从此消失了。但是如果文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。

所以,出现了把Unicode编码转化为“可变长编码”的UTF-8编码。

UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节(所以ASCII编码实际上可以被看成是UTF-8编码的一部分),汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。

最后,在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

\>>> ord('A') #字母和对应的数字相互转换
= 65
\ >>> chr(65)
= 'A'
\>>> print u'中文'  #以unicode表示的字符用u'..'表示
= 中文

\>>> u'ABC'.encode('utf-8')#把Unicode编码表示的字符串转换为UTF-8
= 'ABC'
\>>> 'abc'.decode('utf-8') #把UTF-8编码表示的字符串转换为Unicode字符串
= u'abc'


#!/usr/bin/env python #告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;

# -*- coding: utf-8 -*- #告诉Python解释器,按照UTF-8编码读取源代码

>>> string = "Hello My friend"
>>> print string[0]
= H
>>> print string[0:5]
= Hello

#字符串包含判断操作符:in,not in
>>> print 'He' in string
= True
>>> print 'sHe' in string
= False

#后面跟数字表示字符串重复的次数,比如
print 'hello'*5
>>> hellohellohellohellohello

#string模块,还提供了很多方法,如
S.find(substring, [start [,end]]) #可指范围查找子串,返回索引值,否则返回-1

S.rfind(substring,[start [,end]]) #反向查找

S.index(substring,[start [,end]]) #同find,找不到时产生ValueError异常

S.rindex(substring,[start [,end]])#同上反向查找

S.count(substring,[start [,end]]) #返回找到子串的个数

S.lowercase()

S.capitalize()      #首字母大写

S.lower()           #转小写

S.upper()           #转大写

S.swapcase()        #大小写互换

S.split(str, ' ')   #将string转list,以空格切分

S.join(list, ' ')   #将list转string,以空格连接

#处理字符串的内置函数
len(str)                #串长度

cmp("my friend", str)   #字符串比较。第一个大,返回1

max('abcxyz')           #寻找字符串中最大的字符

min('abcxyz')           #寻找字符串中最小的字符

#string的转换

float(str) #变成浮点数,float("1e-1")  结果为0.1

int(str)        #变成整型,  int("12")  结果为12

int(str,base)   #变成base进制整型数,int("11",2) 结果为2

long(str)       #变成长整型

long(str,base)  #变成base进制长整型,

#字符串的格式化(注意其转义字符,大多如C语言的)
str_format % (参数列表) #参数列表是以tuple的形式定义的,即不可运行中改变
>>>print ""%s's height is %dcm" % ("My brother", 180)
= My brother's height is 180cm


关于格式化输出:

%d 整数

%f 浮点数

%s 字符串

%x 十六进制整数

格式化整数和浮点数还可以指定是否补0和整数与小数的位数:比如 %02d 和 %.2f

如果不太确定应该用什么,%s永远起作用,它会把任何数据类型转换为字符串

对于Unicode字符串,用法完全一样,但最好确保替换的字符串也是Unicode字符串:比如 u’Hi, %s’ % u’Michael’

用%%来表示一个%

如果只有一个%?,括号可以省略

7 不可变对象

list为可变对象。string为不可变对象

对于不可变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容;相反,这些方法会创建新的对象并返回,这样就保证了不可变对象本身永远是不可变的

本篇博客主要参考自

《用python做科学计算》

《Python自学笔记之基础内容回顾》

《Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结 》

《 Python list 操作》

《列表(list), 元祖(tuple), 字典(dict), 字符串(string), 集合(set) 的基本方法 》

《python 2.7教程》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: