第5章 函数的设计和使用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5.3 参数类型
在Python中,函数参数有很多种:可以为普通参数、默认
值参数、关键参数、可变长度参数等等。
Python在定义函数时不需要指定形参的类型,完全由调用
者传递的实参类型以及Python解释器的理解和推断来决定, 类似于重载和泛型。
Python函数定义时也不需要指定函数的类型,这将由函数
5.3.3 可变长度参数
*parameter的用法
>>> def demo(**p): for item in p.items(): print(item) >>> demo(x=1,y=2,z=3) ('y', 2) ('x', 1) ('z', 3)
5.3.3 可变长度参数
几种不同类型的参数可以混合使用,但是不建议这样做
#为列表增加元素
5.2 形参与实参
也就是说,如果传递给函数的是可变序列,并且在函数内
部使用下标或可变序列自身的方法增加、删除元素或修改 元素时,修改后的结果是可以反映到函数之外的,实参也 得到相应的修改。
>>> def modify(d): #修改字典元素值或为字典增加元素 d['age'] = 38 >>> a = {'name':'Dong', 'age':37, 'sex':'Male'} >>> a {'age': 37, 'name': 'Dong', 'sex': 'Male'} >>> modify(a) >>> a {'age': 38, 'name': 'Dong', 'sex': 'Male'}
函数A 函数B 调 用 函数B 函数B 函数B 函数B
调 用
调 用
调 用
调 用
调 用
......
返 回 返 回 返 回 返 回 返 回
返 回
5.2 形参与实参
函数定义时括弧内为形参,一个函数可以没有形参,但是
括弧必须要有,表示该函数不接受参数。
函数调用时向其传递实参,将实参的值或引用传递给形参。
>>> def func_4(a,b,c=4,*aa,**bb): print(a,b,c) print(aa) print(bb) >>> func_4(1,2,3,4,5,6,7,8,9,xx='1',yy='2',zz=3) (1, 2, 3) (4, 5, 6, 7, 8, 9) {'yy': '2', 'xx': '1', 'zz': 3} >>> func_4(1,2,3,4,5,6,7,xx='1',yy='2',zz=3) (1, 2, 3) (4, 5, 6, 7) {'yy': '2', 'xx 3}
5.1 函数定义
函数定义语法:
def 函数名([参数列表]): '''注释''' 函数体
注意事项
函数形参不需要声明其类型,也不需要指定函数返回值类型 即使该函数不需要接收任何参数,也必须保留一对空的圆括号
括号后面的冒号必不可少
函数体相对于def关键字必须保持一定的空格缩进 Python允许嵌套定义函数
5.2 形参与实参
对于绝大多数情况下,在函数内部直接修改形参的值不会
影响实参。例如:
>>> def addOne(a): print(a) a += 1 print(a) >>> a = 3 >>> addOne(a) 3 4 >>> a 3
5.2 形参与实参
在有些情况下,可以通过特殊的方式在函数内部修改实参
试着想一想,这段代码会输出什么呢?
5.3.1 默认值参数
上面的代码输出结果如下,最后一个结果是错的。
[1, 2, 3, 4, '5'] ['a', 'b', 'aaa'] ['a'] ['a', 'b']
继续想:为什么会这样呢?
5.3.1 默认值参数
原因在于默认值参数的赋值只会在函数定义时被解释一次。
当使用可变序列作为参数默认值时,一定要谨慎操作。
最后一个问题来了:正确的代码该怎么写呢?
5.3.1 默认值参数
终极解决方案:改成下面的样子就不会有问题了
def demo(newitem,old_list=None): if old_list is None: old_list=[] old_list.append(newitem) return old_list print(demo('5',[1,2,3,4])) print(demo('aaa',['a','b'])) print(demo('a')) print(demo('b') )
第5章 函数的设计和使用
5.1 函数定义
将可能需要反复执行的代码封装为函数,并在需要该功能
的地方进行调用,不仅可以实现代码复用,更重要的是可 以保证代码的一致性,只需要修改该函数代码则所有调用 均受到影响。
设计函数时,应注意提高模块的内聚性,同时降低模块之
间的隐式耦合。
在实际项目开发中,往往会把一些通用的函数封装到一个
#在外部也可以直接访问函数的成员 #删除函数成员 #删除之后不可访问 no attribute 'x'
5.1 函数定义
函数的递归调用是函数调用的一种特殊情况,函数调用自己,自己再 调用自己,自己再调用自己,...,当某个条件得到满足的时候就不 再调用了,然后再一层一层地返回直到该函数的第一次调用。
5.1 函数定义
生成斐波那契数列的函数定义和调用
def fib(n): a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() fib(1000)
5.1 函数定义
在定义函数时,开头部分的注释并不是必需的,但是如果
为函数的定义加上这段注释的话,可以为用户提供友好的 提示和使用帮助。
5.3.3 可变长度参数
可变长度参数主要有两种形式:
*parameter用来接受多个实参并将其放在一个元组中 **parameter接受关键参数并存放到字典中
5.3.3 可变长度参数
*parameter的用法
>>> def demo(*p): print(p) >>> (1, >>> (1, >>> (1, demo(1,2,3) 2, 3) demo(1,2) 2) demo(1,2,3,4,5,6,7) 2, 3, 4, 5, 6, 7)
模块中,并把这个通用模块文件放到顶层文件夹中,这样 更方便管理。
5.1 函数定义
• 在编写函数时,应尽量减少副作用,尽量不要修改参数本 身,不要修改除返回值以外的其他内容。 • 应充分利用Python函数式编程的特点,让自己定义的函数
尽量符合纯函数式编程的要求,例如保证线程安全、可以
并行运行等等。
5.3.1 默认值参数
再例如,下面的函数使用指定分隔符将列表中所有字符串
元素连接成一个字符串。
>>> def Join(List,sep=None): return (sep or ' ').join(List) >>> aList = ['a', 'b', 'c'] >>> Join(aList) 'a b c' >>> Join(aList, ',') 'a,b,c'
中的return语句来决定,如果没有return语句或者return没 有得到执行,则认为返回空值None。
5.3 参数类型
Python支持对函数参数和返回值类型的标注,但实际上并 不起任何作用,只是看起来方便。
>>> def test(x:int, y:int) -> int: '''x and y must be integers, return an integer x+y''' assert isinstance(x, int), 'x must be integer' assert isinstance(y, int), 'y must be integer' z = x+y assert isinstance(z, int), 'must return an integer' return z >>> test(1, 2) 3 >>> test(2, 3.0) #参数类型不符合要求,抛出异常 AssertionError: y must be integer
5.3.1 默认值参数
默认值参数必须出现在函数参数列表的最右端,且任何一
个默认值参数右边不能有非默认值参数。
5.3.1 默认值参数
调用带有默认值参数的函数时,可以不对默认值参数进行
赋值,也可以赋值,具有较大的灵活性。
>>> def say( message, times =1 ): print(message * times) >>> say('hello') hello >>> say('hello',3) hello hello hello >>> say('hi',7) hi hi hi hi hi hi hi
5.3.1 默认值参数
注意:
默认值参数只在函数定义时被解释一次
可以使用“函数名.__defaults__”查看所有默认参数的当前值
>>> i = 3 >>> def f(n=i): print(n) >>> f() 3 >>> i = 5 >>> f() 3
#参数n的值仅取决于i的当前值
5.1 函数定义
Python是一种高级动态编程语言,变量类型是随时可以改 变的。Python中的函数和自定义对象的成员也是可以随时 发生改变的,可以为函数和自定义对象动态增加新成员。
>>> def func(): print(func.x) >>> func() AttributeError: 'function' object has >>> func.x = 3 >>> func() 3 >>> func.x 3 >>> del func.x >>> func() AttributeError: 'function' object has #查看函数func的成员x #现在函数func还没有成员x,出错 no attribute 'x' #动态为函数增加新成员
#函数定义后修改i的值不影响参数n的默认值
5.3.2 关键参数
关键参数主要指实参,即调用函数时的参数传递方式。 通过关键参数,实参顺序可以和形参顺序不一致,但不影
响传递结果,避免了用户需要牢记位置参数顺序的麻烦。
>>> def demo(a,b,c=5): print(a,b,c) >>> demo(3,7) 3 7 5 >>> demo(a=7,b=3,c=6) 7 3 6 >>> demo(c=8,a=9,b=0) 9 0 8
在定义函数时,对参数个数并没有限制,如果有多个形参,
需要使用逗号进行分割。
5.2 形参与实参
编写函数,接受两个整数,并输出其中最大数。
def printMax(a, b): if a>b: pirnt(a, 'is the max') else: print(b, 'is the max')
5.3 参数类型
位置参数(positional arguments)是比较常用的形式,调 用函数时实参和形参的顺序必须严格一致,并且实参和形 参的数量必须相同。
>>> def demo(a, b, c): print(a, b, c) >>> demo(3, 4, 5) #按位置传递参数 3 4 5 >>> demo(3, 5, 4) 3 5 4 >>> demo(1, 2, 3, 4) #实参与形参数量必须相同 TypeError: demo() takes 3 positional arguments but 4 were given
的值,例如下面的代码。
>>> def modify(v): v[0] = v[0]+1 >>> a = [2] >>> modify(a) >>> a [3] >>> def modify(v, item): v.append(item) >>> a = [2] >>> modify(a,3) >>> a [2, 3] #修改列表元素值
5.3.1 默认值参数
默认值参数如果使用不当,会导致很难发现的逻辑错误,
例如:
def demo(newitem,old_list=[]): old_list.append(newitem) return old_list print(demo('5',[1,2,3,4])) #right print(demo('aaa',['a','b'])) #right print(demo('a')) #right print(demo('b')) #wrong