Python学习笔记(二)

Published: 2013-12-06 Category: python Tags: python

Python学习二

在学习python之前,个人建议先看下维基的python介绍。

列表和元祖


1、通用序列操作

个人认为,它所谓的序列可以理解为数组,比如:

>>> jia = ['zhangjia',42]
>>> wancai = ['chenwancai',23]
>>> member = [jia,wancai]
>>> print(member)
[['zhangjia', 42], ['chenwancai', 23]]
>>> 

在这里我也就用它的说法,使用“序列”这个词来介绍数组吧。所有的序列类型都能进行某些特定的操作,比如索引、分片、加减乘、及 检查某个元素是否序列的成员等等。

序列中的所有元素都是有编号的–从0开始递增。像数组一样,这些元素可以分别访问。

>>> hello = 'mylife'
>>> hello[3]
'i'
>>> 'mylife'[4]
'f'
>>> 

使用负数时,python会从右边也就是最后一个元素开始计数,最后那个元素的编号是-1,因为0已经用了。

如果函数返回的是一个序列,那么可以直接对结果进行索引操作,如下:

>>> year = raw_input('year:')[3]
year:2013
>>> year
'3'
>>> 

下面代码是一个小程序,功能是输入年月日,然后得到相应的年月日名称:


#根据给定的年月日以数字的形式打印出日期
months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
endings = ['st'.'nd'.'rd']+17*['th']\
+['st','nd','rd']+7*['th']\
+['st']
year = raw_input("year:")
month = raw_input("month[1-12]:")
day = raw_input("day[1-31]:")

month_number = int(month)
day_number = int(day)

month_name = months[month_number-1]
day_name = day + endings[day_number-1]

print('result:'+year + month_name + day_name)

上面的小程序可以看出,python中的数组中是可以有运算的。

下面讲讲序列的分片,使用索引时只能访问单个元素,而使用分片可以访问一定范围内的元素,如下:

>>> tags = 'what\'s your name?<\a>'
>>> tags[2:8]
"at's y"
>>> tags[8:-5]
'our nam'
#注意:分片操作的实现需要提供两个索引的边界,第一个索引的元素是包含在分片内的,而第二个索引元素却并不包含在分片内!

#所以下面的代码是可行:
>>> abc = ['1','2','3','4','5','6']
>>> abc[2:7] #7超出了abc序列的边界
['3','4','5','6']

优雅的捷径:如果需要从结尾开始计数,那么可以采用abc[-3:] //结果为[‘4’,’5’,’6’],第二个索引置为空就能取到最后三个元素了。

这种方法同样适用于序列开始的元素:abc[:3] //结果[‘1’,’2’,’3’],实际上如果需要复制整个序列,可以这样做abc[:],也就是 将前后两个索引都置为空。

步长的概念abc[::3] //输出[‘1’, ‘4’],表示取到的是从开始到结尾每隔3个的元素。如果不便理解可以自己做实验。 步长不能为0,但可以为负数,表示从右到左提取元素。如abc[7:1:-2] //输出[‘6’, ‘4’]

总结:在这里得到正确的分片结果可能会费一些脑筋,开始点的元素包含在结果之中,而结束点的元素却不包含在结果中。 当使用负数做步长时,必须让开始索引大于结束索引。但没有正确制定开始和结束点的时候,正负数的使用可能会带来一些 混淆。但python会帮我们进行正确的操作,整数步长会从头部开始提取元素,步长为负数的话就从尾部开始提取元素。


序列加法:

[1,2,3]+[4,5,6]
>>> [1, 2, 3, 4, 5, 6]
#只有相同类型的序列才能进行连接操作

序列的乘法:

>>> 'python'*6
'pythonpythonpythonpythonpythonpython'
>>> [23]*5
[23, 23, 23, 23, 23]

空列表和初始化

python有一个内建值None,表示什么也么有,因为如果想初始化一个10长度的序列,可以使用[None]*10


为检查一个值是否在一个序列中,可以使用in运算符,如:

>>> 'p' in 'Python'
False
>>> 'py'in'python'
True
>>> x = ['zhang','jia','jia58960']
>>> 'jia' in x
True

下面的代码展示了用户输入的用户名和PIN码是否在列表中,

>>> psw = [['zhangjia','123456'],\
       ['wancai','123'],\
       ['yingqi','456']]
>>> user = raw_input('input username')
input usernamezhangjia
>>> pin = raw_input('input pin')
input pin123456
>>> [user,pin] in psw
True
>>> 

长度、最小值和最大值

内建函数:len、min和max非常有用,一看就很明白,len返回列表的长度,min和max分别返回列表中 最大和最小的元素值。例如:

>>> numbers = [1,2,3,5,9,6,12]
>>> max(numbers)
12
>>> len(numbers)
7
>>> min(numbers)
1
>>> max(3,5,2,6,3)
6
#注:上句代码中max函数和min函数的参数并不是一个序列,而是以多个数字直接作为参数。

列表:Python的“苦力”

根据字符串来创建列表的函数list,如下:

>>> str = 'hello world! '
>>> list(str)
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', ' ']
>>> 
#注意,list函数适用于所有类型的序列,而不只是字符串。

基本的列表操作:

>>> #改变列表
>>> s = [1,2,3]
>>> s[0]=4
>>> s
[4, 2, 3]
>>> #删除列表
>>> del s[2]
>>> s
[4, 2]
>>> #分片赋值(使用分片赋值可以使用与原序列不等长的序列将分片替换)
>>> name = list('perl')
>>> name[1:] = list('ython')
>>> name
['p', 'y', 't', 'h', 'o', 'n']
>>> #分片赋值(可以插入新的元素)
>>> number = [1,6]
>>> number[1:1] = [2,3,4,5]
>>> number
[1, 2, 3, 4, 5, 6]
>>> #分片赋值(同理,来删除元素)
>>> number[1:6] = []
>>> number
[1]
#大家可以尝试利用1之外的步长甚至是负数进行分片

列表方法

#append方法(在列表后追加新的对象)
>>> abc = [1,2,3,4,5]
>>> abc.append(6)
>>> abc
[1, 2, 3, 4, 5, 6]
#注:append方法是修改原来的列表!

#count方法统计某个元素在列表中出现的次数,如:
>>> abc.append(3)
>>> abc.count(3)
2
>>>

#extend方法可以在列表末尾追加另一个序列中的多个值。
>>> a = [1,2,3,4]
>>> b = [5,6,7,8]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]
>>> 
#这样看起来像连接操作,但extend是修改了被扩展的序列,如上例中a序列已变。而原始的连接操作则不然,它会返回
#一个全新的列表

#index方法是从列表中找出某个值第一个匹配项的索引位置。
>>> t = ['we','are','friends']
>>> t.index('are')
1

#insert方法用于将对象插入到列表中
>>> a.insert(4,'five')
>>> a
[1, 2, 3, 4, 'five', 5, 6, 7, 8]
>>> 
#虽然用分片的方法也可以实现,但可读性远不如insert方法分片实现如下:
>>> a[4:4] = ['five']
>>> a
[1, 2, 3, 4, 'five', 5, 6, 7, 8]
>>> 

#pop方法移除列表中的一个元素(默认是最后一个),并返回该元素的值
>>> a.pop(4)
'five'
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]
#注意:pop方法是唯一一个既能修改列表又能返回元素值的列表方法。

#remove方法用于移除列表中某个值的第一个匹配项
>>> a.remove(4)
>>> a
[1, 2, 3, 5, 6, 7]
#remove方法是一个没有返回值的原位置改变方法,它修改了列表却没有返回值,与pop方法正好相反。

#reverse方法用于讲列表中的元素反向存放
>>> a.reverse()
>>> a
[7, 6, 5, 3, 2, 1]
>>> 
#如果需要对一个序列进行反向迭代,那么可以使用reserved函数,这函数并不返回一个列表,而是返回一个
#迭代器(itera)对象,尽管如此使用list函数把返回的对象转换成列表也是可行的:
>>> list(reversed(a))
[23, 8, 8, 7, 6, 6, 4, 3, 2, 2, 1]
>>> 

#sort方法用于在原位置对列表进行排序。在“原位置排序”意味着改变原来的列表,从而让其中的元素能按一定的顺序排列#,而不是简单地返回一个已排序副本。
>>> b = [5,9,1,4,8,2,3,6]
>>> b.sort()
>>> b
[1, 2, 3, 4, 5, 6, 8, 9]
#当用户需要一个排序好的副本,而又要保留原来列表不变的时候通常会想打下面的做法(错误的做法):
>>> c = b.sort()
>>> print(c)
None
#因为sort方法修改了b却返回了空值,正确的做法:
>>> c = b[:]
>>> c
[1, 2, 3, 3, 4, 5, 6, 8, 9]
>>> c.sort()
>>> c
[1, 2, 3, 3, 4, 5, 6, 8, 9]
>>> 
#[:]这是一种很有效率的复制整个列表的方法,简单地把b赋值给c是没有用的,这样做就是让b和c都指向同一个列表了。

#另一种获取已排序列表的副本的方法是sorted函数
>>> e = [4,7,2,5]
>>> f = sorted(e)
>>> f
[2, 4, 5, 7]
>>> e
[4, 7, 2, 5]
#这个函数实际上可以用于任何序列(用于任何可迭代的对象),却总是返回一个列表:
>>> sorted('Python')
['P', 'h', 'n', 'o', 't', 'y']
>>> 

#高级排序
#若需要函数按照特定的方式进行排序,那么可以通过compare(x,y)的形式自定义比较函数。内建函数cmp提供了比较函数的默认实现方式:
>>> cmp(1,2)
-1
>>> numbers = [2,5,1,8,3,5,0]
>>> numbers.sort(cmp)
>>> numbers
[0, 1, 2, 3, 5, 5, 8]
>>> 
#sort方法还有另外两个可选的参数-key和reverse。若要使用它们,就要通过名字(关键字参数--后面会说到)来指定。
>>> s = ['str','nostr','third','fourth','six','abandon']
>>> s.sort(key=len)
>>> s
['str', 'six', 'nostr', 'third', 'fourth', 'abandon']
>>> 
#另一个关键字参数reverse是简单的布尔值,用来指明是否要反向排序:
>>> s.sort(reverse=False)
>>> s
['abandon', 'fourth', 'nostr', 'six', 'str', 'third']
>>> s.sort(reverse=True)
>>> s
['third', 'str', 'six', 'nostr', 'fourth', 'abandon']
>>> 

元组:不可变序列

元组与列表一样也是序列,唯一不同的就是元组不能修改。(PS:元组与列表在技术实现上有点不同,但在实际使用时可能不会注意到,而且元组没有像列表一样的方法)

元组大部分时候是通过圆括号()括起来的

>>> 1,23,3
(1, 23, 3)
>>> 34, #实现包括一个值的元组
(34,)

#以下两个例子生成了一个长度为1的元组,第一个例子根本不是元组。(逗号是很重要的)
>>> 2*(20+3)
46
>>> 2*(20+3,)
(23, 23)
>>> 
#注意24和(24)是一样的,但加了逗号就不同了

tuple函数

#tuple函数的功能与list函数基本上是一样的:以一个序列作为参数并把它转换为元组,若参数就是元组,
#那么该参数就会被原样返回
>>> tuple('python')
('p', 'y', 't', 'h', 'o', 'n')
>>> tuple([1,2,3])
(1, 2, 3)
>>> tuple((1,2,3))
(1, 2, 3)
>>> x = (1,2,3,4,5)
>>> x[0:3] #元组的分片还是元组
(1, 2, 3)

那么元组究竟有什么作用呢?

  • 元组可以在映射中当作键使用,而列表则不幸
  • 元组作为很多内建函数和方法的返回值存在,也就是说你必须对元组进行处理。只要不尝试修改元组,那么“处理” 元组在绝大多数情况下就是把他们当作列表来进行操作。

### 小结

序列

序列是一种数据结构。它包含的元素都进行了编号,典型的序列包括列表、字符串和元组。其中,列表是可变的 ,而元组和字符串是不可变的(一旦创建就固定了的)。通过分片可以访问序列的一部分,分片操作需要两个 索引号来指出分片的起始和终止位置。

成员资格

in操作符可以检查一个值是否在序列中。对字符串使用in操作符是一个特例–它可以查找字符串。

方法

一些内建类型有很多有用的方法。方法是面像对象编程的一个重要概念。

第二部分的学习也就到此结束了,还有问题请在下方留言。谢谢你们的支持!

Fork me on GitHub