这里介绍一下python 常用的数据结构,还有小技巧。
序列
列表,元组,字符串都是序列,序列有索引(就是下标操作)和切片操作。就是说前面说的3个的结构都可以这样用,以切片操作为例:
>>> shoplist = ['apple', 'mango', 'carrot', 'banana']
>>> print shoplist[0:2]
['apple', 'mango']
>>> print shoplist[0:-1]
['apple', 'mango', 'carrot']
赋值和引用的区别(新增)
要将一个对象(无论是序列还是字符串)赋值给另外一个对象,要用切片操作!!!若直接将一个对象名赋值到另一个,就是引用。引用的话,若原对象内容改变了,那么引用它的对象的内容也会发生改变;反之,若引用的对象改变了,原对象的内容也会改变!举个栗子:
>>> shoplist = ['apple', 'mango', 'carrot', 'banana']
>>> mylist = shoplist # mylist is just another name pointing to the same object!
>>> del shoplist[0]
>>> print 'shoplist is', shoplist
shoplist is ['mango', 'carrot', 'banana']
>>> print 'mylist is', mylist
mylist is ['mango', 'carrot', 'banana']
>>> del mylist[-1]
>>> print 'shoplist is', shoplist
shoplist is ['mango', 'carrot']
>>> print 'mylist is', mylist
mylist is ['mango', 'carrot']
可以看到,无论是把原来的shoplist更改了,还是把mylist更改了,两者都会变。因为引用的本质是把让一个对象指向另一个对象的地址,即mylist只是指向了shoplist的地址,内容是一样的。
若使用切片进行赋值,则会把元素复制过去,之后的操作,两者互不影响:
>>> mylist = shoplist[:] # make a copy by doing a full slice
>>> del mylist[0] # remove first item
>>> print 'shoplist is', shoplist
shoplist is ['mango', 'carrot', 'banana']
>>> print 'mylist is', mylist
mylist is ['carrot', 'banana']
列表
列表的定义和可用操作
列表用中括号来指示,如下:
shoplist = ['apple', 'mango', 'carrot', 'banana']
>>> dir(shoplist)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
通过是用dir()函数,可以看到这个列表可以使用的一些操作,实际上就是列表结构模块的成员函数。有add,contains,sizeof,str,insert,pop,remove,sort等操作。我们随意是一下,例如add:
>>> shoplist.add('egg')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'add'
报错说并没有add属性,是为什么呢?可以看到__add__带有下划线,这是私有函数(或者变量),不能直接在外部调用。我们可以试一下append:
>>> shoplist.append('egg')
>>> print shoplist
['apple', 'mango', 'carrot', 'banana', 'egg']
>>>
这下成功了!所以,对于列表类型的数据,我们可以使用append,count,extend,insert,remove,pop,reverse,sort这些操作。这些操作的具体使用方法和效果可以自己试一下。
若不想试,可以在交互式解释器下使用help(list)来查看所有成员函数的使用方法和详细介绍,千万不要忘记看完输入quit退出。
Help on class list in module __builtin__:
class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable's items
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __delitem__(...)
| x.__delitem__(y) <==> del x[y]
|
| __delslice__(...)
| x.__delslice__(i, j) <==> del x[i:j]
|
| Use of negative indices is not supported.
|
| __eq__(...)
列表元素的获得
列表元素可以使用下标(从0开始)来获取,也可以用for i in shoplist 来获取每个元素
例如:
print shoplist[2]
carrot
元组
元组和列表十分类似,只不过元组和字符串一样是 不可变的 即你不能修改元组。元组通过圆括号中用逗号分割的项目定义。元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候,即被使用的元组的值不会改变。
但是,元组可以嵌套!
#!/usr/bin/python
# Filename: using_tuple.py
zoo = ('wolf', 'elephant', 'penguin')
print 'Number of animals in the zoo is', len(zoo)
new_zoo = ('monkey', 'dolphin', zoo)
print 'Number of animals in the new zoo is', len(new_zoo)
print 'All animals in new zoo are', new_zoo
print 'Animals brought from old zoo are', new_zoo[2]
print 'Last animal brought from old zoo is', new_zoo[2][2]
输出
$ python using_tuple.py
Number of animals in the zoo is 3
Number of animals in the new zoo is 3
All animals in new zoo are ('monkey', 'dolphin', ('wolf', 'elephant', 'penguin'))
Animals brought from old zoo are ('wolf', 'elephant', 'penguin')
Last animal brought from old zoo is penguin
变量zoo是一个元组,我们看到len函数可以用来获取元组的长度。这也表明元组也是一个序列。
由于老动物园关闭了,我们把动物转移到新动物园。因此,new_zoo元组包含了一些已经在那里的动物和从老动物园带过来的动物。回到话题,注意元组之内的元组不会失去它的身份。
我们可以通过一对方括号来指明某个项目的位置从而来访问元组中的项目,就像我们对列表的用法一样。这被称作 索引 运算符。我们使用new_zoo[2]来访问new_zoo中的第三个项目。我们使用new_zoo[2][2]来访问new_zoo元组的第三个项目的第三个项目。
含有0个或1个项目的元组:一个空的元组由一对空的圆括号组成,如myempty = ()。然而,含有单个元素的元组就不那么简单了。你必须在第一个(唯一一个)项目后跟一个逗号,这样Python才能区分元组和表达式中一个带圆括号的对象。即如果你想要的是一个只包含项目monkey的元组的时候,你应该指明singleton = (‘monkey’, )。
格式化输出
下面讲的是一个常用技巧——格式化输出
#!/usr/bin/python
# Filename: print_tuple.py
age = 22
name = 'Swaroop'
print '%s is %d years old' % (name, age)
print 'Why is %s playing with that python?' % name
注意,第一行输出什么呢:
$ python print_tuple.py
Swaroop is 22 years old
Why is Swaroop playing with that python?
print语句可以使用跟着%符号的项目元组的字符串。这些字符串具备定制的功能。定制让输出满足某种特定的格式。定制可以是%s表示字符串或%d表示整数。元组必须按照相同的顺序来对应这些定制。
观察我们使用的第一个元组,我们首先使用%s,这对应变量name,它是元组中的第一个项目。而第二个定制是%d,它对应元组的第二个项目age。
Python在这里所做的是把元组中的每个项目转换成字符串并且用字符串的值替换定制的位置。因此%s被替换为变量name的值,依此类推。
print的这个用法使得编写输出变得极其简单,它避免了许多字符串操作。它也避免了我们一直以来使用的逗号。
在大多数时候,你可以只使用%s定制,而让Python来提你处理剩余的事情。这种方法对数同样奏效。然而,你可能希望使用正确的定制,从而可以避免多一层的检验程序是否正确。
在第二个print语句中,我们使用了一个定制,后面跟着%符号后的单个项目——没有圆括号。这只在字符串中只有一个定制的时候有效。
注意,这里和C不一样的是,所有的格式化输出在前,变量在后,用括号包含。
字典
字典类似于你通过联系人名字查找地址和联系人详细情况的地址簿,即,我们把键(名字)和值(详细情况)联系在一起。注意,键必须是唯一的,就像如果有两个人恰巧同名的话,你无法找到正确的信息。
注意,你只能使用不可变的对象(比如字符串)来作为字典的键,但是你可以不可变或可变的对象作为字典的值。基本说来就是,你应该只使用简单的对象作为键。
键值对在字典中以这样的方式标记:d = {key1 : value1, key2 : value2 }。注意它们的键/值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。
记住字典中的键/值对是没有顺序的。如果要使用有序字典,需要使用collections模块里的OrderedDict,这样词典中的顺序和添加的时候的顺序一致。否则,即使使用了字典中的sort功能,也只是按照键值的字母顺序排序。
字典的创建
#方法1
phonebook={'Alice':'2342','Tony':'6534'}
#方法2
items=[('name','Alice'),('age',42)]
d=dict(items)
#方法3
d=dict(name='Alice',age=42)
调用
>>> print d['name']
>>> 'Alice'