python必知必会1
新篇章系列开启,围绕两个部分,一是python编程基础与特性,二是数据结构与算法。
Q:列表和元组之间的区别是什么?
元组可以看作是一个不可变的列表。
- 列表是可变的,长度大小不固定,可以进行增删改等一系列操作。而元组是不可变的。大小固定,不可以进行增删改操作。
- 因为元组的不可变性,所以元组无法复制。
- 可以使用元组作为字典的键,但是列表不可以。
- 在两者的性能方面,Python 会将低开销的较大的块分配给元组,因为它们是不可变的。 对于列表则分配小内存块。 与列表相比,元组所支持的操作更少所以会更快一些。
- 存储相同的元素时,列表的大小比元组要大。这是因为列表是动态的,它需要存储指针来指向对应的元素。
Q:为什么有了列表,还需要有元组?
列表占用的空间更大,性能低但是存储内容可变,元组占用空间更小,性能更高,但是存储内容不可变。两种数据结构的应用场景也不一样,所以才会有了两种不同的数据结构。
扩展:序列(sequence)和容器(container)
-
序列(sequence)是一种数据结构,每个元素都分配了一个索引 ,从 0 开始,典型的序列就有列表,元组和字符串。其中列表可变,元组和字符串不可变。
-
容器(container)包含其他对象的任何对象。
序列和映射(mapping)是两种主要的容器。映射中的每个元素都分配了一个键,而字典是 python 中唯一内建的映射内型。键可以是数字,字符串或元组。
Q: 什么是元组拆包?
拆包会把一个可迭代对象中的元素一并赋值到对应变量中去。这样做可以让我们把注意力集中在我们所需要关注的元素上面。
>>> tuple = ('beijing','2019','8.7')
>>> city,year,date = tuple
>>> city
'beijing'
>>> year
'2019'
>>> date
'8.7'
元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象中的元素数量必须要跟接受这些元素的元组的空档数一致。
拆包时我们还可以用 * 来处理剩下的元素,在 python 里常用这种方法来代表不确定数量参数!
使用占位符 _ 去忽略不需要关注的元素,相当于一个占位符,抵消掉了我们不需要关注的元素。
可以同时使用 * 和占位符 _
a, b, *rest = range(5)
print(a) # 0
print(b) # 1
print(rest) # [2,3,4]
a, b, *rest = range(5)
print(a) # 0
print(b) # 1
print(rest) # [2,3,4]
x, _, y = (1, 2, 3)
print(x) # 1
print(y) # 3
x, *_, y = (1, 2, 3, 4, 5)
print(x) # 1
print(y) # 5
Q: *args 和 **kwargs 的用法
当函数的参数不确定时候可以用 *args 和 **kwargs。
*args 是用于接收多余的未命名参数,
**kwargs 用于接收实参中的命名参数,其中 args 是一个元组类型,而 kwargs 是一个字典类型的数据。
形参中的 *args 把传进来的数据放在了 args 这个元组中。把 **kwargs 传进来的数据放在了 kwargs 这个字典中。
*args 其实就是把元组中的数据进行拆包,也就是把元组中的数据拆成单个数据。
def print_everything(*args):
for count, thing in enumerate(args):
print( '{0}. {1}'.format(count, thing))
print_everything('apple', 'banana', 'cabbage')
# print_everything()函数调用结果为:
# 1. apple
# 2. banana
# 3. cabbage
**kwargs 就是把字典中的数据进行拆包,传进的命名数据可以从 kwargs 按键进行索引获得。
def table_things(**kwargs):
for name, value in kwargs.items():
print( '{0} = {1}'.format(name, value))
table_things(apple = 'fruit', cabbage = 'vegetable')
# table_things()函数调用结果为:
# cabbage = vegetable
# apple = fruit
同时使用 *args 和 **kwargs
def func(required_arg, *args, **kwargs):
# required_arg是一个常规参数
print (required_arg)
# args是一个元组
if args:
print (args)
# kwargs是一个字典,里面的键值就是传进来的参数变量名
if kwargs:
print (kwargs)
调用这个函数的结果
>>> func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)
## 直接调用 func() 函数会报错:func()至少需要1个参数(给定0)
>>> func("required argument")
required argument
## 调用 func() 函数的时候给定了一个参数,所以只会打印一个参数。
>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')
## **args 接受了剩余的参数并放到了元组中
>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
## **args接受了无 Key 值的参数并放到元组中,**kwargs 接收了有 key 值的参数并放到了字典中。