第十七周-day72-Python编程基础day04_索引到列表li=[(1,‘a’),(2,‘b’),(3,‘c

将一个对象(元素)插入到列表的指定索引的前面。这只是一个插入操作,并且是原地操作列表,所以该方法没有返回值。

l = ['a', 'b', 'c', 'd']
l.insert(1, 1)
print(l)  # ['a', 1, 'b', 'c', 'd']

可以看到,我们通过insert操作在列表索引为1的元素前面插入一个新元素1
需要注意的是,就如插队一样,前面插入一个人,后面的人都要往后移动一位,如果列表长度很长的话,会对性能有所影响。

In [2]: %timeit list(range(100000)).append('a')
3.25 ms ± 22.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [3]: %timeit list(range(100000)).insert(0, 'a')
3.36 ms ± 99.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

上例,我们通过ipython测试同样是十万个元素的列表,一个执行将元素追加到列表的尾部,一个执行将元素插入到列表的头部,可以看到,追加操作需要耗费3.25ms,而插入操作需要3.36ms

2.3 list.pop([obj])

移除列表中的指定索引位置的元素,若不指定索引,默认移除列表尾部的元素,并且将列表返回(返不返回是我的事儿,接不接收是你的事儿)。

l = ['a', 'b', 'c', 'd']
print(l.pop(1))  # b
print(l.pop())  # d
print(l.pop(9))  # IndexError: pop index out of range
print(l.pop('d'))  # TypeError: 'str' object cannot be interpreted as an integer

前三个打印好解释,最后一个打告诉我们字符串无法解释为整型,也就是说,list.pop(obj)移除操作要么是指定元素下标,要么什么都不指定,按照人家默认的来,而不能指定删除某个元素。

2.4 list.remove(obj)

删除列表中的指定元素,不指定或指定元素不存在报错,而且仅是删除操作,没有返回值。

l = ['a', 'b', 'c', 'd']

l.remove('a')
l.remove('c')
print(l)  # ['b', 'd']
l.remove(1)  # ValueError: list.remove(x): x not in list

最后报错说删除的指定元素不存在。

2.5 list.reverse()

反转列表,并没有参数和返回值,只是在原地对列表中的元素进行反转。

l = ['a', 'b', 'c', 'd']
l.reverse()
print(l)  # ['d', 'c', 'b', 'a']

2.6 list.sort(key=None, reverse=False)

原地对列表进行排序,key是自定义的排序算法,此函数在每次元素比较时被调用,reverse表示排序方式,默认的false是按照升序进行排序的,当reverse=True时,排序结果为降序。

l = ['a', 'c', 'b', 'd']
l.sort()
print(l)  # ['a', 'b', 'c', 'd']
l.sort(reverse=True)
print(l)  # ['d', 'c', 'b', 'a']

我们来看看key参数怎么使用:

l = ['abc', 'cae', 'edg', 'ffh']
l.sort(key=lambda x: x[1])
print(l)  # ['cae', 'abc', 'edg', 'ffh']

通过key指定以每个元素中的索引为1的元素排序。
需要补充的是sorted(key=None, reverse=False)函数,它是Python内置的对于所有序列类型进行排序的函数,而不像sort()方法是列表独有的排序方法。
二者区别是:

  • sort方法仅能对列表进行原地排序,没有返回值。
  • sorted函数对所有序列类型进行排序,并且并不是原地排序,它会返回排序结果,也就是说我们可以通过一个变量接收排序结果。

需要注意的是,无论使用哪种排序方式,排序对象必须是同类型的,也就是说,如果排序对象是列表,那么列表内的元素都为同一类型,因为不同类型无法比较。

转换为字符串


3. 列表的嵌套

如果嵌套层数过多,可以使用递归的方法,扩展项

前文介绍列表时说的元素类型丰富,就是说列表不仅能存储数字、字符串,还能存储列表。

>>> l = [1, 2, [3, 4]]    
>>> for i in l:    
...     print(i)    
...    
1    
2    
[3, 4]    
>>> l[2]    
[3, 4]    
>>> l[2].pop()    
4    
>>> l    
[1, 2, [3]]    
>>> l[2].insert(0,'a')    
>>> l    
[1, 2, ['a', 3]]    

可以看到,列表对嵌套部分处理也同样的简单,可以使用我们学过的方法, 不仅如此,列表还可以存储别的数据结构,如字典、元组、集合。

>>> l = [1,(2, 3), [4,[5, 6]], {'a':'b'}, {7, 8}]    
>>> for i in l:    
...     print(i)    
...    
1    
(2, 3)    
[4, [5, 6]]    
{'a': 'b'}    
{8, 7}    
>>> l[1][1]    
3    
>>> l[2][1][1] = 'c'    
>>> l[3]['a']    
'b'    
>>> l[-1]    
{8, 7}    
>>> l    
[1, (2, 3), [4, [5, 'c']], {'a': 'b'}, {8, 7}]    

先不管元组、字典、集合的是什么。但并不推荐这么用,因为这样操作起来太不方便,只是演示列表可以各种嵌套,一般使用中,更多的是嵌套一种数据类型,如列表嵌套元组,列表嵌套字典,但很少有同时嵌套元组和字典的。
那么,我们如何展示列表中的所有元素呢?这里我们可以使用嵌套循环完成。

>>> for i in [1, [2, 3], 4]:  
...     if isinstance(i, list):  
...         for j in i:  
...             print(j)  
...     else:  
...         print(i)  
...  
1  
2  
3  
4  

上例中,第1行for循环列表,第2行判断每次循环中的元素是否为列表,如果是列表,那么就再用for循环循环打印其内的列表中的元素。否则执行第5行的else语句直接打印列表内的元素。

需要强调的是,Python中并没有二维数组的概念,但是列表嵌套列表同样能够达到相同的目的


4.元组tuple

资料链接:https://www.cnblogs.com/Neeo/articles/11212374.html

Python的元组与列表类似,不同之处在于元组的元素不能修改

元组使用小括号,列表使用方括号

元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

创建空元组

tup1 = ()

元组中只包含一个元素时,需要在元素后面添加逗号

tup1 = (50,)

元组与字符串类似,下标索引从0开始,可以进行截取,组合等。

4.1 元组的基本操作

创建元组

Python中,元组(tuple)用一对小括号()表示,元组内的各元素以逗号分隔。

t = ()
print(type(t))  # <type 'tuple'>
t1 = ('name', )
print(t1)  # ('name',)
print(type(t1))  # <type 'tuple'>

元组中特别注意逗号的使用,一不小心创建的元组就会成为字符串。

t = ('name')
print(t, type(t))  # ('name', <type 'str'>)
t1 = ('name', )
print(t1, type(t1))  # (('name',), <type 'tuple'>)

索引和切片

元组中索引和切片的用法跟列表和字符串类似,或者取范围内的值,或者可以指定在一段范围内,每几个取一个:

t = ('a', 'b', 'c', 'd', 'e')
# 按照索引取值
print(t[1])  # b
print(t[-1]) # e

# 取两者之间(范围)的值
print(t[0:4])  # ('a', 'b', 'c', 'd')
print(t[0:5:2])  # ('a', 'c', 'e')

# 反转元组,返回反转后的新的元组,原本的元组不变
print(t[::-1])  # ('e', 'd', 'c', 'b', 'a')

# for循环取值
for i in t:
    print(i)
'''
a
b
c
d
e
'''

但与列表不同的是,元组身为不可变类型,无法原地修改其中的值。

t = ('a', 'b', 'c', 'd', 'e')
t[2] = 'w'

'''
TypeError: 'tuple' object does not support item assignment
'''

拼接: +

虽然元组无法原地修改其中的元素,但是,通过+号可以把两个元组合并为一个新的元组。

t1 = ('a', 'b')
t2 = ('c', 'd', 'e')
t3 = t1 + t2
print(t3)  # ('a', 'b', 'c', 'd', 'e')

元组的重复:*

简单来说,正如字符串的重复一样,当对元组使用*时,复制指定次数后合并为一个新的元组。

t1 = ('a', 'b')
t2 = t1 \* 2
print(t2)  # ('a', 'b', 'a', 'b')

成员资格测试: in,not in
与字符串、列表的成员资格测试在元组中同样适用:

t1 = ('a', 'b', 'abc')
print('a' in t1)  # True
print('b' not in t1)  # False

需要注意的是,成员资格判断,只是会判断某个元素是否存是元组的一级元素,比如上例中的a是元组的一级元素。而c不是元组的一级元素。在元组中,c是元组一级元素字符串abc的子串。所以判断结果为False。

序列(元组)类型的打包与解包

t = 1, 2, 3
x, y, z = t
print(x, y, z)  # 1 2 3

上例第1行,将1、2、3打包赋值给变量t,相当于将3个苹果打包到一个盒子内。第2行,从盒子t中将3个苹果取出来,分别交给x、y、z,我们称为解包。解包这里需要注意的是,盒子里有几个苹果,必须有几个对应的变量接收。多了不行,少了也不行。

平行赋值

>>> x, y = 1, 2  
>>> x,y  
(1, 2)  
>>> x  
1  
>>> type(x)  
<class 'int'>  
>>> a = x,y  
>>> a  
(1, 2)  
>>> type(a)  
<class 'tuple'>  

如上例第1行所示,平行赋值就是等号右边的1,2分别赋值给等号左边的x,y。第2行就是打包了(只是打包,并没有赋值给某个变量),并且打包后的结果是元组类型。而在第8行将x,y打包并赋值给变量a。此时a就是打包后的元组了。

通过打印斐波那契序列来练习平行赋值:

x, y = 0, 1
while x < 8:
    x, y = y, x + y
    print(x)
'''
1
1
2
3
5
8
'''

首先定义x,y两个变量并赋值。在每次循环中,x和y值都会重新赋值。

删除元组

注意,这里说的删除仅是删除整个元组,而不是删除元组中某个元素。

>>> t = (1, 2, 3)  
>>> del t[1]  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
TypeError: 'tuple' object doesn't support item deletion  
>>> del t  
>>> t  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
NameError: name 't' is not defined  

上例第2行,通过删除元组内的元素导致报错,又一次的证明元组为不可变类型。但我们可以删除整个元组(第6行)。

4.1.1 总结,元组中常用的操作符:
操作符(表达式)描述重要程度
+合并**
*重复**
in成员资格****
for i in (1, 2, 3):print(i)迭代*****
t[2]索引取值*****
t[start:stop:step]切片(截取)*****

另外,还有几个内置的函数可以应用于元组:

方法描述重要程度
max(tuple)返回元组内最大的元素**
min(tuple)返回元组内最小的元素**
tuple(seq)将序列转换为元组*****
len(tuple)返回元组长度*****
4.2 元组的嵌套

与列表一样,元组也能嵌套存储数据:

t = (1, (2, 3), [4, [5, 'c']], {'a': 'b'}, {8, 7})
for item in t:
    print(item)
'''
1
(2, 3)
[4, [5, 'c']]
{'a': 'b'}
{8, 7}
'''

元组内可以存储的数据类型相当丰富,也可以发现,嵌套元素也会当成一个整体称为元组的子元素。但是我们说元组是不可更改的,但我们发现其中是由列表的,这是怎么回事?

t = (1, (2, 3), [4, [5, 'c']], {'a': 'b'}, {8, 7})
t[0] = 'x'  # TypeError: 'tuple' object does not support item assignment

通过上例,可以发现,元组内的普通元素不允许修改,但是列表是可变,我们能否把列表替换为别的元素呢?

t = (1, (2, 3), [4, [5, 'c']], {'a': 'b'}, {8, 7})
print(t[2])  # [4, [5, 'c']]
t[2] = 'w'  # TypeError: 'tuple' object does not support item assignment

通过上例也可以发现,如果列表被当成了元组的普通元素,那么它也是不可以修改的,遵循元组不可变特性。但是我们如果试图修改列表中的子元素呢?

t = (1, (2, 3), [4, [5, 'c']], {'a': 'b'}, {8, 7})
t[2][0] = 'w'
print(t)  # (1, (2, 3), ['w', [5, 'c']], {'a': 'b'}, {8, 7})

上例,可以发现,t[2][0]指的是列表中的第一个元素,我们在第2行修改它,然后发现是可以修改成功的。这是为什么呢?元组内的普通元素不允许修改,嵌套的子元素是否能够修改取决于这个子元素本身属于什么数据类型,如这个子元素是列表,那就可以修改,如果是元组,就可不以修改。

那么,了解完元组,你可能更有疑问了,除了不可变之外,元组跟列表没啥区别么?我们通过与列表的对比,来证明存在即是真理!

需要注意的是,元组并没有增、删功能。那么元组如此设计,以放弃增、删为代价换来了什么呢?

性能!是的,换来了性能!不信请看,以下演示代码由IPython(Python的另一个发行版本)完成。

4.3 list列表与元组tuple的对比
4.3.1 list VS tuple:创建(生成)速度

我们通过创建同样大小的list和tuple,来观察有什么变化:

In [1]: % timeit [1, 2, 3, 4, 5]
139 ns ± 2.34 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: % timeit (1, 2, 3, 4, 5)
17.3 ns ± 0.161 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

上例的意思是说我们创建一个长度为5的列表,大概执行了7次大循环,每次大循环中进行10000000次小循环。这个7次大循环,每次耗时(平均值)139 ns,每次(标准)偏差2.34 ns。而创建同样长度的元组,每次仅耗时17.3 ns,对比创建列表的耗时139 ns,可以看到创建元组的速度快很多。

4.3.2 list VS tuple:存储开销

再来看他们的存储开销:

from sys import getsizeof
l = [1, 2, 3, 4, 5]
t = (1, 2, 3, 4, 5)
print(getsizeof(l))  # 56
print(getsizeof(t))  # 48

可以看到,元组在存储空间上面也占优势。

4.3.3 list VS tuple:遍历速度

元组的遍历性能相比列表也是快很多了

image.png

4.3.4 list VS tuple:哈希比较
l = [1, 2, 3, 4, 5]
t = (1, 2, 3, 4, 5)
print(hash(t))  # -1883319094
print(hash(l))  # TypeError: unhashable type: 'list'

简单来说,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

Python中可哈希(hashable)类型:字符串、元组、对象。可哈希类型就是我们常说的不可变类型,优点是性能经过优化,多线程安全,不需要锁,不担心被恶意篡改或者不小心修改了。

不可哈希类型:字典、列表、集合。相对于可哈希类型,使用起来相对灵活。

4.4 为数组添加元组


5. 字典dict

资料链接:https://www.cnblogs.com/Neeo/articles/11212385.html

我们知道,无论字符串、列表、元组都是将数据组织到一个有序的结构中,然后通过下标索引处理数据,这几种数据结构虽然已经满足大多数场景了,但是依然不够丰满,现在了解一种通过名字(key)来处理数据的数据类型,这种名字对应数值的关系我们称之为映射关系,而这种数据类型就是前文或多或少的了解过的——字典(dict)。字典是目前为止,Python唯一的内建的映射类型的数据类型。需要说明的是,从Python 3.6开始,字典元素的存储顺序由各键值对根据存储时的顺序而定(但依然不支持索引取值),并优化了空间上的开销,更节省内存占用。

通过存储同样的数据,利用列表和字典的不同之处来学习字典。比如存储商品的名称和编号,可以用列表来存。

有三个商品,对应三个价钱,那想要知道banana的价钱怎么办?

goods = ['apple', 'orange', 'banana']
price = ['20', '24', '32']
banana = price[goods.index('banana')]
print(banana)  # 32

如上例这样取值很麻烦,而且,你可能要问为什么价钱要存成字符串类型?

goods = ['apple', 'orange', 'banana']
price = [20, 24, 32]
banana = price[goods.index('banana')]
print(banana)  # 32

上例虽然可以存储为int类型。但要是存个电话号码呢?比如存010998998这样的数字怎么存?

number = [010, 998, 998]  # SyntaxError: invalid token

这个问题告诉我们,碰到类似的数据,或者是0开头的数据,尽量存储为字符串类型,而不是整型。另外,虽然列表能存储多种数据类型,但是通过上面的商品和价钱的例子,在用列表的时候,应该尽量存储数据为单一的类型。
好,言归正传,再来看看更好的选择。

goods = {'apple': '20', 'orange': '24', 'banana': '32'}
print(goods['banana'])  # 20

上例采用了字典来存储数据,接下来就学习一下字典的用法。

5.1 字典基本操作

字典详细讲解:https://www.cnblogs.com/Neeo/articles/11212385.html

字典是无序(Python 3.6版本之前)的可变类型数据类型。我们通过一对{}来创建字典(dict),字典内的值是通过:来存储的,也就是key:value的格式。

d1 = {}
d2 = dict()
print(d1, d2)  # {} {}
d3 = {'apple': 20}
print(d3)  # {'apple': 20}
print(d3['apple'])  # 20

5.1.1 使用内建函数dict()来创建字典
d = dict(apple='20', orange='24')
print(d)  # {'apple': '20', 'orange': '24'}

5.1.2 字典的增删改查
d = dict(apple=20, orange=24)
print(d['apple'])  # 字典取值
d['apple'] = 40  # 为字典的apple键重新赋值
print(d)
d['banana'] = 32  # 为字典新添加一对键值对
print(d)
del d['apple']
del d['orange'], d['banana']
del d

我们可以通过字典加中括号的形式,来对字典进行增删改查的操作。但需要注意的是,通过中括号取值的时候和del声明删除字典的key时,该key必须存在,否则报错(KeyError)。

列表的成员资格测试是不稳定的,而字典稳定。这是因为列表的成员资格判断取决于判断元素处于列表的什么位置,如果是列表的靠前位置,速度肯定快,如果是末尾,就要从头到尾挨着判断,速度就慢下来了。
而字典的存储结构是由key哈希表value三部分组成的,字典在创建一个键值对的时候,首先将key通过哈希得到结果,结果的位置上就是value,然后这个对应关系被保存在哈希表上。查询的时候,无论该key在何方,只要哈希后根据结果去哈希表上就能找到对应的value。所以查询速度快而且稳定,但由于要维护哈希表,在存储和修改时可能会相对麻烦些。

不是什么元组都能成为字典的key
需要注意的是,如果字典的key是元组,那么这个元组就不能是普通的元组了。我们知道元组是可哈希的数据类型,这种说法是基于元组内的元素都是不可变类型才成立的。

print(hash((1, 'a', 2.3, (4, 5))))  # -1680772126
t1 = (1, 'a', 2.3, (4, 5), [6, 7])
print(t1)  # (1, 'a', 2.3, (4, 5), [6, 7])
print(hash(t1))  # TypeError: unhashable type: 'list'

5.2 字典的常用操作
遍历字典
d = {'a': 1, 'b': 2, 'c': 3}
for k in d:
    print(k)
'''
a
b
c
'''

由上例可以看到,遍历的时候,字典默认返回key,那么怎么分别取key和value呢?

d = {'a': 1, 'b': 2, 'c': 3}
print(d.keys())  # dict\_keys(['a', 'b', 'c'])
for k in d.keys():
    print(k)
'''
a
b
c
'''
print(d.values())  # dict\_values([1, 2, 3])
for k in d.values():
    print(k)
'''
1
2
3


### 最后

Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

#### 👉Python所有方向的学习路线👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

![](https://img-blog.csdnimg.cn/img_convert/604bae65027d4d67fb62410deb210454.png)

#### 👉Python必备开发工具👈

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

![](https://img-blog.csdnimg.cn/img_convert/fa276175617e0048f79437bd30465479.png)



#### 👉Python全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

![](https://img-blog.csdnimg.cn/img_convert/16ac689cb023166b2ffa9c677ac40fc0.png)



#### 👉实战案例👈



学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。



因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。

![](https://img-blog.csdnimg.cn/img_convert/0d8c31c50236a205928a1d8ae8a0b883.png)



#### 👉大厂面试真题👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

![](https://img-blog.csdnimg.cn/img_convert/99461e47e58e503d2bc1dc6f4668534a.png)

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值