为什么需要函数?
先使用目前的知识点实现一个需求:
```python
"""
三个功能
1.登录
2.购物车
3.收藏夹
收藏夹和 购物车 需要先登录才能使用!
"""
表示当前用户
current_user = None
while True:
print("""
1.登录
2.购物车
3.收藏夹
""")
choice = input("请选择功能:").strip()
if choice == "1":
print("登录!")
name = input("name:").strip()
pwd = input("pwd:").strip()
with open("user.txt",encoding="utf-8") as f:
for line in f:
ls = line.split("|")
if ls[0] == name and ls[1] == pwd:
print("登录成功!")
current_user = ls[0]
break
else:
print("用户名或密码不正确!")
elif choice == "2":
print("购物车")
# 判断是已经登录过了
# print(current_user)
if not current_user:
print("请先登录!")
name = input("name:").strip()
pwd = input("pwd:").strip()
with open("user.txt", encoding="utf-8") as f:
for line in f:
ls = line.split("|")
if ls[0] == name and ls[1] == pwd:
print("登录成功!")
current_user = ls[0]
break
else:
print("用户名或密码不正确!")
else:
with open("购物车.txt",encoding="utf-8") as f:
print("你购买了 <<%s>>" % f.read())
elif choice == "3":
print("收藏夹")
if not current_user:
print("请先登录!")
name = input("name:").strip()
pwd = input("pwd:").strip()
with open("user.txt", encoding="utf-8") as f:
for line in f:
ls = line.split("|")
if ls[0] == name and ls[1] == pwd:
print("登录成功!")
current_user = ls[0]
break
else:
print("用户名或密码不正确!")
else:
with open("收藏夹.txt",encoding="utf-8") as f:
print("你收藏了了 <<%s>>" % f.read())
else:
print("输入错误")
```
目前程序中存在的问题:
```python
"""
1.代码的组织结构不清晰,可读性差
2.代码冗余度高
3.管理维护难度大,扩展性极差
"""
```
解决上述问题的方案就是函数
在生活中也有类似的场景
例如,安装网线时,电信公司会派一个安装师傅到你家来给你接通网线,通常这个安装师傅都会自带一个工具箱,到你家后打开工具箱就开始干活,
要接网线拿一个网线钳,要测试网络就拿出电脑,试想一下,如果他不自己带上工具来,会是什么情况,要接网线还得一根一根线去接,要测试网
络还得用舌头舔一舔!就像程序里面每次登陆都要把一堆代码重写一遍!
什么是函数?
函数是实现某个功能的代码的集合体,其具备一个名称即函数名,通过函数名就可以访问到函数,并执行内部的代码块
相当于现实生活中的工具,例如扳手,当我们需要拧螺丝时拿出扳手就能很方便的搞定!
需要强调的是:要想使用扳手,则必须先制造扳手。
同理:要想使用函数,则必须先定义函数
**所以使用函数时必须遵循 先定义,再调用**
定义函数
语法:
```python
def 函数名称(参数1,参数2...):
"""
文档注释
可以被help函数提取
"""
代码1
代码2
代码n
return 值
```
def:定义函数得关键字
函数名:用于 查找/调用 函数,函数名必须能够体现函数所实现的功能,函数名也是名字,与变量名一样,需遵循命名规范,并且都是用来绑定内存地址
文档注释:用于描述该函数的详细信息,可以被help函数提取
代码块:称之为函数体,即函数功能的具体实现代码
return:函数的返回值
```python
需求:打印如下内容
"hello world!"
"hello world!"
"hello world!"
1.定义阶段
def print_hello_world():
for i in range(3):
print("hello word!")
2.调用阶段
#print(print_hello_world)
print_hello_world()#
print_hello_world()
```
函数的三种类型
1.无参函数
当函数体代码的执行不需要依赖外部的传入数据时
```python
需求 输出python的描述信息
def print_py_info(): # 不需要依赖任何外部的值
print("==================)
print("python is good language!")
print("==================)
print_py_info() # 定义时没有参数 调用时也不需要且不能传参数
#print_py_info(1) #报错
需求2 接收用户名和 密码
def input_user_info():
name = input("name:").strip()
pwd = input("password:").strip() print(name,pwd)
```
2.有参函数
当函数体的代码逻辑需要依赖外部传如入数据时
```python
需求 比较两个数的大小
def max_two(a,b):
if a > b:
print(a)
else:
print(b)
需求2 求列表中最大值
def max_list(li):
max = li[0]
for i in li:
if i > max:
max = i
print(max)
需求2 实现登录
```
不要为了定义函数而定义函数,当程序代码结构混乱时就必须要拆分到不同函数中,减少代码冗余,提高维护性扩展性,使代码结构更清晰
一个函数的功能应该尽可能的独立完整,例如接收输入就干接收输入,验证用户就干验证用户,读取文件就干读取文件
生活中一个的反例就是多功能折叠刀
3.空函数
函数中只有pass时就是空函数,pass表示略过,什么也不干
```python
def func():
pass
func()# 什么也不干
```
调用空函数是没有任何意义的,空函数仅用于编写程序初期定义程序结构
正常开发中在拿到一个项目时不是立即开始编写代码,而是先分析项目具备哪些功能,将功能列表先定义出来,这时就可以用空函数了,例如要实现,购物车项目
```python
def login():
"""
这是登录功能
"""
pass
def register():
"""
这是注册功能
"""
pass
def shop_car():
"""
这是购物功能
"""
pass
```
定义阶段与调用阶段
定义阶段发生的事情:
1. 申请内存空间存储函数体代码
2. 将内存地址与函数名称进行绑定
需要注意的是,函数的定义阶段不会执行函数体代码,但是会检测语法
```python
def print_hello_world(): # print_hello_world = <function print_hello_world at 0x1047efe18>
abcdassaas
1 / 0
print(100)
for i in range(3):
print("hello world!")
a = 10
print(a)
正常秩序不报错
```
调用阶段发生的事情:
1. 通过名称找到函数的内存地址
2. 加括号触发函数体代码的执行
函数的调用
函数的使用必须遵循先定义,后调用
常见错误
案例1:
```python
func()# 报错:NameError: name 'func' is not defined
def func():
print("func run!")
违反了先定义后调用
```
案例2:
```python
def func1():
print("func1 run")
func2()
func1() #报错:NameError: name 'func2' is not defined
def func2():
print("func2 run")
代码自上而下 顺序执行
func2的定义还没有执行到,就在调用func1时被调用了,不报错是pycharm检测到文件中的确有func2函数,但是pycharm是无法检测代码执行顺序的
正确写法
def func1():
print("func1 run")
func2()
def func2():
print("func2 run")
func1()
```
三种调用方式
```python
直接调用
def func():
print(1)
func()
表达式中调用
def max(a,b):
if a > b:
return a
else:
return b
print(max(1,2) * 10)
将函数得返回值作为参数
print(max(10,max(20,30)))
```
函数的返回值
在函数体中使用return关键字来返回值给调用者
当一个功能的执行会产生一个明确的值时,需要使用返回值
案例1:制作面包的机器,需要一堆面粉作为参数,制作完的面包要返回给使用者
```python
def make_bread(mf):
print("揉",mf)
print("烤",mf)
print("烤完了")
return "金黄的大面包!"
res = make_bread("面粉")
print(res)
```
案例2:获取列表的平均值
```python
def max_list(li):
max = li[0]
for i in li:
if i > max:
max = i
return max
res = max_list([1,23,4,12,12,1212])
```
其他用法
1.返回多个值
会把多个值打包成元组类型
```python
def func():
return 1,2,3
res = func()
print(res)
# 小技巧
# 对返回值进行解压
a,b,c = func()
```
2.返回空(None)
仅有一个return关键字
```python
def func():
return
res = func()
print(res)
需要注意的是 如果函数中没有出现return关键字,默认返回None
def func2():
1 + 1
res = func2()
print(res)
```
3.多个return
函数中出现了多个return关键字
```python
def func():
print(1)
return 1
print(2)
return 2
func()
```
可以发现无论有几个return都只有一个会执行
**只要函数执行时遇到了return立即结束函数执行,无论下面是否有代码**
基于这个特点,我们可以将之前的比较大小进行改写
```python
def max(a,b):
if a > b:
return a
return b
print(max(10,20))
```
最后改造之前写的练习
```python
def login():
name = input("name:").strip()
pwd = input("pwd:").strip()
with open("user.txt", encoding="utf-8") as f:
for line in f:
ls = line.split("|")
if ls[0] == name and ls[1] == pwd:
print("登录成功!")
return ls[0]
else:
print("用户名或密码不正确!")
def read_file(file):
with open(file, encoding="utf-8") as f:
return f.read()
表示当前用户
current_user = None
while True:
print("""
1.登录
2.购物车
3.收藏夹
""")
choice = input("请选择功能:").strip()
if choice == "1":
print("登录!")
current_user = login()
elif choice == "2":
print("购物车")
# 判断是已经登录过了
# print(current_user)
if not current_user:
current_user = login()
else:
print("你购买了 <<%s>>" % read_file("购物车.txt"))
elif choice == "3":
print("收藏夹")
if not current_user:
print("请先登录!")
current_user = login()
else:
print("你收藏了了 <<%s>>" % read_file("收藏夹.txt"))
else:
print("输入错误")
```