Python 基础回顾(二)

求 1) 1 * 2 * 3 … 120
2) 求上述结果的尾部0 的个数。

a = 2100
b = a % 10
if b== 0:
cnt = cnt + 1
else:
stop
a = a / 10
print cnt

a = ‘2100’
len_a = len(a)
a[len_a -1 ]

List 列表
内置的一种数据类型. list是一种有序的集合,可以随时添加和删除其中的元素。
比如,列出班里所有同学的名字,就可以用一个list表示:

classmates = [‘tom’, ‘jerry’, ‘july’]
classmates
[‘tom’, ‘jerry’, ‘july’]
Classmates[::-1]
变量classmates就是一个list。用len()函数可以获得list元素的个数:
len(classmates)
3
还记得上节课的len(string) 吗?
用索引来访问list中每一个位置的元素,记得索引是从0开始的:
classmates[0]
‘tom’
classmates[1]
‘jerry’
classmates[2]
‘july’
classmates[3]
Traceback (most recent call last):
File “”, line 1, in
IndexError: list index out of range
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(classmates) - 1。(思考一下)
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
classmates[-1]
‘july’
以此类推,可以获取倒数第2个、倒数第3个:
classmates[-2]
‘jerry’
classmates[-3]
‘tom’
classmates[-4]
Traceback (most recent call last):
File “”, line 1, in
IndexError: list index out of range
当然,倒数第4个就越界了。
list是一个可变的有序表,所以,可以往list中追加元素到末尾:
classmates.append(‘adam’)
classmates
[‘tom’, ‘jerry’, ‘july’, ‘adam’]
也可以把元素插入到指定的位置,比如索引号为1的位置:
classmates.insert(1, ‘jack’)
classmates
[‘tom’, ‘jack’, ‘jerry’, ‘july’, ‘adam’]
dir(list)
要删除list末尾的元素,用pop()方法:
classmates.pop()
‘adam’
classmates
[‘tom’, ‘jack’, ‘bob’, ‘tracy’]
要删除指定位置的元素,用pop(i)方法,其中i是索引位置:
classmates.pop(1)
‘jack’
classmates
[‘tom’, ‘jerry’, ‘july’]
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
classmates[1] = ‘sarah’
classmates
[‘tom’, ‘sarah’, ‘july’]
list里面的元素的数据类型也可以不同,比如:
L = [‘Apple’, 123, True, None]
list元素也可以是另一个list,比如:
s = [‘python’, ‘java’, [‘asp’, ‘php’], ‘scheme’]
len(s)
4
s = [‘python’, ‘java’, [‘asp’, [‘php’, ‘lua’]], ‘scheme’]

要注意s只有4个元素,其中s[2]又是一个list,如果拆开写就更容易理解了:

p = [‘asp’, ‘php’]
s = [‘python’, ‘java’, p, ‘scheme’]
要拿到’php’可以写p[1]或者s[2][1],因此s可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
L = [] L = list()
len(L)
0
Tuple 元组
tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
classmates = (‘tom’, ‘jerry’, ‘july’)
dir(tuple)
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
t = (1,2,3)
t
(1,2,3)
如果要定义一个空的tuple,可以写成():
t = ()
t
()
但是,要定义一个只有1个元素的tuple,如果你这么定义:
t = (1)
t
1
type(t)
定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
t = (1,)
t
(1,)
只有1个元素的tuple,也会加一个逗号,,以免你误解成数学计算意义上的括号。
最后来看一个“可变的”tuple:
t = (‘a’, ‘b’, [‘A’, ‘B’])
t[2][0] = ‘X’
t[2][1] = ‘Y’
t
(‘a’, ‘b’, [‘X’, ‘Y’])
这个tuple定义的时候有3个元素,分别是’a’,’b’和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?我们先看看定义的时候tuple包含的3个元素:

当我们把list的元素’A’和’B’修改为’X’和’Y’后,tuple变为:

表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
小结
list和tuple是Python内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。

Dict 字典
dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list:
names = [‘tom’, ‘jerry’, ‘july’]
scores = [85, 70, 80]
给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。
如果用dict实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用Python写一个dict如下:

d = {‘tom’: 85, ‘jerry’: 70, ‘july’: 80}
d[‘tom’]
85
d = {‘tom’:[90, 80, 70], }
d = {‘tom’: {‘yuwen’:90, 'shuxue':80,}}
为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字,无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢很多。
给定一个名字,比如’tom’,dict在内部就可以直接计算出tom对应的存放成绩的“页码”,也就是85这个数字存放的内存地址,直接取出来,所以速度非常快。
你可以猜到,这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:
d[‘adam’] = 67
d[‘adam’]
67
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:
d[‘jack’] = 90
d[‘jack’]
90
d[‘jack’] = 88
d[‘jack’]
88
如果key不存在,dict就会报错:
d[‘Test’]
Traceback (most recent call last):
File “”, line 1, in
KeyError: ‘Test’
要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:
‘Test’ in d
False
if ‘Test’ in d:
print d[‘Test’]
二是通过dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value:
d.get(‘jacks’)
d.get(‘jacks’, -1)
-1
注意:返回None的时候Python的交互式命令行不显示结果。
要删除一个key,用pop(key)方法,对应的value也会从dict中删除:
d.pop(‘tom’)
85
d
{‘jerry’: 70, ‘july’: 80}

dict([1,2,3])
请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
1. 查找和插入的速度极快,不会随着key的增加而增加;
2. 需要占用大量的内存,内存浪费多。
而list相反:
1. 查找和插入的时间随着元素的增加而增加;
2. 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。(思考,可变的数据类型有什么?)

练习1. List, tuple, 转为dict类型。 list() dict() tuple()

(1,2,3)
[1,2,3]
{1,2,3}

在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key:
d[123]
key = 123
d[key] d[123]

key = [1, 2, 3]
d[key] = ‘a list’
Traceback (most recent call last):
File “”, line 1, in
TypeError: unhashable type: ‘list’
Set 集合
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
要创建一个set,需要提供一个list作为输入集合:
s = set([1, 2, 3])
s
set([1, 2, 3])
注意,传入的参数[1, 2, 3]是一个list,而显示的set([1, 2, 3])只是告诉你这个set内部有1,2,3这3个元素,显示的[]不表示这是一个list。
重复元素在set中自动被过滤:
s = set([1, 1, 2, 2, 3, 3])
s
set([1, 2, 3])
布隆过滤器
通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
s.add(4)
s
set([1, 2, 3, 4])
s.add(4)
s
set([1, 2, 3, 4])
通过remove(key)方法可以删除元素:
s.remove(4)
s
set([1, 2, 3])
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
s1 & s2
set([2, 3])
s1 | s2
set([1, 2, 3, 4])
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错。
不可变对象!!!
之前我们讲过,str是不变对象,而list是可变对象。
对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:
a = [‘c’, ‘b’, ‘a’]
a.sort() a.sort(reverse=True)
a
[‘a’, ‘b’, ‘c’]
而对于不可变对象,比如str,对str进行操作呢:
a = ‘hello’
a.replace(‘h’, ‘H’)
‘Hello’
a
‘hello’
虽然字符串有个replace()方法,也确实变出了’Abc’,但变量a最后仍是’abc’,应该怎么理解呢?
来看个例子:
a = ‘abc’
b = a.replace(‘a’, ‘A’)
b
‘Abc’
a
‘abc’
要始终牢记的是,a是变量,而’abc’才是字符串对象!有些时候,我们经常说,对象a的内容是’abc’,但其实是指,a本身是一个变量,它指向的对象的内容才是’abc’:

当我们调用a.replace(‘a’, ‘A’)时,实际上调用方法replace是作用在字符串对象’abc’上的,而这个方法虽然名字叫replace,但却没有改变字符串’abc’的内容。相反,replace方法创建了一个新字符串’Abc’并返回,如果我们用变量b指向该新字符串,就容易理解了,变量a仍指向原有的字符串’abc’,但变量b却指向新字符串’Abc’了:

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

使用key-value存储结构的dict在Python中非常有用,选择不可变对象作为key很重要,最常用的key是字符串。
tuple虽然是不变对象,但试试把(1, 2, 3)和(1, [2, 3])放入dict或set中,并解释结果。

列表解析
生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用range(1, 11):[1,11)

range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但如果要生成[1x1, 2x2, 3x3, …, 10x10]怎么做?

方法一是循环:

L = [] list()
for x in range(1, 11):
… L.append(x * x)

L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
来看看列表生成式,可以用一行语句代替循环生成上面的list:
[x * x for x in range(1, 11) ]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
[x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

3*X+1
[1,2,3,4,5,6,7,8,9,10] -> []
还可以使用两层循环,可以生成全排列:

[m + n for m in ‘ABC’ for n in ‘XYZ’]
[‘AX’, ‘AY’, ‘AZ’, ‘BX’, ‘BY’, ‘BZ’, ‘CX’, ‘CY’, ‘CZ’]
三层和三层以上的循环就很少用到了。 可以练习一下试试。
运用列表生成式,可以写出非常简洁的代码。例如,列出当前目录下的所有文件和目录名,可以通过一行代码实现:
import os # 导入os模块,模块的概念后面讲到
[d for d in os.listdir(‘.’)] # os.listdir可以列出文件和目录
[‘.ipython’, ‘.bashrc’, ‘.bash_history’, ‘.profile’, ‘.cache’, ‘testdir’]
for循环其实可以同时使用两个甚至多个变量,比如dict的iteritems()可以同时迭代key和value:
d = {‘x’: ‘A’, ‘y’: ‘B’, ‘z’: ‘C’ }
for k, v in d.iteritems():
… print k, ‘=’, v

y = B
x = A
z = C
因此,列表生成式也可以使用两个变量来生成list:
d = {‘x’: ‘A’, ‘y’: ‘B’, ‘z’: ‘C’ }
[k + ‘=’ + v for k, v in d.iteritems()]
[‘y=B’, ‘x=A’, ‘z=C’]
最后把一个list中所有的字符串变成小写:
L = [‘Hello’, ‘World’]
[s.lower() for s in L]
[‘hello’, ‘world’]
小结
运用列表生成式,可以快速生成list,可以通过一个list推导出另一个list,而代码却十分简洁。
思考:如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,所以列表生成式会报错:
L = [‘Hello’, ‘World’, 18, ‘Test’]
[s.lower() for s in L]
Traceback (most recent call last):
File “”, line 1, in
AttributeError: ‘int’ object has no attribute ‘lower’
使用内建的isinstance函数可以判断一个变量是不是字符串:
x = ‘abc’
y = 123
isinstance(x, str)
True
isinstance(y, str)
False

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值