【python】Tuples元组

  • Post author:
  • Post category:python




基本介绍

元组是值的序列。 这些值可以是任何类型,并且它们由整数进行索引,因此在这方面元组非常类似于列表。 重要的区别在于元组是不可变的(immutable)。

在语法上,tuple 是一个以逗号分隔的值列表,虽然没有必要,但常常将元组括在括号内。

t = 'a', 'b', 'c'
type(t)
#tuple
t = ('a', 'b', 'c')
type(t)
#tuple

要用创建一个 只有一个元素的元组,必须包含一个最后的逗号:

t = 'a',
type(t)
#tuple

括号中的只有一个元素不是元组:

t = ('a')
type(t)
#str
t = ('a',)
type(t)
#tuple

创造一个空的元组:

t =tuple()
t
#()

如果参数是一个序列(字符串、列表或元组) ,结果是一个包含所有其中元素的元组:

t =tuple('mathilda')
t
#('m', 'a', 't', 'h', 'i', 'l', 'd', 'a')

大多数列表操作符也用于元组:

t =tuple('mathilda')
t[0]
#'m'
t[1:3]
#('a', 't')

但是如果试图修改元组的一个元素,会报错:

t[0] = 'A'
#TypeError: 'tuple' object does not support item assignment

因为元组是不可变的,所以不能修改元素。 但是可以用另一个元组替换一个元组(注意第一个要是元组不能是‘M’),语句生成一个新元组,然后命名为t。

t = ('M',) + t[1:]
t
#('M', 'a', 't', 'h', 'i', 'l', 'd', 'a')

关系运算符处理元组和其他序列:Python 从比较每个序列的第一个元素开始。 如果它们相等,则继续到下一个元素,依此类推,直到找到不同的元素。 不考虑后续元素(即使它们非常大)。

(1, 2, 3) < (1, 1, 100)
#false



元组的交换赋值

一般我们要交换两个变量的值,我们会这么写:

temp = a
a = b
b = temp

元组的交换则会更为简略:

a, b = b, a

左边是一个变量元组,右边是一个表达式元组,每个值都分配给其各自的变量,右边的所有表达式都在任何赋值之前进行计算。左边和右边的元素个数必须相同。

右边可以是任何类型的序列(字符串、列表或元组)。 例如,将一个电子邮件地址分割成一个用户名和一个域名,可以这样写:

email = "yrc.mathilda@gmail.com"
uname, doname = email.split("@")
#uname:'yrc.mathilda' doname:gmail.com



返回元组

严格地说,一个函数只能返回一个值,但是如果该值是一个元组,那么可以返回多个值。 例如,如果希望除以两个整数并计算商和余数,那么计算x//y和x%y是低效的,可以同时计算它们。

内置函数divmod接受两个参数并返回两个值(商和余数)组成的元组。 可以将结果存储为一个元组,也可以用元组的赋值分别储存结果:

t = divmod(10, 4)
t
#(2, 2)
a, b = divmod(10, 4)
#a = 2, b = 2

这是一个函数返回元组的例子:

def first_last(l):
    return l[0], l[-1]
first_last([1, 2, 3])
#(1, 3)



参数*

函数可以接受可变数量的参数。以为*开头的参数名称将参数收集到元组中。 比如说,

def first_last(*l):
    print(type(l))
    return l[0], l[-1]
first_last(1, 2, 3)
#<class 'tuple'>
#(1, 3)

*参数可以是任何名称,但是常规用args。

如果是一个元组,也可以用 * 来把它打散

t = (10, 4)
divmod(t)
#TypeError: divmod expected 2 arguments, got 1
divmod(*t)
#(2, 2)

许多内置函数比如max,min就是接受这种参数(Variable-length argument tuples)所以可以接收无数个参数

max(1, 2, 3, 4, 5, 6, 7, ...)

但是sum不可以

sum(1, 2, 3)
#TypeError: sum expected at most 2 arguments, got 3



参数**

*不能在像字典一样的对象中使用

def printall(*args):
    print(args)
printall(1, 2, 3)
#(1, 2, 3)
printall(1, 2, third = 3)
#TypeError: printall() got an unexpected keyword argument 'third'

为了获得字典一样的参数可以用**来获取

def printall(*args, **kwargs):
    print(args, kwargs)
printall(1, 2, 3)
#(1, 2, 3) {}
printall(1, 2, third = 3)
#(1, 2) {'third': 3}

题外话:a和d是等价的

d = dict(x=1, y=2)
a = {'x':1, 'y':2}
a == d
#True

更多的例子

print(1, 2, 3)
#等价于
print(*[1, 2, 3])
#为1 2 3, print([1, 2, 3])为[1, 2, 3]

def f(*args, **kwargs):
	print("ARGS", args)
	print("KWARGS", kwargs)
f(1, 2, x = 3, y = 4, z = 5)
#ARGS (1, 2)
#KWARGS {'x': 3, 'y': 4, 'z': 5}



list和tuple

zip是一个内置函数,它需要两个或多个序列,并将它们并在一起。

a = "abc"
b = (1, 2, 3)
zip(a, b)
#<zip at 0x7fe091401f08>

这样的结果是zip对象,但这个对象可以进行遍历,所以zip最常见的用途就是用在循环中

a = "abc"
b = (1, 2, 3)
for pair in zip(a, b):
    print(pair)
#('a', 1)
#('b', 2)
#('c', 3)

zip对象是一种迭代器,在某些方面与列表相似,但与列表不同的是,不能使用索引从迭代器中选择元素。

如果想使用列表操作符和方法,可以这样:

list(zip(a, b))
#[('a', 1), ('b', 2), ('c', 3)]
type(list(zip(a, b))[0])
#tuple

结果是一个元组列表。

如果序列的长度不相同,则结果是选取较短序列的长度。

list(zip('avbc', 'sdf'))
#[('a', 's'), ('v', 'd'), ('b', 'f')]

还可以这样

a = "abc"
b = (1, 2, 3)
for ch, num in zip(a, b):
    print(ch, num)
#a 1
#b 2
#c 3

如果需要遍历序列的元素及其索引,可以使用内置函数enumerate:

其结果是枚举对象,它迭代一系列对,每个对包含一个索引(从0开始)和一个来自给定序列的元素。

for index, ch in enumerate('abc'):
    print(index, ch)
#0 a
#1 b
#2 c



字典和tuple

字典有一个名为items的方法,它返回一个元组序列,其中每个元组是一个键值对。items的对象可以用于循环,在字典里的元素没有特定顺序。

d = {'a':1, 'b':3, 'c':10}
d.items()
#dict_items([('a', 1), ('b', 3), ('c', 10)])
for key, val in d.items():
    print(key, val)
#a 1
#b 3
#c 10

反过来,可以使用元组列表来初始化一个新的字典:

t = [('a', 1),('b', 3),('c', 10)]
dict(t)
#{'a': 1, 'b': 3, 'c': 10}

可以结合dict和zip非常简洁的创造字典:

dict(zip('abc', [1,2, 3]))
#{'a': 1, 'b': 2, 'c': 3}

字典中的update方法同样可以接收由tuple组成的list,并且添加到字典中。

在字典中使用tuple作为key是很普遍的,因为不能使用list

可以写:

d[a, b] = c
for a, b in d:
	print(a, b, d[a, b])

这样在循环中的ab只会取值d的key赋值给ab



版权声明:本文为mathilda33原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。