一、函数基础
1.1、函数的用法和底层分析
函数是可重用的程序代码块。
函数的作用,不仅可以实现代码的复用,更能实现代码的一致性。一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现。
在编写函数时,函数体中的代码写法和我们前面讲述的基本一致,只是对代码实现了封装,并增加了函数调用、传递参数、返回计算结果等内容。
1.2、函数简介
1.2.1函数的基本概念
一个程序由一个一个的任务组成;函数就是代表一个任务或者一个功能(function)。
函数是代码复用的通用机制
1.2.2、函数的分类
内置函数
我们前面使用的
str()
、list()
、len()
等这些都是内置函数,我们可以拿来直接使用。标准库函数
我们可以通过
import
语句导入库,然后使用其中定义的函数第三方库函数
Python社区也提供了很多高质量的库。下载安装这些库后,也是通过
import
语句导入,然后可以使用这些第三方库的函数用户自定义函数
用户自己定义的函数,显然也是开发中适应用户自身需求定义的函数。今天我们学习的就是如何自定义函数。
1.2.3、 函数的定义和调用
实现某个功能的一段完整的代码code. 使用函数名称进行封装.以便 通过函数名调用,实现一次编写,多次调用的目的.
python语言中:封装函数尽量做到: 高内聚 低耦合 (只完成自己的 功能, 函数执行成功与失败,与别的内容无关)
自定义函数语法:
def 函数名(形式参数列表):
code # 函数体
return value
python">def add(a,b,c):# 执行三个数相加,并返回和sum=a+b+cprint(f'{a} {b} {c}三个数相加的和为:{sum}')return sum
add(10,20,30)
我们使用def来定义函数,然后就是一个空格和函数名称;
Python执行def时,会创建一个函数对象,并绑定到函数名变量上。
参数列表
圆括号内是形式参数列表,有多个参数则使用逗号隔开
定义时的形式参数不需要声明类型,也不需要指定函数返回值类型
调用时的实际参数必须与形参列表一一对应
return返回值
如果函数体中包含return语句,则结束函数执行并返回值;
如果函数体中不包含return语句,则返回None值。
调用函数之前,必须要先定义函数,即先调用def创建函数对象
内置函数对象会自动创建
标准库和第三方库函数,通过import导入模块时,会执行模块中的def语句
二、函数的参数传递
2.1、位置参数
位置参数是最基本的参数传递方式,函数调用时参数的传递顺序必须与函数定义时的参数顺序一致
python"># 定义一个函数
def function(name, age, sex): # 需要传递三个参数print(f"姓名: {name}, 年龄:{age}, 性别: {sex}")# 调用这个函数
function("懒洋洋", 5, "Man")#姓名: 懒洋洋, 年龄:5, 性别: Man
2.2、关键字参数
关键字参数允许在调用函数时使用参数名来传递参数,这样可以不必考虑参数的顺序
python"># 定义一个函数 info: 做一个自我介绍
def info(name, age, score):print(f"my name is {name}, age: {age}, score: {score}")# 使用关键字去调用info 函数
info(age=18, score=100, name="小白")#my name is 小白, age: 18, score: 100
info("小白",score=90, age=6) # my name is 小白, age: 6, score: 90
2.3、缺省参数
缺省参数允许在定义函数时为某些参数提供默认值。如果在调用函数时没有提供这些参数的值,则使用默认值
python"># 定义一个函数 info: 做一个自我介绍
def info(name="某某某", age=18, score=100):print(f"my name is {name}, age: {age}, score: {score}")# 调用info函数
info() # info函数在调用的时候没有给出参数,则name,age, score使用的是默认值
info("小白") # 小白给出的是位置参数name的内容, age,score使用的是默认值
info(age=5, score=20) # age, score是关键字参数, name是没有给出值得.# name使用的是默认值参数info("小黑", age=10) # name是位置参数,age是关键字参数,score:默认值
info(age=18,"小白",score=20) # error :一旦使用了关键字参数,后面的内容就能再是# 位置参数了。
2.4、不定长参数
不定长参数允许在调用函数时传递任意数量的位置参数和关键字参数。这种参数在函数定义时使用
*args
和**kwargs
2.4.1、*args
不定长位置参数使用
*args
接收多个位置参数,参数以元组的形式传递
python">def info(name, age, *hobby): # hobby参数前面有一个*表示的是不定长参数。print(f"name:{name}, age: {age}")print(f"hobby : {hobby}")# hobby这个参数是一个元组print(f"{type(hobby)}")# 调用函数info # 小白 与 5 是位置参数,会给到name,age
# "足球", "篮球", "保龄球" 属于不定长参数,打包成元组,给到 hobby这个变量
info("小白", 5, "足球", "篮球", "保龄球")
# name:小白, age: 5
# hobby : ('足球', '篮球', '保龄球')
# <class 'tuple'>
print("*"*20)
info("小黑",10, "唱", "跳", "舞", "吃", "喝")
# name:小黑, age: 10
# hobby : ('唱', '跳', '舞', '吃', '喝')
# <class 'tuple'>
2.4.2、 **kwargs
不定长关键字参数使用
**kwargs
接收多个关键字参数,参数以字典的形式传递
python">def info(name, age, **parent): # parent:不定长参数: 前面有**,会将键值对的# 形式的参数打包成字典print(f"name: {name}, age: {age}")print(f"parent: {parent}")print(f"parent: {type(parent)}")# 调用info函数
info("小白", 5, mother="母亲", father="父亲")
# name: 小白, age: 5
# parent: {'mother': '母亲', 'father': '父亲'}
# parent: <class 'dict'>
2.4.3、组合
python">def info(name, age, *hobby, **parent):print(f"name:{name}, age: {age}, hobby: {hobby}, parent:{parent}")print(f'{type(hobby)}')print(f'{type(parent)}')# 调用info函数
info("小白", 5, "唱","跳", "篮球", mother="母亲", father="父亲")
'''
name:小白, age: 5, hobby: ('唱', '跳', '篮球'), parent:{'mother': '母亲', 'father': '父亲'}
<class 'tuple'>
<class 'dict'>
'''# error,在* 与 **混用的时候,一旦使用了**传递键值对儿的时候,就不能再传递单个的参数了。
# info("小黑", 5, "唱", mother="母亲", father="父亲", "跳", "篮球")
三、函数的返回值
return
返回值要点:如果函数体中包含
return
语句,则结束函数执行并返回值如果函数体中不包含
return
语句,则返回None
值要返回多个值,使用列表、元组、字典、集合将多个值“存起来”即可
返回多个值,会将返回值的值打包成 一个元组。
定义一个函数,返回100 ~ 999之间的所有的水仙花数字。 水仙数数字有 4个:
python">def flower():# 定义一个列表,记录水仙花数字ls = []# 编写功能,找到这四个水仙花数字for number in range(100, 1000):g = number % 10s = (number // 10) % 10b = number // 100# 判断是不是水仙花数字if number == g**3 + s**3 + b**3:ls.append(number)# 出了循环以后,ls里面的内容就是4个水仙花数字a, b, c, d = ls[0], ls[1], ls[2], ls[3]return a, b, c, d# 接收函数的返回值 value1, value2, value3, value4 = flower() print(f"{value1}, {value2}, {value3}, {value4}")#153, 370, 371, 407result = flower() print(f"result : {result}")#result : (153, 370, 371, 407)
四、全局变量和局部变量
4.1、全局变量
在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始直到模块结束。
全局变量降低了函数的通用性和可读性。应尽量避免全局变量的使用。
global关键字作用: 声明使用的变量属于全局变量
global一般在函数的内部使用。
python">a = 100 #全局变量
def f1():global a #如果要在函数内改变全局变量的值,增加global关键字声明print(a) #打印全局变量a的值 a = 300 f1()#100
f1()#300
print(a)#300
4.2、局部变量
在函数体中(包含形式参数)声明的变量。
局部变量的引用比全局变量快,优先考虑使用
如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量
python">a=100
def f1():a = 3 #同名的局部变量print(a)f1()#3
print(a) #a仍然是100,没有变化
4.3、局部变量和全局变量效率测试
局部变量的查询和访问速度比全局变量快,优先考虑使用,尤其是在循环的时候。
在特别强调效率的地方或者循环次数较多的地方,可以通过将全局变量转为局部变量提高运行速度。
python">import time
a = 1000
def test01():start = time.time()global afor i in range(100000000):a += 1end = time.time()print("耗时{0}".format((end-start)))
def test02():c = 1000start = time.time()for i in range(100000000):c += 1end = time.time()print("耗时{0}".format((end-start)))
test01()#耗时6.526300430297852
test02()#耗时5.019754648208618
print(globals())