Python基础 day08--函数基本使用
从前面的几篇博客中,我们已经熟悉了print()、input()和len()函数。Python提供了这样一些内建函数,但你也可以编写自己的函数。"函数"就像一个程序内的小程序一样。
在之前的学习中,只是用Python实现了一些简单的功能,这些功能也只是由简单的流程控制语句配合数据类型(如列表、字典)实现,但是这些程序有着无法避免的缺陷,比如说:
- 代码耦合性太高,各功能都糅合在一起,“干湿”不分离。
- 扩展性差,由于代码都揉在一起,如果要添加新的功能,可能就要费一番功夫了。
- 代码冗余,比如实现一个加法功能,那么当别处还需要这个功能的话,还要重新实现这个功能,这种情况多了,就是在重复的造轮子,这种情况是不可取的。
- 可读性差,经过如上的几种不可避免操作之后,代码可读性就变得非常差。
列举了如上的几种目前代码的弊端之后,该如何解决呢?解决方法就是使用函数。其实我们在之前的学习中已经体会到函数的好处了,比如要计算一个列表的长度,可能想到用for循环解决问题:
count = 0
li = ['曹操','吕布','周瑜','孙权','马超','郭嘉']
for i in li:count += 1print(count)
# 结果为:
6
当要计算一串字符串、元组的长度,此时不可避免的陷入重复造轮子的过程。知道学习了len()函数之后。
li = ['曹操','吕布','周瑜','孙权','马超','郭嘉']
print(len(li))
# 结果为:
6
函数的定义与调用
创建(定义)函数
def <function_name>([arg1,arg2,...argn]):'''functional annotation'''passreturn
通过def关键字来定义函数,空格之后的function_name 为函数名(必须有),函数的命名规则参考变量的命名。括号(必须有)内的参数是可选的,括号后面的 : 也是必须的。注释部分为可选的(但强烈建议有注释,就像功能说明书一样),pass部分为函数的具体功能实现代码。执行结果视情况可以选择用return返回,如果没有显式的return具体内容的话,默认返货None。
虽然def 为关键字,但def也是可执行的语句,就是说当定义完函数之前,这个函数此时是不存在的:
print(dir())
def fun():pass
print(dir)
# 结果为:
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
<built-in function dir>
第一个打印结果显示,当程序执行到def语句之前,fun函数不存在,而当def执行完毕,第二个打印结果告诉我们,当前的名称空间内存在了fun函数。
注意:dir()函数返回绑定在当前名称空间内(如果参数为空)的变量。
函数声明:
def 函数名(形式参数1):函数体return 函数结束语句
函数调用:
返回值变量 = 函数名(实际参数1)
返回值变量2 = 函数名(实际参数2)
当Python解释器执行到def 语句时,def语句创建一个函数对象并将这个对象赋值给def 后面的function_name变量。然后这个变量指向这个函数,或者说这个函数名(变量名)成为了这个函数的引用。因为def为执行语句,函数可以嵌套在if等语句内:
def fun():print("fun function")
def bar():print("bar 函数")
if 1:fun()
else:bar()for i in range(10):if i == 2:fun()else:bar()
# 结果为:
fun function
bar 函数
bar 函数
fun function
bar 函数
bar 函数
bar 函数
bar 函数
bar 函数
bar 函数
bar 函数
通过上面的栗子,也可以看到,fun() 和 bar()函数一处定义,多出调用。函数的特点:
- 最大化的减少代码冗余和代码重用。
- 程序的结构分解,也就是解耦合。
- 打包打代码,使功能更加独立。
通过若干函数将整个程序的功能拆分开,每个功能都是独立的存在。而上述示例也说明了函数要先定义,后调用。(类似C++的变量,先声明,后使用)。而栗子中的函数加括号,是执行这个函数:
def fun():return 1print(fun)
# 输出结果为:
<function fun at 0x0000028C5CB261F0>
print(fun())
# 输出结果为:
1
由上示例可以看出,打印这个函数时,打印的时函数在内存中的地址,而打印这个函数加括号,打印的时这个函数的执行结果。
当定义了一个函数对象之后,这个对象允许任何附属功能绑定到这个函数对象上:
def fun():return 1def bar():pass
bar.a = fun()
bar.b = 3
print(bar.a)
# 输出结果为:
1
print(bar.b)
# 输出结果为:
3
可以看到,我们分别将fun函数的执行结果和整数3绑定到了bar函数对象上。
注意:养成良好的编程习惯,写注释。
虽然函数的注释是可选的,但我们强烈建议有注释(虽然后买你的栗子中为了节省空间且函数功能太小,有些可能不带),因为注释就相当与这个函数的说明书。
函数的返回值
- 函数体中 return 语句有指定返回值时返回的就是其值
- 函数体中没有 return 语句时,函数运行结束会隐含返回一个 None 作为返回值,类型是 NoneType,与 return 、return None 等效,都是返回 None。
def fun():passf = fun()
print(f)
# 结果为:
None
如上示例,如果函数没有显示的写return,那么默认返回None。我们可以理解为当我们没有写return时,该函数默认return None。
返回一个值
def fun():# return 1# return 'abc'# return [1, 2, 3]# return {'name':'悟空'}return len('1234')f = fun()
print(f)
# 结果为:
4
可以看到return 返回的值是任意类型。
返回多个值
当一个函数返回多个值的时候,值之间需要用逗号隔开,最后多个值以元组的方式返回。
def fun():return 1, 2, {'name':'孙悟空'}, ['黑豹警长','舒克贝塔']print(ret) # 这句没有打印result = fun()
print(result)
# 结果为:
(1, 2, {'name': '孙悟空'}, ['黑豹警长', '舒克贝塔'])
print(result[2])
# 结果为:
{'name': '孙悟空'}
由上例还可以发现,return 之后的print语句并没有执行。这也是return返回的另一个特点,那就是终止函数的执行。
函数的参数
之前示例中的函数并没有传递参数,这样的函数成为无参函数。对应的就是有参函数。有参函数的参数传参方式一般分为:位置参数、关键字传参、接收可变长度的参数、命名关键字参数。而在传递参数的时候,一般根据参数的实际意义来划分,函数接收的参数为形式参数(形参),调用函数的参数为实际参数(实参)。
def fun(x,y): # x,y为:形式参数(形参)。print(x+y)return '计算完成!'
fun(5, 6) # 5和6 为:实际参数(实参)
# 结果为:
11
f = fun(5, 6)
# 结果为:
11
print(f) # return 返回"计算完成!"
# 返回值为:
"计算完成!"
函数的形参可以接受任意类型的参数,但又由于不确定接收的到底什么类型,所以称为形式参数。而调用时传递的参数就是一个具体的数据,所以称为实际参数。
通俗的说,形参就像萝卜坑,而实参就是萝卜,但萝卜也不能随便找个坑就好了,什么样的萝卜对应什么样的坑那是有规矩的。
常见的函数传参方式
常规参数,按位置匹配传参
def func(value):print(value)func("中国")
# 结果为:
中国
func函数,参数的传递按照位置传参。位置传参需要按照从左到右的顺序依次定义参数。
按位置传参的形参,必须被船只,而对应得实参,必须与形参一一对应,多一个不行,少一个也不行,位置不对,输出结果也不正确。
按照关键字传参,通过变量名匹配传参
def math1(a,b):print(a+b)math1(b=9,a=1)
# 结果输出为:
10
math1函数,按照关键字传参。关键字参数可以不用想位置实参一样与形参一一对应,而是指定参数的传值。多个关键字传参的话,因为指定将key传给指定的value,所以也就不必在乎前后顺序了,为了增强可读性,我们仍建议按照位置传参的形式为关键字传参。而当形参位置已经有值得话,则为默认参数,而默认参数在定义函数阶段,就已经为形参赋值,定义阶段有值,调用阶段如无必须无需船只。如果实参是经常变化得值,那么在定义位置是定义为位置形参,如果实参是不经常变化得时候,形参可以定义为默认参数。当位置参数和关键字参数都存在的话,位置参数优先级大于关键字参数。
def stu(value1,value2,value3):print(f'值1:{value1}, 值2:{value2}, 值3:{value3}')stu(99,value2=108,value3=2020)
# 结果为:
值1:99, 值2:108, 值3:2020def stu(name,gander="女"):print("姓名:{},性别:{}".format(name,gander))stu("黑猫警长","男")
# 结果为:
姓名:黑猫警长,性别:男
stu("小龙女")
# 结果为:
姓名:小龙女,性别:女
stu函数,以*args传递所有的实参对象,并作为一个(都被手机到元组内)基于位置的参数。就是说*args接受所有的出key=value格式的位置参数。
位置传参和可变长度搭配传参
def func5(value, *args):print(value, args)func5(1, 2, 3, 4, 5) # 第一个参数按照位置传参,剩余的被 *args 收集
# 结果:
1 (2, 3, 4, 5)
func5
函数,位置和可变长度的*args
结合,从结果来看,从左到右的第一个参数按位置传递给了value
,而剩余的位置参数都被*args
接收。
*args
接收任意长度的位置参数,并收集到元组中, 命名关键字参数value接收关键字参数
def func6(*args, value):print(args,value)func6("葫芦娃", "黑猫警长", "舒克贝塔", "齐天大圣", value=5)
# 命名关键字传参,前面被*args接收,value以key=value的形式传递
# 结果为:
('葫芦娃', '黑猫警长', '舒克贝塔', '齐天大圣') 5
func6函数,可变长度参数配合命名关键字参数(value),*args 接收所有位置参数,而当value在*args后面的时候,我们称其为命名关键字参数,而命名关键字参数定义在*后的形参,这类形参,必须被传值,而且要求实参必须是以关键字的形式来传值。
接受任意长度的key=value形式的参数,并收集到一个字典内,一般在所有的参数的后面。
def func7(**kwargs):print(kwargs) # {'a': 1, 'b': 2, 'c': 3}func7(西游记='齐天大圣', 圣斗士='星矢', 四驱兄弟='小豪')
# 结果为:
{'西游记': '齐天大圣', '圣斗士': '星矢', '四驱兄弟': '小豪'}
func7函数,**kwargs接收任意长度的key=value合适的参数,并收集到字典中。注意:**kwargs还是要放到*args的后面。
各种传参混用,但是不推荐这种传参方式,提高了代码的复杂度,这里只是介绍可以这么用而已。
def func8(*args, **kwargs):print(args, kwargs)func8('猪八戒', '孙悟空', 3, 4, a=5, b=6)
# 结果为:
('猪八戒', '孙悟空', 3, 4) {'a': 5, 'b': 6}
func8函数,*args
和**kwargs
一起使用的话,可以接收任意形式、任意长度的参数。但切记**kwargs
还是要放到*args
的后面。
Python基础 day08--函数基本使用相关推荐
- python的用途实例-Python基础之函数原理与应用实例详解
本文实例讲述了Python基础之函数原理与应用.分享给大家供大家参考,具体如下: 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体 ...
- Python基础day08 作业解析【7道 面向对象题目】
视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] Python基础day08[面向对象(类.对象.属性).魔方方法(init.str.del.rep ...
- Python基础之函数
详情请戳 python基础之函数介绍及使用 python基础之内置函数 python基础之迭代器和生成器 python基础之装饰器 转载于:https://www.cnblogs.com/zhangl ...
- Python数据结构与算法(1.5)——Python基础之函数与异常
Python数据结构与算法(1.5)--Python基础之函数与异常 0. 学习目标 1. 函数 1.1 自定义函数 1.2 函数与参数 1.3 函数与返回值 2. 异常处理 2.1 raise 语句 ...
- 刻意练习:Python基础 -- Task05. 函数与Lambda表达式
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- Python基础day08【面向对象(类、对象、属性)、魔方方法(init、str、del、repr)】
视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] 目录 0.复习 1.类外部添加和获取对象属性 2.类内部操作属性 3.魔法方法 3.1.__i ...
- Python基础__函数
本节将进入函数的介绍,函数是Python基础中最精彩的部分之一,接下来将对函数做详细介绍. 函数 函数就是对代码进行一个封装.把实现某一功能的代码进行封装到一起.下次需要使用时不需要进行编写代码直接调 ...
- 『Python基础』函数
Python中的函数 函数 (1)什么是函数? 软件开发,是为了解决生活中的问题,函数就是生活中的一种行为,如:吃饭.睡觉.学习.游戏等等等- 不需要资源.不需要结果.执行即可 关门的行为 需要资源. ...
- 第七篇 python基础之函数,递归,内置函数
阅读目录 一 数学定义的函数与python中的函数 二 为何使用函数 背景提要 三 函数和过程 四 函数参数 五 局部变量和全局变量 六 前向引用之'函数即变量' 七 嵌套函数和作用域 八 递归调用 ...
- python入门之函数调用内置函数_第九篇 python基础之函数,递归,内置函数
阅读目录 一 数学定义的函数与python中的函数 二 为何使用函数 背景提要 三 函数和过程 四 函数参数 五 局部变量和全局变量 六 前向引用之'函数即变量' 七 嵌套函数和作用域 八 递归调用 ...
最新文章
- Oracle 12c 新特性之 temp undo
- Linux下Minigui开发环境的搭建(PC+S3C2440
- java 8 并行_Java 8新特性之 并行和并行数组(八恶人-8)
- php v9开发网站,phpcms开发步骤
- 二位四进制计数器_金三银四还在看JVM这一块?看完这篇万字JVM面试解析就够了...
- 上层应用开发是否真的没有底层开发有前途?
- P1313 计算系数
- python 正则表达式 \b 大坑
- Java架构师成长之道之计算机组成原理概述篇
- 史上最难的初等几何问题?分享一个参考答案
- java尚硅谷 java基础第一个项目,记账软件
- centos php 开启libgdgd_linux gd
- 激光SLAM 前端数据预处理--剔除坏点方法总结
- portraiture4图片修图磨皮滤镜插件支持Win和Mac
- Xshell下载安装教程和使用教程(超详细)
- xml文件基本格式与解析
- github.io使用方法
- 国脉科技股份有限公司
- Linux配置yum源出现的问题
- 计算机硬件初中,初中信息技术-认识计算机硬件
热门文章
- Excel如何下拉实现按16进制递增?
- 应收账款和应付账款字段无效
- mac下Homebrew安装Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask failed报错解决方法
- fairygui富文本html语法怎么用,文本-FairyGUI 教程-面试哥
- ARM汇编指令xmind
- 质检总局:智能摄像头抽检八成存隐患,或致视频泄露
- 《Go程序设计语言》中文版翻译错误
- 『C/C++养成计划』C++项目遇到Aborted (core dumped)的处理方法
- 软件质量保证测试——共享车位
- 米莱狄机器人怎么那么多_王者米莱狄小机器人怎么变大机器人