Python——函数及递归

news/2024/11/25 9:34:31/

Python

  • Python
    • 一、补充循环结构
      • for循环:
    • 二、函数
      • 1、函数(function)
      • 2、调用函数:
      • 3、函数的分类:
      • 4、局部变量和全局变量:
      • 5、函数在内存中调用问题
      • 6、值传递和引用传递:
      • 7、函数的参数
      • 8、函数传递
      • 9、匿名函数以及lambda表达式
      • 10、偏函数
    • 三、递归
      • 递归的内存分析以及优缺点
    • 四、容器
    • 五、作业:
    • 作业1
    • 作业2:
    • 作业3:
    • 作业:
    • 作业5:
    • 作业6:
    • 作业7:
    • 作业8:
    • 作业9:
    • 作业10:
    • 作业11:
    • 作业12:
    • 作业13:
    • 作业14:

Python

一、补充循环结构

for循环:

由于while只能通过下标进行循环,不过有些容器是没有下标的,不能用while循环。
所以设计出来了for循环,Python中的for本质是用来迭代容器中的每一个元素的!!!

而不是在C,Java理解的那个循环。
列表[]:和数组有点像,不过更像是数据结构中的list。
里面可以包含多个元素。
我们来看下具有下标的:

>>> ["1","2","3"]
['1', '2', '3']
>>> users = ['1','2','3']
>>> users
['1', '2', '3']
>>> users[1]
'2'
>>> users[0]
'1'
>>> users[2]
'3'

首先我们在users中存储了三个元素。
接下来我们使用循环将其进行输出:

>>> len(users)
3
>>> i = 0
>>> while i < len(users):
...     print(users[i])
...     i += 1
...
1
2
3
>>>

此时是具有下标的情况,而我们往往在之后不知道元素具体的位置,我们又该怎么办呢?比如说哈希表。
这时我们引入了for循环,当然for循环我们可以在有序中使用也可以在无序中使用。

简单来演示下for循环的使用方法:

for 临时变量 in(所属运算符) 容器 :print(临时变量)    #每一个迭代出来的元素

例如:

>>> for user in users:
...     print(user)
...
1
2
3
>>>

range全局函数:
range(nujm) ** #[0,num)区间内的所有整数**
我们实际操作来观察下:

>>> range(10)
range(0, 10)
>>> for i in range(10):
...     print(i)
...
0
1
2
3
4
5
6
7
8
9
>>>

range(start , end) #[start,end)区间内的所有整数
比如说我们要求10到20之间的数的和包含10以及20
实现代码:

>>> s = 0
>>> for i in range(10,21):
...     s += i
...
>>> s
165
>>>

那如果说我们要求10到20包含10但不包含20:

>>> s = 0
>>> for i in range(10,20):
...     s += i
...
>>> s
145
>>>

这个就是关于两个参数。
那如果我们要三个参数的,比如1,3,5······
range(start,end,step) #默认步长是1,但是可以通关第三个参数修改步长那个。

比如我们接下来求0到100的偶数:

>>> for x in range(0,101,2):
...     print(x)
...
0
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
50
52
54
56
58
60
62
64
66
68
70
72
74
76
78
80
82
84
86
88
90
92
94
96
98
100
>>>

步长可以填负数,那便是自减。

比如我们求1到100的和:
方法一:

>>> s = 0
>>> for i in range(101):
...     s += i
...
>>> s
5050

方法二:

>>> s = 0
>>> for i in range(100,0,-1):
...     s += i
...
>>> s
5050
>>>

接下来我们使用for循环进行打印:
题目1:
*
**
***
****
*****
实现代码:

layer = int(input("请输入您要打印的层数"))for i in range(1,layer + 1):for j in range(i):print("*",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数5
*
**
***
****
*****D:\soft\pythonworkplace>

题目2:
*
***
*****
*******
*********
实现代码:

layer = int(input("请输入您要打印的层数:"))for i in range(layer):for j in range(2 * i + 1):print("*",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:5
*
***
*****
*******
*********D:\soft\pythonworkplace>

题目3:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))for i in range(1,layer + 1):space_name = layer - ifor j in range(space_name):print(" ",end = "")for j in range(i):print("*",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:5**********
*****D:\soft\pythonworkplace>

这道题同样可以进行简化代码:

layer = int(input("请输入您要打印的层数:"))
for i in range(1,layer + 1):print(" " * (layer - i),end = "")print("*" * i)

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:6***************
******D:\soft\pythonworkplace>

题目4:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))for i in range(1, layer + 1):for j in range(layer - i):print(" ",end = "")for j in range(2 * i - 1):print("*",end = "")print()

输出结果

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:5****************
*********D:\soft\pythonworkplace>

题目5:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))for i in range(layer,0,-1):for j in range(layer - i):print(" ",end = "")for j in range(2 * i - 1):print("*",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:5
*************************D:\soft\pythonworkplace>

题目6:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))while layer % 2 == 0:layer = int(input("请输入奇数行"))
for i in range(0,layer // 2 + 1):print(" " * (layer - i),end = "")print("*" * (2 * i + 1))
for i in range(layer // 2,0,-1):print(" " * (layer - i + 1),end = "")print("*" * (2 * i - 1))

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:11*************************************************************D:\soft\pythonworkplace>

题目7:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))while layer % 2 == 0:layer = int(input("请输入奇数行"))
for i in range(0,layer // 2 + 2):print(" " * (layer - i),end = "")for j in range(2 * i + 2):if j == 0 or j == 2 * i:print("*",end = "")else:print(" ",end = "")print()
for i in range(layer // 2,-1,-1):print(" " * (layer - i),end = "")for j in range(2 * i + 1):if j == 0 or j == 2 * i:print("*",end = "")else:print(" ",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:11** **   **     **       **         **           **         **       **     **   ** **D:\soft\pythonworkplace>

题目8:

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

实现代码:

layer = int(input("请输入您要打印的层数:"))while layer % 2 == 0:layer = int(input("请输入奇数行"))
for i in range(0,layer // 2 + 2):print(" " * (layer - i),end = "")for j in range(2 * i + 1):if j == 0 or j == 2 * i or j == i or i ==layer // 2 + 1:print("*",end = "")else:print(" ",end = "")print()
for i in range(layer // 2,-1,-1):print(" " * (layer - i),end = "")for j in range(2 * i + 1):if j == 0 or j == 2 * i or j == i:print("*",end = "")else:print(" ",end = "")print()

输出结果:

D:\soft\pythonworkplace>test.py
请输入您要打印的层数:11***** * **  *  **   *   **    *    ***************    *    **   *   **  *  ** * *****D:\soft\pythonworkplace>

二、函数

1、函数(function)

1.1 什么叫做函数?
编程看来,函数其本质就是一个功能代码的集合。
函数本质就是现实中行为动作的代名词;
具有名称的功能代码的集合
1.2 python中函数如何定义:
使用关键字def【该关键字就是用来定义函数的】
defined function

def 函数名称([参数列表...]):# 函数体 由一行或者多行代码组成# [return 返回值]

1.3 案例:
在控制上输出三句你好
实现代码:

# 实现一个函数,在控制台上输出你好
def say_hello():print("你好")print("你好")print("你好")

输出结果:

D:\soft\pythonworkplace>test.pyD:\soft\pythonworkplace>

1.4 这里我们又为什么没有输出结果呢?

这里我们可以把函数理解为功能,这里它的功能也就是输出三句你好;然则你也可以有很多的功能;但是,功能的实现我们肯定是建立在需求之上的, 也就是我们构建了多个函数,有很多的功能,而这些功能呢?我们肯定不是每时每刻都要用到,所有函数本身是不进行执行的,同时,我们也进行学习了函数本身的功能也就是实现功能的复用

所以当函数定义完成之后我们就要进行调用函数。

2、调用函数:

[返回值 = ]函数名称([参数列表])

C:\Users\lenovo>python
Python 3.11.3 (tags/v3.11.3:f3909b8, Apr  4 2023, 23:49:59) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> help(print)
Help on built-in function print in module builtins:print(*args, sep=' ', end='\n', file=None, flush=False)Prints the values to a stream, or to sys.stdout by default.sepstring inserted between values, default a space.endstring appended after the last value, default a newline.filea file-like object (stream); defaults to the current sys.stdout.flushwhether to forcibly flush the stream.>>> print()

所以上一个案例的完整代码

# 实现一个函数,在控制台上输出你好
def say_hello():print("你好")print("你好")print("你好")# 调用函数
say_hello()

此时我们来看输出结果:

D:\soft\pythonworkplace>test.py
你好
你好
你好D:\soft\pythonworkplace>

好的,这里我们改变案例要求,我想要输出别人的基本信息,而print自己的基本信息不能进行修改;
所以此时我们可以进行改变下:

# 实现一个函数,在控制台上输出你好
def say_hello(name,age,address,gender):print(f"我叫{name}")print(f"我今年{age}岁")print(f"我是一个来自{address}{gender}")# 调用函数
say_hello()

输出结果:

D:\soft\pythonworkplace>test.py
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 573, in <module>say_hello()
TypeError: say_hello() missing 4 required positional arguments: 'name', 'age', 'address', and 'gender'D:\soft\pythonworkplace>

这里我们的很显然的可以看出我们并没有给他们传name,age,address,gender这四个值,所以:

# 实现一个函数,在控制台上输出你好
def say_hello(name,age,address,gender):print(f"我叫{name}")print(f"我今年{age}岁")print(f"我是一个来自{address}{gender}")# 调用函数
say_hello("1",16,"陕西西安","男生")
say_hello("2",17,"陕西渭南","女生")
say_hello("3",18,"陕西延安","女生")

输出结果:

D:\soft\pythonworkplace>test.py
我叫1
我今年16岁
我是一个来自陕西西安的男生
我叫2
我今年17岁
我是一个来自陕西渭南的女生
我叫3
我今年18岁
我是一个来自陕西延安的女生D:\soft\pythonworkplace>

3、函数的分类:

这里上面案例进行阐述了有参数以及没有参数的案例。
所以,下面我们来一起看下有返回值的函数:
案例要求:输出x和y的和
实现代码:

def add(x,y):return x + yadd(10,20)

这里我们可以看到输出结果:

D:\soft\pythonworkplace>test.pyD:\soft\pythonworkplace>

输出结果并没有,这又是什么原因?
我们首先来测试函数是否进行执行了:
实现代码:

def add(x,y):print("函数执行了吗")return x + yadd(10,20)

输出结果:

D:\soft\pythonworkplace>test.py
函数执行了吗D:\soft\pythonworkplace>

这里我们可以看到函数是执行了的。
这里其实已经是返回了一个结果,我们只是没有进行接收这个值,所以:

def add(x,y):return x + yres = add(10,20)
print(res)

输出结果:

D:\soft\pythonworkplace>test.py
30D:\soft\pythonworkplace>

下面我们来看下函数的分类。

  • 以函数是否存在返回值
    返回值的函数 return关键字 调用后需要接受返回值
    返回值的函数 没有return关键字 返回值为None
  • 以函数是否存在参数
    有参数函数
    无参数函数

4、局部变量和全局变量:

1、局部变量local variable):又叫做本地变量,定义在函数内部的变量
局部变量只能在当前定义的函数内部有效
2、全局变量global variable):直接定义在模块中的变量,叫做全局变量
在python中,函数内部不允许修改全局变量!!!!
3、实际练习:

# 全局变量
name = "张三"
age = 16def work_1(msg,show):# a就是一个局部变量a = 20# 全局变量可以直接在函数内部访问print(name)print(age)print(a)a += 10print(a)work_1("哦","聊天止于哦哦")

这里我们来猜想下输出结果:

D:\soft\pythonworkplace>test.py
张三
16
20
30D:\soft\pythonworkplace>

好,那么我们此时进行分步访问测试:
首先我们进行全局变量的访问:

name = "张三"
age = 16def work_1(msg,show):a = 20print(name)print(age)print(a)a += 10print(a)work_1("哦","聊天止于哦哦")print(name)
print(age)

输出结果:

D:\soft\pythonworkplace>test.py
张三
16
20
30
张三
16D:\soft\pythonworkplace>

我们可以看到我们可以在外界正常访问到全局变量;
接下来我们来访问a的值:

name = "张三"
age = 16def work_1(msg,show):a = 20print(name)print(age)print(a)a += 10print(a)work_1("哦","聊天止于哦哦")print(name)
print(age)
print(a)

输出结果:

D:\soft\pythonworkplace>test.py
张三
16
20
30
张三
16
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 600, in <module>print(a)^
NameError: name 'a' is not definedD:\soft\pythonworkplace>

我们可以看到这里只有a是没有正常访问到的,报错了。
变量a没有被定义。
下面我们接着改变案例的要求,这里要输出张三长了一岁的年龄:

name = "张三"
age = 16def work_1(msg,show):a = 20print(name)print(age)print(a)a += 10print(a)age += 1print(age)work_1("哦","聊天止于哦哦")print(name)
print(age)
# print(a)

输出结果:

D:\soft\pythonworkplace>test.py
张三
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 599, in <module>work_1("哦","聊天止于哦哦")File "D:\soft\pythonworkplace\test.py", line 590, in work_1print(age)^^^
UnboundLocalError: cannot access local variable 'age' where it is not associated with a valueD:\soft\pythonworkplace>

我们可以看到这里报错了,又是什么原因呢?
这里它的意思是找不到局部变量age。
这又是什么原因呢?
正常情况,python拒绝在函数中修改全局变量,但是考虑到特殊情况下的需求,python中如果要修改全局变量,需要提前声明!!!!
如果说我们此时加上一个局部变量age:

name = "张三"
age = 16def work_1(msg,show):age = 1a = 20print(name)print(age)print(a)a += 10print(a)age += 1print(age)work_1("哦","聊天止于哦哦")print(name)
print(age)
# print(a)

输出结果:

D:\soft\pythonworkplace>test.py
张三
1
20
30
2
张三
16D:\soft\pythonworkplace>

我们可以看到内部输出的age最后加了1,而最终输出的age值依然为我们定义的值16。
下面这个便是全局变量确实需要修改的时候,我们则需要在其使用内部加上声明global:
关键字 global 来声明

name = "张三"
age = 16def work_1(msg,show):global agea = 20print(name)print(age)print(a)a += 10print(a)age += 1print(age)work_1("哦","聊天止于哦哦")print(name)
print(age)
# print(a)

输出结果:

D:\soft\pythonworkplace>test.py
张三
16
20
30
17
张三
17D:\soft\pythonworkplace>

5、函数在内存中调用问题

a = 10def test():b = 230print("hello")test()

那么我们来猜想下电脑执行代码的过程:

内存是一个缓冲设备;
这里我们在第一节课讲到过;
内存中存在着堆以及栈,对象都是放在堆中,栈是一种线性结果,先进后出FILO以及后进先出LIFO。
与栈相对立的为队列:先进先出,后进后出。

程序为什么要建立这种结构?

首先我们来思考下我们创建执行栈而不创建执行队列?
假如我们有以下一串代码?
a = 10
b = a + 10
如果说我们创建的是队列,那么我们最终想要访问b的值,而a已经出去了,则访问不到了;栈的话则不一样,它会在执行b = a + 10之前将a = 10存进去。
然而当我们将所有的都往里面放,内存则会被撑爆了。也从而导致内存溢出。

下面我们接着分析;
在python中,函数本质也是一种对象!!!!!
对象则会存在堆里面,栈空间有限。
我们将函数的地址存在了栈中,和C中指针有点像。
程序调用的:本质就是将函数临时压入执行栈!!!
也就是我们将test函数压入栈中进行执行,当执行完最后一行代码就会立即进行弹栈操作,以避免长时间占用内存。

这里我们就可以理解为什么局部变量不能够被外面访问到,因为函数执行完毕立即弹栈,栈已经不存在局部变量的值了。

6、值传递和引用传递:

  • 值传递:变量之间,数值的传递,这种传递相当于变量赋值
  • 引用传递:传递的地址(指针),对象,引用

形参是局部变量
我们来看下面这串代码:

def change(a,b):a += 10b += 30print(a,b)x = 100
y = 200
print(x,y)
change(x,y)
print(x,y)

下面我们来看输出结果:

D:\soft\pythonworkplace>test.py
100 200
110 230
100 200D:\soft\pythonworkplace>

这里也很好理解。
a和b这里只是局部变量,我们只进行了将x以及y的值分别赋予给了a以及b,也就是值传递,函数内部修改不会影响x以及y因为这是一个值传递。
下面我们来看下一串代码:

def change(a,b):a += 10b += 30print(a,b)x = 100
y = 200
print(x,y)
change(x,y)
print(x,y)def add(nums):nums.append(100)nums.append(200)print(nums)ages = [10,20,30]
print(ages)
add(ages)
print(ages)

输出结果:

D:\soft\pythonworkplace>test.py
100 200
110 230
100 200
[10, 20, 30]
[10, 20, 30, 100, 200]
[10, 20, 30, 100, 200]D:\soft\pythonworkplace>

这里我们可以看到,我们最终将100以及200存了进去。
这又是什么原因呢?
ages在这里也就是对象,对象我们都是存放在堆中的,堆中地址则存在了栈中,而这里add则传递的是地址,也就相当于nums变量拿到的是ages的存放堆中的地址,也就相当于指向了这一变量,而这里ages则将值存了进去,那么nums也会将100以及200存到这个地址中去。

7、函数的参数

# (默认值、可变、关键字参数)
def func_name([arge...])# 函数体# [return 返回值]

练习,求圆的周长以及面积。
在这之前,我们首先知道一个东西:帮助文档:

>>> help(print)
Help on built-in function print in module builtins:print(*args, sep=' ', end='\n', file=None, flush=False)Prints the values to a stream, or to sys.stdout by default.sepstring inserted between values, default a space.endstring appended after the last value, default a newline.filea file-like object (stream); defaults to the current sys.stdout.flushwhether to forcibly flush the stream.>>>

我们一般给函数进行标注注释一般在函数的上方,而python不一样,这里必须在函数定义下面的第一行,比如:

def get_circle_area():"""求圆的面积"""passprint(help(get_circle_area))

输出结果:

D:\soft\pythonworkplace>test.py
Help on function get_circle_area in module __main__:get_circle_area()求圆的面积NoneD:\soft\pythonworkplace>

这里none代表返回值为空。
而这里我们打印了所有,我们如果想要打印帮助文档:

def get_circle_area():"""求圆的面积"""passprint(get_circle_area.__doc__)

输出结果:

D:\soft\pythonworkplace>test.py求圆的面积D:\soft\pythonworkplace>

好,我们接着看求圆的面积:

def get_circle_area(r,PI):"""求圆的面积"""return r * r * PIr1 = float(input("请输入圆的半径:"))print(get_circle_area(r1,3.14))

输出结果:

D:\soft\pythonworkplace>test.py
请输入圆的半径:2
12.56D:\soft\pythonworkplace>test.py
请输入圆的半径:3
28.26D:\soft\pythonworkplace>

默认值参数:
如果函数中的某个或者某些参数,在调用时大多数情况下,是一个固定值。
为了调用方便,可以设定默认值。
默认值参数一定要写在普通值参数之后,否则会报错。

如果一个值在大多数情况下取一个值,我们可以默认给他一个值,比如这里PI大多数情况下使用3.14,则:

def get_circle_area(r,PI=3.14):"""求圆的面积"""return r * r * PIr1 = float(input("请输入圆的半径:"))print(get_circle_area(r1))

输出结果:

D:\soft\pythonworkplace>test.py
请输入圆的半径:4
50.24D:\soft\pythonworkplace>

当然,如果我给了PI另一个值,那么他肯定是使用给定值,如果没有才采用默认值:

def get_circle_area(r,PI=3.14):"""求圆的面积"""return r * r * PIr1 = float(input("请输入圆的半径:"))print(get_circle_area(r1))
print(get_circle_area(r1,3.1415926))

输出结果:

D:\soft\pythonworkplace>test.py
请输入圆的半径:3
28.26
28.2743334D:\soft\pythonworkplace>

可变参数:
*变量 这种形式定义的,注意:不是C语言中指针
它主要用来存储额外的参数!!!!
会将参数封装到元组中

依然是上一个案例,我们如果说想要进行加入别的功能,我们可以进行加入函数,当然,python中也可以加入可变参数。加上*arges不影响原来的代码,可以给他不进行传值。

def test(x,y,*args):print(x + y)test(2,5)
test(2,3,4,5,6,7)

输出结果:

D:\soft\pythonworkplace>test.py
7
5D:\soft\pythonworkplace>

这里我们可以看到,我们给它进行多传几个值依然不会影响原来的代码,但是,最终执行的功能我们可以看到进行多个输入,它只传前面两个值,,从而输出了5.

而这里我们加入arges又有什么用呢?

def test(x,y,*args):print(args)print(x + y)test(2,5)
test(2,3,4,5,6,7)

输出结果:

D:\soft\pythonworkplace>test.py
()
7
(4, 5, 6, 7)
5D:\soft\pythonworkplace>

这里我们可以看到里面存进了4567,也就是你传了多余的参数他会把这些存进去。扩展了程序的功能也不影响原有的代码。

def test(x,y,*args):if len(args) > 0:print(args[0])print(x + y)test(2,5)
test(2,3,4,5,6,7)

输出结果:

D:\soft\pythonworkplace>test.py
7
4
5D:\soft\pythonworkplace>

所以,我们可以看下print函数:

>>> help(print)
Help on built-in function print in module builtins:print(*args, sep=' ', end='\n', file=None, flush=False)Prints the values to a stream, or to sys.stdout by default.sepstring inserted between values, default a space.endstring appended after the last value, default a newline.filea file-like object (stream); defaults to the current sys.stdout.flushwhether to forcibly flush the stream.>>>

这里面我们就可以明确的看到print里面第一个就是可变参数,因此它可以直接传入多个值。
命名参数:
又叫做关键字参数
**变量
可变参数和关键字参数,主要的功能就是配合装饰器进行功能扩展的!!!
就比如:

>>> help(print)
Help on built-in function print in module builtins:print(*args, sep=' ', end='\n', file=None, flush=False)Prints the values to a stream, or to sys.stdout by default.sepstring inserted between values, default a space.endstring appended after the last value, default a newline.filea file-like object (stream); defaults to the current sys.stdout.flushwhether to forcibly flush the stream.>>> print("hello","world",end = "")
hello world>>> print("hello","world",end = "",sep = "+")
hello+world>>>

这里我们可以看到print函数有着end以及分割sep关键字参数。
下面我们依旧是那个案例:

def test(x,y,*args,**kwargs):if len(args) > 0:print(args[0])print(kwargs)print(x + y)test(2,5)
test(2,3,4,5,6,7,a = 123,b = 456,name = "xxx",age = 16)

输出结果:

D:\soft\pythonworkplace>test.py
{}
7
4
{'a': 123, 'b': 456, 'name': 'xxx', 'age': 16}
5D:\soft\pythonworkplace>

{'a': 123, 'b': 456, 'name': 'xxx', 'age': 16}这个我们叫做字典
我们也试着去拿值:

def test(x,y,*args,**kwargs):if len(args) > 0:print(args[0])if len(kwargs) > 0:print(kwargs["name"])print(x + y)test(2,5)
test(2,3,4,5,6,7,a = 123,b = 456,name = "xxx",age = 16)

输出结果:

D:\soft\pythonworkplace>test.py
7
4
xxx
5D:\soft\pythonworkplace>

8、函数传递

函数作为参数传递函数内部:
python中函数是对象,python中函数的参数只要是对象即可,所以pyhton中函数可以作为参数传递到函数内部。
注意如下两种情况的不同之处:

def a()pass
def b()pass
b(a) # 函数作为参数传递到函数中
b(a())# 将a的返回值作为参数传递到函数中

案例:

def demo(fn):# 下面这行代码就是一个函数调用# fn是一个函数fn("hello,函数你好")demo(print)

输出结果:

D:\soft\pythonworkplace>test.py
hello,函数你好D:\soft\pythonworkplace>

那么我们可不可以加括号?

def demo(fn):# 下面这行代码就是一个函数调用# fn是一个函数fn("hello,函数你好")demo(print())

输出结果:

Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 657, in <module>demo(print())File "D:\soft\pythonworkplace\test.py", line 655, in demofn("hello,函数你好")
TypeError: 'NoneType' object is not callableD:\soft\pythonworkplace>

这又是什么意思呢?

这里我们也就是等同于如下代码,首先执行调用。

def demo(fn):# 下面这行代码就是一个函数调用# fn是一个函数fn("hello,函数你好")print(print())
demo()

输出结果:

D:\soft\pythonworkplace>test.pyNone
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 658, in <module>demo()
TypeError: demo() missing 1 required positional argument: 'fn'D:\soft\pythonworkplace>

我们可以看到首先print(print())执行结果为none,然后我们在进行了调用,此时进行报错,也就是none不能被调用。

这里我们也可以进行联想到,print实际存储在堆里面,而栈里面存储的则是print的引用地址。所以我们也就是将print的引用地址传给了fn,从而输出了一段i字符串。

当然,这里直接使用print输出函数可以,同时我们也可以自己构建一个函数进行函数传递:

def demo(fn):# 下面这行代码就是一个函数调用# fn是一个函数fn("hello,函数你好")def print_msg(msg):print(msg)demo(print_msg)

输出结果:

D:\soft\pythonworkplace>test.py
hello,函数你好D:\soft\pythonworkplace>

这里可以看到输出结果是一样的。
所以,python中函数是可以以参数的形式存入函数内部的。带了括号相当于传了函数的返回值。函数带括号表示函数调用,不带括号表示函数引用,代表函数本身。

9、匿名函数以及lambda表达式

匿名函数:没有名称的函数,不能直接调用
pythonlambda引入之前是没有匿名函数的!
lambda表达式之后,才通过lambda实现了匿名函数
lambda(x,b,c):函数体
同样是以上案例:

def demo(fn):# 下面这行代码就是一个函数调用# fn是一个函数fn("hello,函数你好")demo(lambda msg:print(msg))

输出结果:

D:\soft\pythonworkplace>test.py
hello,函数你好D:\soft\pythonworkplace>

这里lambda使用后面加参数这里也就是函数名,冒号后面加返回值,这里则为函数内容。
使用lambda主要用于匿名场景中,进行简化。

lambda本质是简化编写程序的难度!!!!!

10、偏函数

可能存在某个函数,该函数中存在默认值
如果后面调用时,多次需要修改为一个相同的默认值【变成另外一个值】可以使用偏函数实现
我们可以看下int:

>>> help(int)
Help on class int in module builtins:class int(object)|  int([x]) -> integer|  int(x, base=10) -> integer||  Convert a number or string to an integer, or return 0 if no arguments|  are given.  If x is a number, return x.__int__().  For floating point|  numbers, this truncates towards zero.||  If x is not a number or if base is given, then x must be a string,|  bytes, or bytearray instance representing an integer literal in the|  given base.  The literal can be preceded by '+' or '-' and be surrounded|  by whitespace.  The base defaults to 10.  Valid bases are 0 and 2-36.|  Base 0 means to interpret the base from the string as an integer literal.|  >>> int('0b100', base=0)|  4||  Built-in subclasses:|      bool||  Methods defined here:||  __abs__(self, /)|      abs(self)||  __add__(self, value, /)|      Return self+value.|
-- More  --

我们可以看到base=10,这里int就是整型10进制不用改默认值。如果我们需要进行进制转换:

>>> int("123456")
123456
>>> int("123456",base = 10)
123456
>>> int("123456",base = 8)
42798
>>> int("11111",base = 2)
31
>>>

我们可以重新构建一个函数,只是这里不是10进制,而是二进制,引入functools模块。

1import functoolsfunctools.partial()2from functools import partial# 返回一个新的函数 = partial(原函数, 默认值=新值)

使用:

>>> import functools
>>> dir(functools)
['GenericAlias', 'RLock', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', '_CacheInfo', '_HashedSeq', '_NOT_FOUND', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_c3_merge', '_c3_mro', '_compose_mro', '_convert', '_find_impl', '_ge_from_gt', '_ge_from_le', '_ge_from_lt', '_gt_from_ge', '_gt_from_le', '_gt_from_lt', '_initial_missing', '_le_from_ge', '_le_from_gt', '_le_from_lt', '_lru_cache_wrapper', '_lt_from_ge', '_lt_from_gt', '_lt_from_le', '_make_key', '_unwrap_partial', 'cache', 'cached_property', 'cmp_to_key', 'get_cache_token', 'lru_cache', 'namedtuple', 'partial', 'partialmethod', 'recursive_repr', 'reduce', 'singledispatch', 'singledispatchmethod', 'total_ordering', 'update_wrapper', 'wraps']
>>> functools.partial
<class 'functools.partial'>
>>> from functools import partial
>>> partial(int,base=2)
functools.partial(<class 'int'>, base=2)
>>> a = partial(int,base=2)
>>> a
functools.partial(<class 'int'>, base=2)
>>> a("100")
4
>>> a("100",base=10)
100
>>> int("100")
100
>>>

三、递归

递归recursion):函数自身调用自身,需要设置递归的终止条件
一定要有终止条件,否则是个死循环。
案例:求 0-n的和

# 求0-n的和
def get_count(n:int):if n == 1:return 1return n + get_count(n - 1)count = get_count(100)
print(f"0-100的和是{count}")

输出结果:

D:\soft\pythonworkplace>test.py
0-100的和是5050D:\soft\pythonworkplace>

递归的内存分析以及优缺点

这里也就牵扯了压栈,弹栈。
这就是栈内进行大量调用执行从而占用大量空间。

这里我们可以尝试着让其调用1000多次:

# 求0-n的和
def get_count(n:int):if n == 1:return 1return n + get_count(n - 1)count = get_count(1000)
print(f"0-100的和是{count}")

输出结果:

D:\soft\pythonworkplace>test.py
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 668, in <module>count = get_count(1000)^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 665, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 665, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 665, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceededD:\soft\pythonworkplace>

这里报错,递归错误,已经超过了递归最大数量。
同时,我们可以调用sys内置模块来看递归最大次数:

import sysprint(sys.getrecursionlimit())
# 求0-n的和
def get_count(n:int):if n == 1:return 1return n + get_count(n - 1)count = get_count(1000)
print(f"0-100的和是{count}")

输出结果:

D:\soft\pythonworkplace>test.py
1000
Traceback (most recent call last):File "D:\soft\pythonworkplace\test.py", line 671, in <module>count = get_count(1000)^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 668, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 668, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^File "D:\soft\pythonworkplace\test.py", line 668, in get_countreturn n + get_count(n - 1)^^^^^^^^^^^^^^^^[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceededD:\soft\pythonworkplace>

当然,我们如果真的要求1到1000以上的和或者其他,我们也可以进行自己设置递归的次数,这里设置2000次最大次数,从而输出1到1500的求和:

import sys# print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
# 求0-n的和
def get_count(n:int):if n == 1:return 1return n + get_count(n - 1)count = get_count(1500)
print(f"0-100的和是{count}")

输出结果:

D:\soft\pythonworkplace>test.py
0-100的和是1125750D:\soft\pythonworkplace>

练习: 1、求斐波那契数列的第n项值
实现一个函数,求斐波那契数列的第n项值
斐波那契数列:从第三项开始,每一项的值是前两项之和

a[n] = a[n - 1] + a[n - 2]
1 1 2 3 5 8 13 21 34 55	89 ……

实现代码:

def fibonacii(n: int) -> int:if n == 1 or n == 2:return 1return fibonacii(n - 1) + fibonacii(n - 2)print(fibonacii(10))

输出结果:

D:\soft\pythonworkplace>test.py
55D:\soft\pythonworkplace>

2、跳楼梯问题:
f(n)=f(n-1)+f(n-2)
实现代码:

def staircase(n):if n == 1 or n == 2:return nreturn staircase(n - 1) + staircase(n -2)print(staircase(10))

输出结果:

D:\soft\pythonworkplace>test.py
89D:\soft\pythonworkplace>

3、不死兔子问题:
小明得到了一对兔子
1 1 1 1 2 3 4 5 7 10 14 19 26 36
a[n] = a[n - 1] + a[n - 4]
实现代码:

def rabbit(n):"""求不死兔子数量"""if n <= 4:return 1else:return rabbit(n - 1) + rabbit(n -2)print(rabbit(8))

输出结果

D:\soft\pythonworkplace>test.py
8D:\soft\pythonworkplace>

四、容器

容器本质就是用来存储大量数据的一种数据结构
容器篇:

list
set
tuple
dict

线性表:
指的是一种有顺序的存储表

  • 数组(array):
    大小固定、类型固定、内存存储地址是连续的
    优点:
    查询效率非常高:查询时间复杂度:O(1)
    缺点:
    更新(删除、增加)比较麻烦,需要内存进行挪动
  • 2、链表(list):
    大小不固定、内存存储地址不一定连续
    它的优缺点和数组正好相反
  • 3、栈(stack):
    FILO LIFO
  • 4、队列(queue)
    FIFO LILO

list(列表)
注意: python中的列表底层是使用双向链表实现的!!!

五、作业:

作业1

判断以下哪些不能作为标识符

	A、aB、¥aC、_12D、$a@12E、falseF、False

作业2:

输入数,判断这个数是否是质数(要求使用函数 + for循环)
实现代码:

um = int(input("请输入一个整数:"))
def work_1(num):flag = Truefor i in range(2,num // 2 + 1):if num % i == 0:flag = Falsebreakif flag:print(f"{num}为质数")else:print(f"{num}为合数")work_1(num)

作业3:

求50~150之间的质数是那些?
实现代码:

def work_9():for num in range(50,101):for i in range(2,num):if num % i == 0:breakelse:print(num)work_9()

作业:

4打印输出标准水仙花数,输出这些水仙花数
实现代码:

def work_10():for a in range(1,10):for b in range(0,10):for c in range(0,10):num = a * 100 + b * 10 + countif num == a ** 3 + b ** 3 + c ** 3:print(num)work_10()

作业5:

验证:任意一个大于9的整数减去它的各位数字之和所得的差,一定能被9整除.
实现代码:

def work_2(num):for i in range(9,num):if (num - num % 10) & 9 == 0:return Truereturn False
for i in range(100):if work_2(i):print(f"{i}可以被整除")

作业6:

一个五位数,若在它的后面写上一个7,得到一个六位数A,
若在它前面写上一个7,得到一个六位数B,B是A的五倍,求此五位数.
实现代码:

def work_4():for i in range(10000,100000):a = i * 10 + 7b = 7 *100000 +iif b == a * 5:return iprint(get(num))

作业7:

求十进制数字的二进制编码:求十进制数字的二进制编码中的1的数量
实现代码:

作业8:

求1~100之间不能被3整除的数之和
实现代码:

def work_5():sum = 0for i in range(1,101):sum += isum1 = 0for j in range(1,101):if j % 3 != 0:sum1 = jsum1 += jsum2 = sum - sum1print(f"1~100之间不能被3整除的数之和:{sum2}")work_5()

作业9:

给定一个正整数N,找出1到N(含)之间所有质数的总和
实现代码:

num = int(input("请输入一个正整数:"))
def work_6(N):sum = 0for i in range(1,N+1):for j in range(2,i // 2 + 1):if i  %  j == 0:breaksum += iprint(f"所有质数的总和:{sum}")work_6(num)

作业10:

计算PI(公式如下:PI=4(1-1/3+1/5-1/7+1/9-1…)
实现代码:

num = int(input('请输入正整数n:'))
def work_7(n):x = 0a = 0for i in range(1 , n+1 , 2):x += 1 / i * (-1) ** a a += 1print("PI的近似值:",4 * x)work_7(n)

作业11:

求a+aa+aaa+…+aaaaaaaaa=?其中a为1至9之中的一个数,项数也要可以指定
实现代码:

def work_8(n):count = 0num = 0for i in range(n):num += n * 10 ** icount += numreturn count
num = int(input("请输入一个1到9的整数:"))
print(work_8(num))

作业12:

找出10000以内能被5或6整除,但不能被两者同时整除的数(函数)
实现代码:

作业13:

不死兔子和跳楼梯问题
实现代码:

作业14:

汉诺塔问题
实现代码:


http://www.ppmy.cn/news/586587.html

相关文章

创科视觉软件说明书_机器视觉入门指南

在中国&#xff0c;如果将制造业比作国民经济的主体&#xff0c;那工业自动化就是血液。在一个主体中&#xff0c;血液是无处不在的&#xff0c;而血液是主体生命延续的基本保障。 要说工业自动化那就要说机器视觉&#xff0c;因为工业自动化离不开机器视觉。在工业自动化制造过…

3D视觉点云数据处理十大方法

这篇博客主要介绍三维计算机视觉中点云数据处理面对的问题&#xff0c;主要方法和技术&#xff0c;概述其特点。 ICP点云配准就是我们非常熟悉的点云处理算法之一。实际上点云数据在形状检测和分类、立体视觉、运动恢复结构、多视图重建中都有广泛的使用。点云的存储、压缩、渲…

物联网视觉技术及应用

物联网技术不断发展&#xff0c;已经从单纯地强调连接&#xff0c;更多地强调多场景的支持。出现了越来越多带有视觉能力的智能硬件&#xff0c;包括智能门锁&#xff0c;智能猫眼&#xff0c;86智能面板&#xff0c;带屏智能中控&#xff0c;网络摄像头等。 这些智能设备基本都…

CVPR2021 | 最新CVPR2021论文抢先看,附全部下载链接!

CVPR2021最全1660篇pdf&#xff08;4.3G&#xff09; 链接: https://pan.baidu.com/s/1GWkqUOcO6KMOu-uLJrSpbA 提取码: vwkx 持续更新Github&#xff1a; https://github.com/Sophia-11/Awesome-CVPR-Paper 2021持续论文集锦百度云请在【计算机视觉联盟】后台回复 CVPR2…

计算机视觉领域顶级会议和顶级期刊汇总

目录 一、计算机视觉顶会 二、计算机视觉顶刊 三、机器学习顶会 四、人工智能顶会 五、国际期刊 一、计算机视觉顶会 &#xff08;&#xff11;&#xff09;ICCV&#xff1a;International Conference on Computer Vision International Comference on Computer Vision&…

新兴AI解决方案将越来越依赖于嵌入式视觉技术

https://www.toutiao.com/a6703777192976843272/ 随着先进机器人技术和机器学习技术的涌现以及向工业4.0制造模式的转变&#xff0c;嵌入式视觉应用的疆土在逐步扩大。现代汽车采用的电子产品&#xff0c;尤其是高级驾驶辅助系统&#xff08;ADAS&#xff09;和车载信息娱乐系统…

计算机视觉论文-2021-11-01

本专栏是计算机视觉方向论文收集积累&#xff0c;时间&#xff1a;2021年9月15日&#xff0c;来源&#xff1a;paper digest 欢迎关注原创公众号 【计算机视觉联盟】&#xff0c;回复 【西瓜书手推笔记】 可获取我的机器学习纯手推笔记&#xff01; 直达笔记地址&#xff1a;机…

计算机视觉论文-2021-03-10

本专栏是计算机视觉方向论文收集积累&#xff0c;时间&#xff1a;2021年3月9日&#xff0c;来源&#xff1a;paper digest 欢迎关注原创公众号 【计算机视觉联盟】&#xff0c;回复 【西瓜书手推笔记】 可获取我的机器学习纯手推笔记&#xff01; 直达笔记地址&#xff1a;机器…