这次Python学习参考的是Python基础教程,前面由于有一些Java基础,所以看的还比较顺利,然而到了函数这章就不太顺了,特别是参数这节。
下面对函数做一下简单的讲解。
假设需要编写一个存储联系人姓名并且能用名字、中间名、或姓查找联系人的程序,可以使用下面的数据结构:
storage = {}
storage['first'] = {}
storage['middle'] = {}
storage['last'] = {}
storage是一个有三个键(‘first’,‘middle’,‘last’)的字典,每个键下面又存储一个子字典,子字典中可以使用名字(名字、中间名或姓)作为键,插入联系人姓名的列表作为值,比如将作者的名字Magnus Lie Hetland插入这个数据结构中:
author = 'magnus Lie Hetland'
storage['first']['Magnus'] = [author]
storage['middle']['Lie'] = [author]
storage['last']['Hetland'] = [author]
每个键下面都存储了一个以人名组成的列表,现在如果想得到所用中间名为Lie的人则可进行如下操作:
print storage['middle']['Lie']
结果为: ['magnus Lie Hetland']
其实我看到这里就有点混乱了,这种字典中含字典的不太好理解,所以现在将storage输出看一下它的整体结构:
print storage
结果为(字典的键没有顺序):
{
'middle':
{
'Lie': ['magnus Lie Hetland']
},
'last':
{
'Hetland': ['magnus Lie Hetland']
},
'first':
{
'Magnus': ['magnus Lie Hetland']
}
}
这样起来就清楚多了。
现在再在storage中加入作者姐姐的名字Anne Lie Hetland:
sister = 'Anne Lie Hetland'
storage['first'].setdefault('Anne', []).append(sister)
storage['middle'].setdefault('Lie', []).append(sister)
storage['last'].setdefault('Hetland', []).append(sister)
现在storage的结构为
{
'middle': {
'Lie': ['magnus Lie Hetland', 'Anne Lie Hetland']
},
'last': {
'Hetland': ['magnus Lie Hetland', 'Anne Lie Hetland']
},
'first': {
'Anne': ['Anne Lie Hetland'],
'Magnus': ['magnus Lie Hetland']
}
}
现在storage中姓Hetland的有两个人,名为Anne的有一个人,名为Magnus的有一个人。现在应该清楚这个数据结构的存储方式了吧。
(我要吐槽一下我的进度了,以上内容来自于2017年3月21日,现在是2017年3月22日晚11点50分,估计一会发表完就得23号了吧......)
如果要继续增加联系人的话以上写法就会变得臃肿且笨拙不堪了,这个过程可以用函数来实现:
首先是初始化数据结构的函数:
def init(data):
data['first'] = {}
data['middle'] = {}
data['last'] = {}
调用及结果如下:
storage = {}
init(storage)
{'middle': {}, 'last': {}, 'first': {}} # 结果
在编写存储名字的函数前,先写一个获得名字的函数:
def lookup(data, label, name):
return data[label].get(name)
即返回字典data中键为label的字典中名为name的键对应的值。
现在开始写存储名字的函数:
def store(data, full_name):
names = full_name.split() # 将名字拆分成一个列表
if len(names) == 2: # 如果名字长度为2(只有first和last),插入一个空字符串作为中间名
names.insert(1, '')
labels = 'first', 'middle', 'last' # 将字符串first、middle、last作为元祖存储在labels中,方便一会遍历的时候使用
for label, name in zip(labels, names): # 使用zip函数联合标签和名字,对于每一个(lable,name)对,进行如下处理
people = lookup(data, label, name) # people为键name对应的值
if people: # 如果people不为空,证明已经存在name这个键了,所以直接把名字添加到这个键下即可
people.append(full_name)
else: # 如果people为空,则现在还不存在name这个键,所以以name为键,full_name(想要加入的名字)为值创建一个新的列表
data[label][name] = [full_name]
之前的添加过程就可以表示为:
MyNames = {}
init(MyNames)
store(MyNames, 'magnus Lie Hetland')
store(MyNames, 'Anne Lie Hetland')
print lookup(MyNames, 'middle', 'Lie')
现在到了我认为这章的重点——参数。为止参数和关键字参数就不做介绍了,我主要想讲一下收集参数。
如果想给函数提供任意多的参数可以向如下这样定义函数:
def print_params(*params):
print params
调用及结果如下:
print_params('1')
print_params(1, 2, 3)
# 结果
('1',)
(1, 2, 3)
参数前的星号将所有值放置在同一个元祖中。可以说是将一个值收集起来然后使用。
现有如下函数:
def print_params2(title, *params):
print title
print params
# 调用
print_params2('Params:', 1, 2, 3)
# 结果
Params:
(1, 2, 3)
星号可以理解为收集其余的位置参数,如果不提供任何参数,params就是个空元祖,输出结果为{}。
但它不能处理关键字参数,如:
# 调用print_params2
print_params2('Params:', p1=1)
# 错误为
TypeError: print_params2() got an unexpected keyword argument 'p1'
如果想要处理关键字操作则需要写两个星(“**“):
def print_params3(**params):
print params
调用及结果为:
print_params3(x=1, y=2, z=3)
# 结果
{'y': 2, 'x': 1, 'z': 3}
各种参数也可放在一起混合使用:
# 函数
def print_params4(x, y, z=3, *poster, **params):
print x, y, z
print poster
print params
# 调用
print_params4(1, 2, 3, 4, 5, 6, m=7, n=8)
# 结果
1 2 3
(4, 5, 6)
{'m': 7, 'n': 8}
现在如果想一次性存储多个名字时就可以将store改写为:
def store(data, *full_names):
for full_name in full_names:
names = full_name.split()
if len(names) == 2:
names.insert(1, '')
labels = 'first', 'middle', 'last'
for label, name in zip(labels, names):
people = lookup(data, label, name)
if people:
people.append(full_name)
else:
data[label][name] = [full_name]
函数调用就可以写为store(MyNames,‘magnus Lie Hetland'’,‘Anne Lie Hetland’)结果不变。
(现在是3月23日凌晨1点12分,终于为我的Python坑填上了第一把土,没想到第一篇博就写了这么长时间,不知道我还能坚持多久......总之,加油吧!)