Ⅳ 函数与代码复用

第 6 章. 函数与代码复用

看下面一段伪代码:

	if cpu使用率 >80%:
连接邮箱
发送邮件
关闭邮箱
if 内存使用率 >80%:
连接邮箱
发送邮件
关闭邮箱
if 硬盘使用率 >80%:
连接邮箱
发送邮件
关闭邮箱

思考这段代码有什么问题?

 

1⃣️  函数的概念

函数是一段具有特定功能的,可重用的语句组,用函数名来表示并通过函数名进行完成功能调用。

函数也可以看作是一段具有名字的子程序,可以在需要的地方调用执行,不需要再在每个执行地方重复编写这些语句。每次使用函数可以提供不同的参数作为输入,以实现对不同数据的处理;函数执行后,还可以以反馈相应的处理结果。

函数是一种功能抽象。

 

 

2⃣️  python中函数的定义

Python 定义一个函数使用 def 关键字,语法形式如下:

def <函数名>(<参数列表>):

<函数体>

return <返回值列表>

函数名的命名规范:只能由数字字母下划线组成,不能用数字开头
命名风格:尽量简短、见名知意,推荐使用下划线命名法(每个单词之间用下划线连接)
注意点:不能和python中的关键字重名,也不要和python中的内置函数重名(如果重名会覆盖内置函数)

实例:生日歌

过生日时要为朋友唱生日歌,歌词为:

Happy birthday to you!

Happy birthday to you!

Happy birthday,dear<名字>

Happy birthday to you!

编写程序为 Mike 和 Lily 输出生日歌。最简单的方式是重复使用 print() 语句

# 最简单的方式
print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Mike!')
print('Happy birthday to you!')

print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Lily!')
print('Happy birthday to you!')

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!
Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Lily!
Happy birthday to you!
以函数的方式

# 定义函数
def happy():
print('Happy birthday to you!')

def happy_birthday(name):
happy()
happy()
print('Happy birthday, dear {}!'.format(name))
happy()

# 调用函数
happy_birthday('Mike')
print()
happy_birthday('Lily')

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Lily!
Happy birthday to you!
看起来感和上面的直接 print 还多了几行代码,但是考虑如果要给 100 个人唱生日歌的情况。

 

 

函数的注释

①函数的注释 与 普通的注释有一定的区别,他描述函数用来做什么,参数的含义,是否有返回值

 

函数用来做什么?

:param 参数的诠释 

:return 函数的返回结果

 

这样在调用函数时,能更加直观的去理解函数的参数含义以及函数的返回值含义

 

 

②调用函数时鼠标移上函数可以看到函数的注释

(补图)

 

③打印函数的注释信息:print(函数.__doc__)

 

⭐ 也可以用 ctrl + 左键点击进入函数查看(mac : command + 左键 )

 

3⃣️  函数的调用过程

①函数的调用:函数名()

 

程序调用一个函数需要执行以下四个步骤:

  1. 调用程序在调用处暂停执行

  2. 在调用时将实参赋值给函数的形参

  3. 执行函数体语句

  4. 函数调用结束给出返回值,程序回到调用前的暂停处继续执行

上面的 happy_birthday 函数的调用过程

image.png

 

 

image.png

 

 

image.png

 

②函数的嵌套 

1)一个函数内可以直接调用另一个函数

# ①函数的嵌套调用
def fun1():
print("桃花开了")


def fun2():
  print("梅花开了")
  fun1() # 调用fun1函数


fun2()


梅花开了

桃花开了

 

2)函数相互调用会死循环

def fun1():
print("桃花开了")
  fun2()


def fun2():
  print("梅花开了")
  fun1() # 调用fun1函数

3)python中 函数内可以定义函数,也可以直接调用

# ②函数的嵌套定义与调用
def fun3():
  print("今天天气真好~~")

  def fun4():
    print("可以去踏青了~~")

  fun4() # 嵌套调用fun4函数
  print("调用fun3会打印几句话?")

fun3()


 

今天天气真好~~

可以去踏青了~~

调用fun3会打印几句话?

 

4)断点调试

 

 

4⃣️  函数的返回值:return

4.1)返回值

函数还有一个很重要的功能就是返回结果。

python 中使用 return 关键字来退出函数,返回到函数被调用的地方继续往下执行。

return 可以将 0 个,1 个,多个函数运算完的结果返回给函数被调用处的变量。

函数可以没有返回值,也就是说函数中可以没有 return 语句,这时函数返回 None,例如上面我们定义的那些函数。

None - 调用函数并将函数值打印出来 - 结果为None

 有返回值 - 调用函数,并将函数值打印出来 - return后的结果

 

 

 

return 会将多个返回值以元组的形式返回。

案例:

定义一个函数接收 2 个或多个数值,并返回它们的和。

def add(x,y,*args):
x += y
for i in args:
x += i
return x

res = add(1,2)
print(res)

3
定义一个函数接收被除数 x 和除数 y,返回它们的商和余数。

def my_mod(x,y):
res1 = None
res2 = None
if x < y:
res1 = x
res2 = 0
else:
i = 0
while x >= y:
x = x-y
i += 1
res1 = i
res2 = x

return res1, res2
res = my_mod(10,3)
print(res)

(3, 1)

 

⭐如果return多个结果可以用多变量接收

 

⭐如何获取函数的返回结果,也就是return的值

方法一:定义变量接收值


a = my_mod(10,3)
print(a)

方法二:直接用print()打印函数调用的结果


print(my_mod(10,3))


 

5️⃣  函数的参数

定义函数时 () 里的参数叫形参(形式参数),它只是一个变量名,供函数体中的代码调用。

函数调用时,传入 () 里的参数叫实参(实际参数),它是实际的数据,会传递给形参,供函数体执行。

5.1)形参

定义函数时,形参根据功能不同,可以定义几种类型。

5.1.1 必须参数

在定义函数时,如果要求调用者必须传递实参给这个形参,它就是必须参数。

定义了几个,调用函数时就要传几个。

直接定义在函数名后的 () 中的形参就是必须参数。

例如上面的 happy_birthday 函数中的 name

案例:

定义一个函数接收两个数,然后打印它们的和

def add(x,y):
print(x+y)
add(1) # 调用时必须传递实参给必须参数,否则报错

TypeError Traceback (most recent call last)

in
----> 1 add(1) # 调用时必须传递实参给必须参数,否则报错

TypeError: add() missing 1 required positional argument: 'y'

 

 

5.1.2 默认参数(缺省参数)

在定义函数时,某些形参有可能在调用时不用接收实参,这种情况可以定义为默认参数。

在函数名后 () 中,以 参数名=默认值 的形式定义的形参就是默认参数。

注意:默认参数必须定义在必须参数的后面

案例:

定义一个函数,它接收两个参数 content 和 times,

content 是函数要打印的内容

times 是函数打印的次数,如果不传递 times 默认打印 1 次

# 定义
def my_print(content, times=1):
for i in range(times):
print(content)
# 调用
my_print('happy birthday!')
my_print('happy birthday!', 2)

happy birthday!
happy birthday!
happy birthday!
调用函数时传递实参给默认形参会覆盖默认值。

⭐  1.有默认值的参数,在定义的时候一定要写到最后面

      2.如果两种 传参形式 混合使用,位置参数写前面,指定参数名传参写后面

      3.如果两种 传参形式 混合使用,同一参数不能传递两次

 

 

5.1.3 不定参数

在定义函数时,不确定在调用时会传递多少个实参时,可以定义不定参数。

不定参数根据传递实参的不同(详见 4.2 实参)有分为两种。

位置不定参

在函数名后的 () 中,在形参前加 * 号可以定义位置不定参,通常它会定义为 *args

它用来接收函数调用时,以位置参数传递过来的超过形参数量的多余的实参。

注意:不定参必须定义在默认参数后面【❄不一定要放在最后,放在何处,前面的参数接收完剩下的都归他。】

位置不定参数会将所有多余的位置实参创建成元组。

def func(a, *args):
print(args,type(args))

func(1,2,3,4)

(2, 3, 4) <class 'tuple'>

 

 

 

案例:

定义一个函数,接收 2 个以上的数,打印它们的和。

def add(x,y,*args):
x += y
for i in args:
x += i
print(x)
add(1,2,3,4)

10

 

关键字不定参

在函数名后的 () 中,在形参前加 ** 号可以定义关键字不定参,通常它会定义为 **kwargs

它用来接收函数调用时,以关键字参数传递过来的超过形参数量的多余的实参。

注意:不定参必须定义在默认参数后面

关键字不定参数会将所有多余的关键字实参创建成字典。

def func(a, **kwargs):
print(kwargs,type(kwargs))

func(a=1,b=2,c=3,d=4)

{'b': 2, 'c': 3, 'd': 4} <class 'dict'>

 

⭐可以打印,打印要去星花

 

 

 

5.2)实参

调用函数时传递实参有两种方式。

5.2.1 位置参数

调用函数时,传递实参时默认会按照形参的位置一一对应,这种实参传递叫做位置参数。

案例

定义一个函数实现打印一个数的 n 次幂。

def my_power(x, n):
print(x**n)

my_power(3,2)
my_power(2,3)

9
8

 

5.2.2 关键字参数(指定参数)

调用函数时,传递实参时以 形参名=实参 的形式传递参数,叫做关键字参数。

这时不用考虑参数的位置。

注意:关键字参数必须写在位置参数后面。

案例

使用关键字参数调用上面的案例

my_power(x=3,n=2)
my_power(n=2,x=3)
my_power(3,n=2)

9
9
9

my_power(n=2,3)

File "", line 1
my_power(n=2,3)
^
SyntaxError: positional argument follows keyword argument

 

5.2.3 *,** 在传递实参时的用法

* 解包

在传递实参时,可以通过 * 对迭代对象列表、元组进行解包。

def fun(a,b,*arg):
print(a,b,arg)
ls = [1,2,3,4,5,6]
fun(*ls) # => fun(1,2,3,4,5,6) ⭐=>fun(ls[0],ls[1],ls[2],ls[3],ls[4],ls[5])

1 2 (3, 4, 5, 6)

 

⭐ * 表示传入的是元组

def fun1(*args):
  print(args)
  print(type(args))
  print(args[0])
fun1(1, 2, 3, 4, 5)





(1, 2, 3, 4, 5)

<class 'tuple'>

1

 

** 解包

在传递实参时,可以通过 ** 对字典对象进行解包。

def fun(a,b, **kwargs):
print(a,b,kwargs)
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
fun(**d) # => fun(a=1,b=2,c=3,d=4)

1 2 {'c': 3, 'd': 4}

 

⭐ ** 表示传入的是一个字典

 

def fun2(**kwargs):
  print(kwargs)
  print(type(kwargs))
  print(kwargs["name"])

fun2(name="花花",addr="长沙")



{"name":"花花", "addr":"长沙"}
<class 'dict'="">
花花
 

 

 

练习

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 5.

"""
实现学生管理系统,完成对学员的增,删,改,查和退出学生管理系统。
要求1:使用一个list用于保存学生的姓名。
要求2:输入0显示所有学员信息,1代表增加,2代表删除,3代表修改,4代表查询,exit代表退出学生管理系统。每一个功能定义一个自定义函数。界面如下:
系统界面如下:
-----------------------欢迎进入V220班学生管理系统-----------------------------
请选择系统功能:
0:显示所有学员信息
1:添加一个学员信息
2:删除一个学员信息
3:修改一个学员信息
4:查询一个学员信息
exit:退出学生管理系统


(0)输入0后效果如下:
0
["那棵草","下个路口见"..]

(1)输入1后效果如下:
1
请输入增加人的姓名:南一
["那棵草","下个路口见",'南一'..]

(2)输入2后效果如下:
2
请输入删除人的姓名:南一
["那棵草","下个路口见"..]

(3)输入3后效果如下:<注意:如果list中没有这个学员则打印:V217班没有这个学员>
3
请输入需要修改人的姓名:下个路口见
请输入需要修改后的姓名:小蓝紫
["那棵草","小蓝紫"..]

(4)输入4后效果如下:<注意:如果list中没有这个学员则打印:V217班没有这个学员>
请输入查询人的姓名:那棵草
那棵草在座位号(0<下标>)的位置。

(5)输入exit后效果如下:
exit
欢迎使用V220的学生管理系统,下次再见。
"""

 

 


mylist = ["那棵草","下个路口见"]
str1 = """
-----------------------欢迎进入V220班学生管理系统-----------------------------
请选择系统功能:
0:显示所有学员信息
1:添加一个学员信息
2:删除一个学员信息
3:修改一个学员信息
4:查询一个学员信息
exit:退出学生管理系统
"""
def getallinfo():
print("所有学员信息:",mylist)
caozuo(input(str1+"请输入你的选择:"),mylist)

def addinfo():
name = input("请输入增加人的姓名:")
if name in mylist:
print("{}名字已存在,请添加不同的名字".format(name))
else:
mylist.append(name)
print("新增学员后的信息:",mylist)
caozuo(input(str1+"请输入你的选择:"), mylist)

def delinfo():
delname = input("请输入要删除人的姓名:")
if mylist.count(delname)>0:
mylist.remove(delname)
print("删除学员后的信息:",mylist)
else:
print("V217班没有这个学员!")
caozuo(input(str1+"请输入你的选择:"), mylist)

def updateinfo():
oldname = input("请输入要修改人的姓名:")
newname = input("请输入要修改后的姓名:")
if mylist.count(oldname)>0:
mylist[mylist.index(oldname)] = newname
print("修改后的学员信息:",mylist)
else:
print("V217班没有这个学员!")
caozuo(input(str1+"请输入你的选择:"), mylist)

def selectinfo():
selectname = input("请输入要查询人的姓名:")
if mylist.count(selectname)>0:
print("{}在座位号({}<下标>)的位置。".format(selectname,mylist.index(selectname)))
else:
print("V217班没有这个学员!")
caozuo(input(str1+"请输入你的选择:"), mylist)

def caozuo(num,mylist):
if num == "0":
getallinfo()
elif num == "1":
addinfo()
elif num == "2":
delinfo()
elif num == "3":
updateinfo()
elif num == "4":
selectinfo()
elif num == "exit":
print("欢迎使用V220的学生管理系统,下次再见。")
else:
print("输入不正确,请重新输入!")
caozuo(input(str1+"请输入你的选择:"),mylist)



caozuo(input(str1+"请输入你的选择:"),mylist)

 

 

6️⃣  lambda 函数

简单来说,lambda 函数用来定义简单的,能够在一行内表示的函数。

语法格式如下:

lambda 参数:逻辑
lambda arg1,arg2,... : expression
案例
f = lambda x,y : x + y
res = f(1,2)
print(res)

3
lambda 函数一般不会直接定义,通常是作为参数传递给其他函数作为参数使用。

 或

res = (lambda x,y : x+y)(1,2)
res = (函数)(传参)

⭐:前定义函数参数,:后是返回值 

⭐ :打印圆周率

 import math

p = math.pi
print(p) # 可以打印圆周率


 ⭐:函数的本体

res = lambda r:pow(r,2) * math.pi
print(res) # 打印函数的本体,函数所在的内存地址
print(res(r=5))

⭐:普通函数 - 匿名函数(+内置函数) - 结合函数

 

 

 1. 序列调用匿名函数

 

 

 

 2. 内置函数map使用

 

 

 

 3. 匿名函数在自动化中的使用

 

 

 

 

 

7️⃣  变量作用域

python 中一个变量能够被访问的范围叫做作用域。根据作用域的大小简单的分为全局变量和局部变量。

7.1)全局变量

python 是解释型编程语言,解释器在运行一个 python 程序时会在计算机内存中申请一块内存用来运行这个程序。全局变量在这块内存空间中都可以被访问和修改。

直接定义在函数外的变量就是全局变量,在程序运行的全过程有效。

 

7.2)局部变量

定义在函数里的变量就是局部变量,它只在它定义的函数里起作用,一旦函数执行完毕它就不存在了。

⭐一个模块就是一个.py文件

image.png

 

 

案例

a = 1 # 全局变量

def fun():
print(a)
fun()

1
①上面的案例说明全局变量能够在函数里访问。
image.png

 

②全局变量也能在函数外访问

def fun():
b = 2 # 局部变量
print(b)

fun()
print(b)

2


NameError Traceback (most recent call last)

in
4
5 fun()
----> 6 print(b)

NameError: name 'b' is not defined
③上面的案例说明局部变量在函数外部不能直接访问

 

⭐ ④函数外部可以直接修改全局变量
a = 100
a = a + 200
print(a)

*****************************************************************

a = 1
def fun():

a += 1 # 尝试直接在函数内部修改全局变量
print(a)
fun()

UnboundLocalError Traceback (most recent call last)

in
4 a += 1 # 尝试直接在函数内部修改全局变量
5 print(a)
----> 6 fun()

in fun()
2 def fun():
3
----> 4 a += 1 # 尝试直接在函数内部修改全局变量
5 print(a)
6 fun()

UnboundLocalError: local variable 'a' referenced before assignment
⑤上面的案例说明在函数内部不能直接修改全局变量(不可变数据类型)

 

⑥可变数据类型的动态添加或删除等修改数据不受影响(⭐因为没有改变全局变量指向的内存地址),所以可变类型的全局变量在使用的过程中需要格外的注意

a = [1,2]
def func():
a[0] = 2
print(a)
func()
print(a)

[2, 2]
[2, 2]

 

7.3)global 关键字

函数外部可以修改全局变量。

有时候需要在函数内部修改全局变量。

⑦使用 globals 关键字可以在函数内部修改全局变量

案例1:

a = 1 # 全局变量

def fun():
# global要放在第一行
global a # 申明 a 是全局变量
  
    global b # 全局变量要先声明,后定义
b = 4

a += 1
fun()
print(a)
print(b)

2

4

 

 案例2:

a = 1 # 全局变量

def fun():
# global要放在第一行
global a # 申明 a 是全局变量
  
    global b # 全局变量要先声明,后定义
b = 4

a += 1


print(b) # 先print b 再调用函数,会报错,因为b没有先定义,函数的执行逻辑:从上往下,由内而外
fun()

 

 

7.4)变量访问优先级

⑧函数内部访问变量,优先查找局部变量,如果局部变量中没有,才会引用全局变量。

⭐因为自定义的函数,在当前模块中优先级高于内置函数,所以自定义的函数和内置函数重名会覆盖掉内置函数

 

 

8️⃣  python 内建函数

python 解释器提供了 70 多个内置函数。
⭐小写的就是全局内建函数和类

 

 

 

8.1)基本数据类型类(转换函数)

8.1.1 int

  • int([x]) -> integer

  • int(x, base=10) -> integer

将一个数字或字符串转换成整数。
如果 x 不是一个数字,那么它必须是和 base 匹配的整数字符串表达式

int(1.1)

1

int('1')

1

int('0b0101',2)

5

int('0x11',16)

17

int('0o11',8)

9

 

8.1.2 float

将一个字符串或数字转换为浮点数。

float(123)

123.0

float('1.2')

1.2

判断是否浮点数:

print(isinstance(1.0, float))

True

 

8.1.3 complex

  • complex(real=0, imag=0)
    创建一个复数通过实部和虚部

complex(10,8)

(10+8j)

 

8.1.4 str

  • str(object='')
    通过给定的对象创建一个新的字符串对象。

str(1)

'1'

str([1,2,3])

'[1, 2, 3]'

str({'name':'xinlan'})

"{'name': 'xinlan'}"

 

8.1.5 list

  • list(iterable=())

根据传入的可迭代对象创建一个列表,如果没有参数返回空列表

list()

[]

list(range(10))

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

list('abcde')

['a', 'b', 'c', 'd', 'e']

 

8.1.6 tuple

  • tuple(iterable=())

根据传入的可迭代对象创建一个元组,如果没有参数返回空元组

tuple()

()

tuple('abcd')

('a', 'b', 'c', 'd')

 

8.1.7 set

  • set(iterable)

根据传入的可迭代对象创建一个集合对象。

set('abc')

{'a', 'b', 'c'}

set(range(10))

{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

 

8.1.8 dict

根据传入的参数创建一个字典对象

# 形如(key, value)的键值对数据
dict([('name','xinlan'),('age',18)])

{'name': 'xinlan', 'age': 18}

# 关键字参数
dict(name='xinlan',age=18)

{'name': 'xinlan', 'age': 18}

 

8.1.9 bool

bool()

 

 

8.2)常用内建函数_1

8.2.1 print

  • print(value,..,sep=' ', end='\n')

    • value 会打印 value 的字符串形式

    • sep 分隔符,当有多个 value 时默认用空格作为分割

    • end 每次打印在最后默认添加回车换行符

打印传入对象的字符串形式

print(1,2,3,sep=',')

1,2,3

print(1,end='')
print(2)

12

 

8.2.2 input

接收用户的输入数据,以字符串的形式返回。

可以接收字符串参数作为提示信息输出

input('>>>:')

:aaa

'aaa'

 

8.2.3 type

  • type(object)

返回 object 的类型

type(1)

int

 

 

8.2.4 dir

  • dir([object])

返回传入对象的所有属性和方法名的列表

 

 

8.2.5 help

  • help(builtins.object)

返回内建对象的帮助信息

help(help)

Help on _Helper in module _sitebuiltins object:

class _Helper(builtins.object)
| Define the builtin 'help'.
|
| This is a wrapper around pydoc.help that provides a helpful message
| when 'help' is typed at the Python interactive prompt.
|
| Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object 'thing'.
|
| Methods defined here:
|
call(self, *args, kwds)
| Call self as a function.
|
repr**(self)
| Return repr(self).

 
Data descriptors defined here:
 
dict
dictionary for instance variables (if defined)
 
weakref
list of weak references to the object (if defined)

 

 

8.2.6 len

  • len(obj)

返回容器的元素个数

len([1,2,3])

3

 

8.2.7 hash

  • hash(obj)

返回对象的 hash 值

hash('a')

3636161774609400683

 

8.2.8 iter

  • iter(iterable)

根据传入的可迭代对象返回一个迭代器

iter('abcd')

<str_iterator at 0x7f98b7dd2eb0>

 

8.2.9 id

  • id(obj)

返回传入对象的身份 id(虚拟内存地址的整数形式)

id(1)

4344134656

 

8.2.10 range

  • range(stop) -> range object

  • range(start, stop[,step])

返回一个 range object 对象,产生整数序列

range(10)

range(0, 10)

range(0,10,2)

range(0, 10, 2)

更多方法详见官方文档

Python 标准库

 

8.3)常用内建函数_2

8.3.0 数学函数

abs()       绝对值                          

divmod() 返回商和余数

round()    四舍五入(银行家算法)

pow()       次方

sum()       求和

min()        最小值

max()       最大值

 

 

 

 

 

8.3.1 min

min((1,2,3,4,5))
min([1,2,3,4,5])

8.3.2 max

max((1,2,3,4,5))
max([1,2,3,4,5])

8.3.3 sum

sum((1,2,3,4,5))
sum([1,2,3,4,5])
sum(dic.values())

8.3.4 eval

识别字符串中有效的python表达式

 

 

 

 

 

 

8.3.5 zip

聚合打包

 

 

⭐以索引相组合,以最短的列表为基,进行聚合

案例

 

 

 

 

练习

 

 

 

 

 

 

 

1.写函数,接收两个数字参数,返回最大值
例如:
传入:10,20
返回:20

 

def get_max(a,b):
mmax = a
if b>a:
mmax = b
return mmax

def getmax(*args):
lst = []
for i in args:
lst.append(i)

return max(lst)

print(getmax(*(1,2,3,4,5,6)))
print(get_max(1,2))

2.写函数,获取传入列表的所有奇数位索引对应的元素,并将其作为新列表返回。
例如:
传入:[34,23,52,352,352,3523,5]
返回:[23,352,3523]

 

def x(*args):
return args[1::2]


print(list(x(*[34,23,52,352,352,3523,5])))


def getnewlist(mylist):
list1 = []
for i in range(0,len(mylist)):
if i%2!=0:
list1.append(mylist[i])
return list1
print(getnewlist([34,23,52,352,352,3523,5]))



3.写函数,判断用户传入的对象(列表)长度是否大于5,如果大于5,那么仅保留前五个长度的内容并返回。不大于5返回本身。
例如:
传入1:[34,23,52,352,666,3523,5] 返回1:[34,23,52,352,666]
传入2:[34,23,52] 返回2:[34,23,52]

 

def f(*args):
if len(args)>5:
return args[:5]
else:
return args

print(list(f(*[34,23,52,352,666,3523,5] )))
print(list(f(*[34,23,52] )))


def get5len(mylist):
list1 = []
if len(mylist)>5:
for x in range(5):
list1.append(mylist[x])
else:
list1=mylist
return list1

print(get5len([34,23,52,352,666,3523,5] ))
print(get5len([34,23,52] ))

4.写函数,检查传入的字符串是否含有空格,并返回结果,包含空格返回True,不包含返回False
例如:
传入:"hello world"
返回:True

def isstrip(str1):
a = False
for x in str1:
if x==' ':
a = True
break
return a

print(isstrip("hello world!"))


5.写函数,接收n个数字,分别写4个函数求n数字的和、差、商、积

 

def sum1(*args):
res = 0
for n in args:
res += n
return res

def sub1(num1,*args):
res = num1
for n in args:
res -= n
return res

def mult(*args):
res = 1
for n in args:
res *= n
return res

def div1(num1,*args):
res = num1
for n in args:
res /= n
return res



 

 9️⃣  装饰器

1. 函数的传递

python中可以把函数当作变量传递

def fun1():
  print("执行了fun1函数") 

def fun2(fun_name):
  print("我是第二个函数的打印")
  fun_name() # 等同于fun1()


fun2(fun_name=fun1)
# fun2(fun_name=fun1()) # 报错(先执行fun1()完成打印,再把fun1()执行的结果None传给了fun_name,fun_name=None,那么fun_name() = None())

 

⭐函数的调用与引用:

调用:在函数后面加一个小括号()  -- 语法,就是在执行对应的函数,跑函数里面的代码

引用:不加小括号,直接写函数命,这叫函数的本体

 

 2. 函数的嵌套

 

 ⭐ python中一个函数的内部还可以定义函数

 

 

 

3. 装饰器

 

 

简化掉所有流程,只要遇到@符号,就去找同名函数,如果有的话就先去执行同名函数

装饰器是针对函数执行的增强,增强:就是在函数执行的前面或后面插入一段代码

 

装饰器的语法规则:在函数头上加 @装饰器名称

目的:对原来定义好的方法(函数)进行增强

 

import logging

logging.basicConfig(level=logging.DEBUG)


def log_info(fun_name):
def wra():
logging.info('执行内部函数')
return fun_name() # 返回fun_name参数本体
     # ②return fun_name

return wra # 返回了wra函数本体

@log_info
def fun5():
print("fun5函数执行了。。。")


fun5()
# ②fun5()() # 没有人用

 

结果:

INFO:root:执行内部函数
fun5函数执行了。。

 

 

# 写了@log_info后,会默认把fun5当作参数传递给log_info,会默认去调用wra,这是装饰器的规则

 

# 执行fun5()函数,在执行之前,通过装饰器完成日志的打印,再去执行它

 

⭐ 装饰器真正的原理(原则)

 

 案例:

① 案例

 

②被装饰函数-带参

 

 

 练习:

1.请实现一个装饰器,把函数的返回值+100然后返回

 

def fun1(value):
def warpper(value):
ret = print(value+100)
return ret

return warpper

@fun1
def fun(num):
print("函数执行加100操作")


fun(5)

2.请实现一个装饰器,通过一次调用使函数重复执行5次

 


def fun2(value):
def warpper(*args,**kwargs):
for i in range(5):
value(*args,**kwargs)

return warpper

@fun2
def fun():
print("重复执行函数")


fun()

3.请实现一个装饰器,每次调用函数时,将函数名字以及调用此函数的时间点写入文件中

import time

def fun3(value):
def warpper(*args,**kwargs):
with open(r'D:\AutoTest\P_test\txt1',encoding='utf-8',mode='a+') as f:
stime = time.localtime()
f.write("时间:{} 函数名:{}\n".format(time.strftime("%Y-%m-%d %H-%M-%S",stime),value.__name__))
print("时间:{} 函数名:{}".format(time.strftime("%Y-%m-%d %H-%M-%S",stime),value.__name__))
ret = value(*args,**kwargs)
return ret
return warpper

@fun3
def fun():
print("执行")


fun()

4.判断函数中被传入的数据类型——

# 编写装饰器,条件如下:

#1)确保函数接收到的每一个参数都是证书;

#2)如果参数不是整型数,打印TypeError:参数必须为整型(提示。。。)

如:if not isinstance(i,int):

# print('函数所有的参数并非都是int型')

def wapper(value):
def inner(*args,**kwargs):
for i in args:
if not isinstance(i,int):
print('函数不是int型')
break
else:
res = value(*args,**kwargs)
print("函数是int型")

return res
return inner

@wapper
def fun(num):
return num

fun(34.3)


 







posted @ 2022-11-06 18:54  千秋与  阅读(12)  评论(0编辑  收藏  举报