首页 > 代码库 > *号的妙用

*号的妙用

之前在python基础我们有了解到对变量赋值可以用x = 5或者 x,y = 3,5

问题一:现在有一个包含N个元素的元组或者序列,怎样将它里面的值解压后同时赋值给N个变量?

答:任何的序列(或者是可迭代对象)可以通过一个简单的赋值语句解压并赋值给多个变量。唯一的前提就是变量的数量必须跟元素的数量是一样的

代码示例:

p = (4,5)

x,y= p

print(x,y) ->4,5

data = http://www.mamicode.com/[‘ACME‘,50,91]

x,y,z= data

print(x,y,z) ->ACME 50 91

如果变量个数和序列元素的个数不匹配,会抛出一个异常

代码示例:

data = http://www.mamicode.com/[‘ACME‘,50,91]

x,y= data

结果:ValueError: too many values to unpack (expected 2)

问题二:如果一个可迭代对象的元素个数超过变量个数时,会抛出一个ValueError,那么怎样才能从这个可迭代对象中解压出N个元素处理?

  答:用*号可以解决该问题。比如你在学习一门课程,期末需统计平均成绩,排除掉第一个和最后一个分数,如果只有4个分数,但是如果有24个呢?这时候*号就派上用场了:

代码示例:

record = [10,50,90,100]

first,*middle,last = record

print(middle,sum(middle)/len(middle)) #middle值和平均成绩 -> [50, 90] 70.0

  你可能也能想到也可以用切片的方法对变量赋值,first,middle,last = record[0],record[1:-1],record[-1],但是稍显复杂,下面再看几个例子

如:你现在有一些用户的记录列表,每条记录包含一个名字,邮件,接着就是不确定数量的电话号码。

record = (‘Dave‘,‘dave@example.com‘,‘773-555-1212‘,‘847-555-1212‘)

name,email,*phone_numbers = record

print(name,email,phone_numbers) ->Dave dave@example.com [‘773-555-1212‘, ‘847-555-1212‘]

  注意:phone_numbers变量永远是列表类型,不管解压的电话号码数量是对手(包括0个)。

如:*号表达式也可用于最开始的部分。比如,你有一个公司前8个月销售数据的序列,但是你想看下最近一个月数据和前面7个月的平均值对比。你可以这样做

sales_record = [10,8,7,1,9,5,10,3]

*trailing,current = sales_record

print(round(sum(trailing)/len(trailing),2),current)  #前7个月的平均值,现在的数据->7.14 3

  值得注意的是,星号表达式在迭代元素为可变长元组的序列是很有用的。比如,下面是一个带有标签的元组序列,你要对不同的函数传入不同的参数

首先先知道一个知识点print(*(1,2,3))  #相当于把(1,2,3)解压出来 ->1 2 3

def foo(x,y):
print("x = %s,y = %s"%(x,y))
def bar(value):
print("value is %s"%value)
records = [
(foo,1,2),
(bar,‘hello‘),
(foo,3,4)
]

for func,*args in records:
func(*args)
结果:

x = 1,y = 2
value is hello
x = 3,y = 4

有时候你想解压一些元素后丢弃他们,你不能简单的使用*,但是你可以使用一个普通的废弃名称,比如_或者ign

代码示例:

record = (‘ACME‘,50,123,(12,18,2012))
name,*_,(*_,year) = record
print(name,year)

 

 总结:扩展的迭代解压语法是专门为解压不稳定个数或任意个数的可迭代对象而设计的。通常这些可迭代对象的元素结构有确定的规则(比如第一个元素后面都是电话号码),*号表达式让你可以很容易的利用这些规则来解压元素处理。而不是通过一些复杂的手段去获取这些元素的元素值。

 

*号的妙用