一 引子
1 为何要用函数之不用函数的问题
- #1 代码的组织结构不清晰, 可读性差
- #2 遇到重复的功能只能重复编写实现代码, 代码冗余
- #3 功能需要扩展时, 需要找出所有实现该功能的地方修改之, 无法统一管理且维护难度极大
2 函数是什么?
针对二中的问题, 想象生活中的例子, 修理工需要实现准备好工具箱里面放好锤子, 扳手, 钳子等工具, 然后遇到锤钉子的场景, 拿来锤子用就可以, 而无需临时再制造一把锤子
修理工 ===> 程序员
具备某一功能的工具 ===> 函数
要想使用工具, 需要事先准备好, 然后拿来就用且可以重复使用
要想用函数, 需要先定义, 再使用
3 函数分类
#1 内置函数
为了方便我们的开发, 针对一些简单的功能, python 解释器已经为我们定义好了的函数即内置函数对于内置函数, 我们可以拿来就用而无需事先定义, 如 len(),sum(),max()
ps: 我们将会在最后详细介绍常用的内置函数
#2 自定义函数
很明显内置函数所能提供的功能是有限的, 这就需要我们自己根据需求, 事先定制好我们自己的函数来实现某种功能, 以后, 在遇到应用场景时, 调用自定义的函数即可
二 定义函数
1 如何自定义函数?
# 语法
def 函数名 (参数 1, 参数 2, 参数 3,...):
注释
函数体
return 返回的值
- # 函数名要能反映其意义
- def func(user,pwd):
验证用户名密码
- if user == duoduo and password == 123:
- return 1 #返回 1
- user=input(用户名 >>: ).strip()
- pwd=input(密码 >>: ).strip()
- res=func(user,pwd)
- print(res)
- # 输入用户名密码正确, 会得到值为 1
2 函数使用的原则: 先定义, 再调用
函数即变量, 变量必须先定义后引用未定义而直接引用函数, 就相当于在引用一个不存在的变量名
- # 测试一
- def foo():
- print(from foo)
- bar()
- foo() #报错 foo 函数中函数 bar 还未定义
- # 测试二
- def bar():
- print(from bar)
- def foo():
- print(from foo)
- bar()
- foo() #正常
- # 测试三
- def foo():
- print(from foo)
- bar()
- def bar():
- print(from bar)
- foo() #会报错吗? 会! 函数还未定义, 无法调用
- # 结论: 函数的使用, 必须遵循原则: 先定义, 后调用 #我们在使用函数时, 一定要明确地区分定义阶段和调用阶段
- # 具体图解可也点这篇: http://www.cnblogs.com/ManyQian/p/8137462.html
- # 定义阶段
- def foo():
- print(from foo)
- bar()
- def bar():
- print(from bar)
- # 调用阶段
- foo()
函数即变量, 变量必须先定义后引用未定义而直接引用函数, 就相当于在引用一个不存在的变量名
- # 测试一
- def foo():
- print(from foo)
- bar()
- foo() #报错
- # 测试二
- def bar():
- print(from bar)
- def foo():
- print(from foo)
- bar()
- foo() #正常
- # 测试三
- def foo():
- print(from foo)
- bar()
- def bar():
- print(from bar)
- foo() #会报错吗?
- # 结论: 函数的使用, 必须遵循原则: 先定义, 后调用
- # 我们在使用函数时, 一定要明确地区分定义阶段和调用阶段
- # 定义阶段
- def foo():
- print(from foo)
- bar()
- def bar():
- print(from bar)
- # 调用阶段
- foo()
3 函数在定义阶段都干了哪些事?
# 只检测语法, 不执行代码
也就说, 语法错误在函数定义阶段就会检测出来, 而代码的逻辑错误只有在执行时才会知道
4 定义函数的三种形式
- #1 无参: 应用场景仅仅只是执行一些操作, 比如与用户交互, 打印
- #2 有参: 需要根据外部传进来的参数, 才能执行相应的逻辑, 比如统计长度, 求最大值最小值
- #3 空函数: 设计代码结构
- # 定义阶段
- def tell_tag(tag,n): #有参数
- print(tag*n)
- def tell_msg(): #无参数
- print(hello world)
- # 调用阶段
- tell_tag(*,12)
- tell_msg()
- tell_tag(*,12)
- ************
- hello world
- ************
- # 结论:
- #1 定义时无参, 意味着调用时也无需传入参数
- #2 定义时有参, 意味着调用时则必须传入参数
- def auth(user,password):
- auth function
:param user: 用户名
:param password: 密码
:return: 认证结果
- pass
- def get(filename):
- :param filename:
- :return:
- pass
- def put(filename):
- :param filename:
- :return:
- def ls(dirname):
- :param dirname:
- :return:
- pass
- # 程序的体系结构立见
三 调用函数
1 调用函数
函数的调用: 函数名加括号
1 先找到名字
2 根据名字调用代码
2 函数返回值
无 return->None #没有意义的 return None 值也是 None
return 1 个值 -> 返回 1 个值
return 逗号分隔多个值 -> 元组
什么时候该有返回值?
调用函数, 经过一系列的操作, 最后要拿到一个明确的结果, 则必须要有返回值
通常有参函数需要有返回值, 输入参数, 经过计算, 得到一个最终的结果
什么时候不需要有返回值?
调用函数, 仅仅只是执行一系列的操作, 最后不需要得到什么结果, 则无需有返回值
通常无参函数不需要有返回值
3 函数调用的三种形式
语句形式: foo()
表达式形式: 3*len(hello)
当中另外一个函数的参数: range(len(hello))
四 函数的参数
1 形参与实参
# 形参即变量名, 实参即变量值, 函数调用时, 将值绑定到变量名上, 函数调用结束, 解除绑定
2 具体应用
#1 位置参数: 按照从左到右的顺序定义的参数
位置形参: 必选参数
位置实参: 按照位置给形参传值
#2 关键字参数: 按照 key=value 的形式定义的实参
无需按照位置为形参传值
注意的问题:
1. 关键字实参必须在位置实参右面
2. 对同一个形参不能重复传值
#3 默认参数: 形参在定义时就已经为其赋值
可以传值也可以不传值, 经常需要变得参数定义成位置形参, 变化较小的参数定义成默认参数 (形参)
注意的问题:
1. 只在定义时赋值一次
2. 默认参数的定义应该在位置形参右面
3. 默认参数通常应该定义成不可变类型
#4 可变长参数:
可变长指的是实参值的个数不固定
而实参有按位置和按关键字两种形式定义, 针对这两种形式的可变长, 形参对应有两种解决方案来完整地存放它们, 分别是 * args,**kwargs
- ===========*args===========
- def foo(x,y,*args):
- print(x,y)
- print(args)
- foo(1,2,3,4,5)
- def foo(x,y,*args):
- print(x,y)
- print(args)
- foo(1,2,*[3,4,5])
- def foo(x,y,z):
- print(x,y,z)
- foo(*[1,2,3])
- ===========**kwargs===========
- def foo(x,y,**kwargs):
- print(x,y)
- print(kwargs)
- foo(1,y=2,a=1,b=2,c=3)
- def foo(x,y,**kwargs):
- print(x,y)
- print(kwargs)
- foo(1,y=2,**{a:1,b:2,c:3})
- def foo(x,y,z):
- print(x,y,z)
- foo(**{z:1,x:2,y:3})
- ===========*args+**kwargs===========
- def foo(x,y):
- print(x,y)
- def wrapper(*args,**kwargs):
- print(====>)
- foo(*args,**kwargs)
- #5 命名关键字参数:* 后定义的参数, 必须被传值 (有默认值的除外), 且必须按照关键字实参的形式传递
可以保证, 传入的参数中一定包含某些关键字
- def foo(x,y,*args,a=1,b,**kwargs):
- print(x,y)
- print(args)
- print(a)
- print(b)
- print(kwargs)
- foo(1,2,3,4,5,b=3,c=4,d=5)
结果:
1 x 值
2 y 值
(3, 4, 5) args 值
1 a 值
3 b 值
{c: 4, d: 5} kwargs 值
python 全栈开发 - Day8 函数基础
来源: http://www.bubuko.com/infodetail-2538111.html