函数、参数1
1、函数的定义方式
def 函数名([参数]):##参数可选
语句体
例:定义一个斐波那契数据的函数
>>> def fibs(num):
result = [0,1]
for i in range(int(num)-2):
result = result.append(result[-2]+result[-1])
return result
2、函数中的return,一般情况下,函数处理完后会返回值给调用的对象,也有的函数是不返回值的这种函数里的return就是用来终止函数的;所有的函数运行到return语句后就会终止
>>> def hello():
print('你好')
return
print('Hello')
>>> hello ###这里hello并不是调用函数hello
<function hello at 0x000002691AD89BF8>
>>> hello() ###调用函数hello(),打印你好,遇到return 函数终止运行,所以第二个打印Hello不执行;
你好
3、没有返回值的函数,实际返回的是None;函数在使用if条件语句时,最好每个条件都有返回值
>>> x = hello()
你好 ###这个不是返回值,返回值是赋值给了x的,你好是函数体内的打印
>>> x
>>> print(x) ###打印返回值,显示None
None
4、参数;大多数情况下我们使用函数都是有参数的,参数就是函数要处理的值;函数(参数)里的参数我们成为形参,我们调用函数时,实际传递的参数称为实参;函数处理时,因为不确定会传入什么参数,所以用形参表示实参,函数对形参进行处理;当我们调用函数时,将实参传递给形参,函数根据我们传入的实参,处理我们的数据;参数存储在局部作用域;
###这个函数fibs的形参是num,接收用户输入的值来生成需要的斐波那契额数据
>>> def fibs(num):
result = [0,1]
for i in range(int(num)-2):
result = result.append(result[-2]+result[-1])
return result
>>> x = fibs(8) ###调用fibs函数,8就是实参就是我们想要处理的数据,实参传递给形参类似给形参赋值;num=8
>>> print(x)
[0, 1, 1, 2, 3, 5, 8, 13]
不可变参数: string、tuple、数字都是不可变的,它们不能被修改,只能替换
>>> def change_to_name(name):
name = 'Mr.Smith'
return name
>>> name = 'Bob Gumby' ###外部元素name
>>> x = change_to_name(name) ####change_to_name(name)函数体内运行逻辑:name = name 内部变量和外部变量name都指向了 'Bob Gumby';name='Mr.Smith' 内部变量name重绑定了 'Mr.Smith' ;这时函数体内变量name是指向的‘Mr.Smith’,所以外部name指向的还是 'Bob Gumby';就是说函数体内部对外部变量进行重绑定(赋值),外部变量的值是不会变的(参数是list也是这样的)
>>> x
'Mr.Smith'
>>> name
'Bob Gumby'
可变参数:list,dict
>>> def change(n):
n[0] = 'Mr.Gumby'
>>> names = ['Mr.Bob','Mr.Morse']
>>> change(names) ###内部运转:n=names 指向同一个列表,n[0]='Mr.Gumby',修改列表内的值,列表也被修改,这时n和names还是指向同一个列表的所以 names输出也是修改后的列表
>>> names
['Mr.Gumby', 'Mr.Morse']
如果想对list类型参数进行修改而不改变原列表,可以用分片赋值法[:]赋值一个副本的list参数,对副本进行处理
>>> def change(n):
n[0]= ['Mr.Gumby']
>>> names = ['Mr.Bob','Mr.Morse']
>>> names_fu = names[:]
>>> change(names_fu)
>>> names_fu
[['Mr.Gumby'], 'Mr.Morse']
>>> names
['Mr.Bob', 'Mr.Morse']
5、可变参数,实例:需要编写一个存储名字并且能用名字、中间名或姓查找联系人的程序
》用名字查找联系人----根据key查找value 数据类型dict{}
》用名、中间名、姓查找联系人 初始化dict里面应该有三个key,考虑到多人情况,每个key再对应{} 里面为名:联系人,中间名:联系人,姓:联系人的方式
》查找模式 dict[first/middle/last][名/中间名/姓]
初始化数据结构 {“first”:{},'middle':{},'last':{}}
>>> def init(data):
data['first']={}
data['middle']={}
data['last']={}
return data
>>> mynames = {}
>>> mynames = init(mynames)
>>> mynames
{'first': {}, 'middle': {}, 'last': {}}
定义存储数据的函数:
>>> def store(data,full_name):
names = full_name.split()
if len(names)==2:
names.insert(1,'')
labels = ['first','middle','last']
for label,name in zip(labels,names):
data[label][name]=[full_name]
return data
>>> full_name = 'liang yang yang'
>>> mynames = store(mynames,full_name)
>>> mynames
{'first': {'liang': ['liang yang yang']}, 'middle': {'yang': ['liang yang yang']}, 'last': {'yang': ['liang yang yang']}}
定义查找函数:
>>> def lookup(data,label,name):
return data[label][name]
>>> print(lookup(mynames,'middle','yang'))
['liang yang yang']
目前看这三个函数组合已经可以使用,但是还不完善,如果名字中(名、中间名、姓)某一项有重复的值呢
>>> def store(data,full_name):
names = full_name.split()###拆分full_names为一个列表,split()默认使用空格拆分
if len(names)==2:
names.insert(1,'') ### 如果名字长度为2,则在中间插入一个空的字符串作为中间名
labels = ['first','middle','last']
for label,name in zip(labels,names): ###zip联合labels和names,每项为(label,name)格式
try:
people = lookup(data,label,name) ###查看一下输入的名字里 data[label][name]
except KeyError as err: ###如果data里不存在data[label][name]会抛出KeyError
print('KeyError:%s'%str(err)) ###打印错误信息
people = None ###data里不存在data[label][name]不存在,则people=None
finally:
if people: ###根据people的值,选择是添加到已有的列表中,还是创建新的项
data[label][name].append(full_name)
else:
data[label][name]=[full_name]
return data
6、不可变参数
函数是不能改变(不可变参数)的,只能从函数返回值,对参数重新处理
>>> def inc(x):
return x+1
>>> foo = 100
>>> inc(foo)
101
>>> foo ###函数并没有改变参数foo
100
>>> foo = inc(foo) ###对foo进行了赋值,改变了foo,并不是inc函数改变了foo
>>> foo
101
###如果想要用函数改变不可变参数,可以用可变参数替换
>>> def inc(x):
x[0]=1
return x
>>> foo = [10]
>>> inc(foo)
[1]
>>> foo
[1]