【译文】递归函数(1)

4!= 4 * 3!

3!= 3 * 2!

2!= 2 * 1

替换计算值给了我们以下表达式

4!= 4 * 3 * 2 * 1

换句话说,计算机科学中的递归是一种解决问题的方法,它基于解决同一问题的较小实例。

Python 中的递归函数


现在我们来在 Python 中实现阶乘。它就像数学定义一样简单而优雅。

def factorial ( n ):

if n == 0 :

return 1

else :

return n * factorial ( n - 1 )

我们可以通过在前面的函数定义中添加两个 print() 函数来跟踪该函数的工作方式:

def factorial ( n ):

print ( "factorial has been called with n = " + str ( n ))

if n == 1 :

return 1

else :

res = n * factorial ( n - 1 )

print ( “intermediate result for " , n , " * factorial(” , n - 1 , "): " , res )

返回 res

打印(阶乘(5 ))

输出:

阶乘已被调用,n = 5

阶乘已被调用,n = 4

阶乘已被调用,n = 3

阶乘已被调用,n = 2

阶乘已被调用,n = 1

2 * factorial( 1 ) 的中间结果:2

3 * factorial( 2 ) 的中间结果:6

4 * factorial( 3 ) 的中间结果:24

5 * factorial( 4 ) 的中间结果:120

120

让我们看一下阶乘函数的迭代版本。

def iterative_factorial ( n ):

result = 1

for i in range ( 2 , n + 1 ):

result *= i

return result

对于 范围(5 ):

打印(我, iterative_factorial (我))

输出:

0 1

1 1

2 2

3 6

4 24

通常的做法是将 0 的阶乘函数扩展为参数。定义0!为 是有道理的1,因为只有零个对象的一个​​排列,即如果没有什么要排列,“一切”就留在原地。另一个原因是在一组 n 中选择 n 个元素的方法的数量计算为 n!除以 n! 的乘积!和0!。

为了实现这一点,我们所要做的就是改变 if 语句的条件:

def factorial ( n ):

if n == 0 :

return 1

else :

return n * factorial ( n - 1 )

斐波那契数列


我们关于递归的论文现在将我们引向另一个有趣的递归案例。

向日葵、黄金比例、枞树球果、达芬奇密码、Tool 的歌曲“Lateralus”和右侧的图形有什么共同点?对,斐波那契数列。我们不介绍斐波那契数列,因为它们是递归函数的另一个有用示例。尝试为这个数字序列编写递归函数可能会导致程序效率低下。事实上,如此低效以至于它不会有用。我们介绍斐波那契数列是为了向您展示递归的陷阱。

斐波那契正方形

斐波那契数是以下整数值序列的数字:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

斐波那契数列定义为:

Fn=Fn-+Fn-2

和 F0=0 和 F1=1

斐波那契数列以比萨的数学家列奥纳多 (Leonardo of Pisa) 的名字命名,他更为人所知的是斐波那契。在他的书“Liber Abaci”(出版于 1202 年)中,他介绍了这个序列作为处理兔子的练习。他的斐波那契数列从 F1 = 1 开始,而在现代数学中,该序列从 F0 = 0 开始。但这对序列的其他成员没有影响。

斐波那契数是人工兔子种群的结果,满足以下条件:

  • 一对刚出生的兔子,一公一母,建立初始种群

  • 这些兔子可以在一个月大的时候交配,这样在第二个月末,雌性就可以生育另一对兔子

  • 这些兔子是不朽的

  • 从第二个月开始,一对交配的一对总是每个月产生一对新的(一男一女)

斐波那契数是n几个月后兔子对的数量,即 10 个月后我们将有F10 兔子。

斐波那契数列很容易写成 Python 函数。它或多或少是数学定义中的一对一映射:

def fib ( n ):

if n == 0 :

return 0

elif n == 1 :

return 1

else :

return fib ( n - 1 ) + fib ( n - 2 )

迭代解决方案也很容易编写,尽管递归解决方案看起来更像定义:

def fibi ( n ):

old , new = 0 , 1

if n == 0 :

return 0

for i in range ( n - 1 ):

old , new = new , old + new

return new

我们将编写一个名称fibonacci包含函数fibfibi. 为此,您必须将以下代码复制到名为 fibonacci0.py 的文件中:

“”" 包含斐波那契函数的递归和迭代实现的

模块_。_该模块的目的在于展示__斐波那契函数__的纯递归实现的低效率!“”"

def fib ( n ):

“”" 斐波那契函数的递归版本 “”"

if n == 0 :

return 0

elif n == 1 :

return 1

else :

return fib ( n - 1 ) + fib ( n - 2 )

def fibi ( n ):

“”" 斐波那契函数的迭代版本 “”"

old , new = 0 , 1

if n == 0 :

return 0

for i in range ( n - 1 ):

old , new = new , old + 新

返回

输出:

覆盖 fibonacci0.py

如果您检查函数 fib() 和 fibi(),您会发现迭代版本 fibi() 比递归版本 fib() 快很多。为了了解这“快得多”可以达到多少,我们编写了一个脚本,它使用 timeit 模块来测量调用。为此,我们将 fib 和 fibi 的函数定义保存在文件 fibonacci.py 中,我们可以在下面的程序 (fibonacci_runit.py) 中导入该文件:

timeit 导入 计时器

t1 = Timer ( “fib(10)” , “from fibonacci import fib” )

对于 范围(1 , 20 ):

CMD = “FIB(” + STR (我) + “)”

T1 = 定时器(CMD , “从进口斐波纳契FIB” )

TIME1 = T1 。timeit ( 3 )

cmd = “fibi(” + str ( i ) + “)”

t2 = Timer ( cmd , “from fibonacci import fibi” )

时间 2 = t2 。timeit ( 3 )

打印( f "n= { i : 2d } , fib: { time1 : 8.6f } , fibi: { time2 : 7.6f } , time1/time2: { time1 / time2 : 10.2f } " )

输出:

n= 1, fib: 0.000001, fibi: 0.000002, time1/time2: 0.50

n= 2, fib: 0.000002, fibi: 0.000002, time1/time2: 0.85

n= 3, fib: 0.000003, fibi: 0.000002, time1/time2: 1.11

n= 4, fib: 0.000004, fibi: 0.000003, time1/time2: 1.45

n= 5, fib: 0.000011, fibi: 0.000003, time1/time2: 3.35

n= 6, fib: 0.000008, fibi: 0.000003, time1/time2: 2.98

n= 7, fib: 0.000012, fibi: 0.000002, time1/time2: 5.05

n= 8, fib: 0.000018, fibi: 0.000002, time1/time2: 7.98

n= 9, fib: 0.000029, fibi: 0.000002, time1/time2: 12.15

n=10, fib: 0.000046, fibi: 0.000003, time1/time2: 18.18

n=11, fib: 0.000075, fibi: 0.000003, time1/time2: 28.42

n=12, fib: 0.000153, fibi: 0.000003, time1/time2: 51.99

n=13, fib: 0.000194, fibi: 0.000003, time1/time2: 72.11

n=14, fib: 0.000323, fibi: 0.000003, time1/time2: 109.50

n=15, fib: 0.001015, fibi: 0.000008, time1/time2: 134.65

n=16, fib: 0.002165, fibi: 0.000008, time1/time2: 261.11

n=17, fib: 0.003795, fibi: 0.000019, time1/time2: 198.87

n=18, fib: 0.006021, fibi: 0.000010, time1/time2: 574.59

n=19, fib: 0.008807, fibi: 0.000011, time1/time2: 785.54

time1是 3 次调用所需的时间(以秒为单位)fib(n)time2分别是fibi(n).

我们的递归实现有什么问题?

让我们来看看计算树,即调用函数的顺序。fib() 被 f() 代替。

fib() 计算树

我们可以看到子树 f(2) 出现了 3 次,而用于计算 f(3) 的子树出现了两次。如果你想象为 f(6) 扩展这棵树,你就会明白 f(4) 将被调用两次,f(3) 被调用三次,依此类推。这意味着,我们的递归不会记住先前计算的值。

我们可以通过使用字典来保存先前计算的值,为我们的递归版本实现“内存”。我们称这个版本为fibm

备忘录 = { 0 :0 , 1 :1 }

DEF fibm (Ñ ):

如果 Ñ 备忘录:

备忘录[ Ñ ] = fibm (ñ - 1 ) + fibm (ñ - 2 )

返回 备忘录[ Ñ ]

在我们对新版本做一些计时之前,我们将它添加到我们的fibonacci模块中:

“”" 包含斐波那契函数的递归和迭代实现的

模块_。_该模块的目的在于展示__斐波那契函数__的纯递归实现的低效率!“”"

def fib ( n ):

“”" 斐波那契函数的递归版本 “”"

if n == 0 :

return 0

elif n == 1 :

return 1

else :

return fib ( n - 1 ) + fib ( n - 2 )

def fibi ( n ):

“”" 斐波那契函数的迭代版本 “”"

old , new = 0 , 1

if n == 0 :

return 0

for i in range ( n - 1 ):

old , new = new , old + 新

返回

memo = { 0 : 0 , 1 : 1 }

def fibm ( n ):

“”" 递归斐波那契函数,它

在字典 memo 的帮助下

记忆先前__计算的值 “”"如果 memo 中不是 n :memo [ n ] = fibm ( n - 1 ) + fibm ( n - 2 )返回备忘录[ n ]

输出:

覆盖 fibonacci.py

我们再次计时以将其与 fibi() 进行比较:

from timeit import Timer

from fibonacci import fib

t1 = Timer ( “fib(10)” , “from fibonacci import fib” )

对于 范围(1 , 20 ):

小号 = “fibm(” + STR (我) + “)”

T1 = 定时器(小号,“从进口斐波纳契fibm” )

TIME1 = T1 。timeit ( 3 )

s = “fibi(” + str ( i ) + “)”

t2 = Timer ( s , “from fibonacci import fibi” )

时间 2 = t2 。timeit ( 3 )

打印( f "n= { i : 2d } , fibm: { time1 : 8.6f } , fibi: { time2 : 7.6f } , time1/time2: { time1 / time2 : 10.2f } " )

输出:

n= 1, fibm: 0.000002, fibi: 0.000002, time1/time2: 0.68

n= 2, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.63

n= 3, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.51

n= 4, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.46

n= 5, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.48

n= 6, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.41

n= 7, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.41

n= 8, fibm: 0.000001, fibi: 0.000011, time1/time2: 0.10

n= 9, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.40

n=10, fibm: 0.000001, fibi: 0.000002, time1/time2: 0.36

n=11, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.38

n=12, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.35

n=13, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.44

n=14, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.36

n=15, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.35

n=16, fibm: 0.000001, fibi: 0.000004, time1/time2: 0.34

n=17, fibm: 0.000001, fibi: 0.000003, time1/time2: 0.33

n=18, fibm: 0.000001, fibi: 0.000004, time1/time2: 0.29

n=19, fibm: 0.000001, fibi: 0.000004, time1/time2: 0.27

我们可以看到它甚至比迭代版本还要快。当然,论点越大,我们记忆的好处就越大:

我们还可以通过使用具有 callabe 实例的类,即使用特殊方法call为我们的 Fibonacci 函数定义递归算法。这样,我们将能够以优雅的方式隐藏字典。我们使用了一种通用方法,它允许定义类似于 Fibonacci 的函数,如 Lucas 函数。这意味着我们可以通过实例化此类的实例来创建类似斐波那契数列的数字序列。基本上,构建原理,即前两个数字的总和,将是相同的。它们将因两个初始值而异:

FibonacciLike****类

def __init__ ( self , i1 = 0 , i2 = 1 ):

self 。备忘录 = { 0 : i1 , 1 : i2 }

高清 __call__ (自我, ñ ):

如果 ñ 不是 自我。备忘录:

自我。备忘录[ n ] = 自我。__call__ ( n - 1 ) + self 。__call__ ( n - 2 )

返回 self 。备忘录[ n ]

# 我们创建一个可调用对象来创建斐波那契数列:

fib = FibonacciLike ()

# 这将创建一个可调用对象来创建 Lucas 数列:

lucas = FibonacciLike ( 2 , 1 )

对于 范围(1 , 16 ):

打印(我, FIB (我), 卢卡斯(我))

输出:

1 1 1

2 1 3

3 2 4

4 3 7

5 5 11

6 8 18

7 13 29

8 21 47

9 34 76

10 55 123

11 89 199

12 144 322

13 233 521

14 377 843

15 610 1364

卢卡斯数或卢卡斯级数是一个整数序列,以数学家弗朗索瓦·爱德华·阿纳托尔·卢卡斯 (1842-91) 的名字命名,他研究了该序列和密切相关的斐波那契数。卢卡斯数与斐波那契数有相同的创生法则,即前两个数之和,但0和1的取值不同。

广义斐波那契数列


现在我们将证明我们的方法也适用于计算任意广义斐波那契数列。斐波那契数列取决于前面的两个值。我们现在通过以下方式定义 k-Fib 序列来概括这个概念

给定一个固定的自然数kk >= 2。还给出了k初始值一世0,一世1,…一世克-1

满意 F克(0)=一世0,…F克(克-1)=一世克-1

该功能还需要 克 系数 C0,C1,…C克-1

F克(n) 被定义为

F克(n)=一个0⋅F克(n-1)+一个1⋅F克(n-2)…一个克-1⋅F克(n-克)

和 克<=n

kFibonacci****类

def __init__ ( self , k , initials , coefficients ):

self . memo = dict ( zip ( range ( k ), initials ))

self . coeffs = 系数

self 。k = k

def __call__ ( self , n ):

k = self 。ķ

如果 ñ 不是 自我。备忘录:

结果 = 0

系数_ , 我 拉链(自我。coeffs , 范围(1 , ķ + 1 )):

结果 + = 系数_ * 自我。__call__ ( n - i )

self. 备注[ n ] = 结果

返回 self 。备忘录[ n ]

fib = kFibonacci ( 2 , ( 0 , 1 ), ( 1 , 1 ))

lucas = kFibonacci ( 2 , ( 2 , 1 ), ( 1 , 1 ))

对于 范围(1 , 16 ):

打印(我, FIB (我), 卢卡斯(我))

输出:

1 1 1

2 1 3

3 2 4

4 3 7

5 5 11

6 8 18

7 13 29

8 21 47

9 34 76

10 55 123

11 89 199

12 144 322

13 233 521

14 377 843

15 610 1364

Pell 数字的序列以 1, 2, 5, 12, 29, …

功能是

磷(n)=2⋅磷(n-1)+磷(n-2) 和 磷(0)=1 和 磷(1)=1

用我们的kFibonacci类很容易制定这个序列:

P = kFibonacci ( 2 , ( 1 , 2 ), ( 2 , 1 ))

for i in range ( 10 ):

print ( i , P ( i ))

输出:

0 1

1 2

2 5

3 12

4 29

5 70

6 169

7 408

8 985

9 2378

我们可以通过在两个佩尔数 P(i) 和 P(i+1) 之间添加前两个佩尔数之和来创建另一个有趣的系列。我们得到:

磷(0),磷(1),磷(0)+磷(1),磷(2),磷(1)+磷(2),磷(3),磷(2)+磷(3),…

对应于: 1,2,3,5,7,12,17,29,…

def nP ( n ):

如果 n < 2 :

return P ( n )

else :

i = n // 2 + 1

if n % 2 : # n 是奇数

return P ( i )

else :

return P ( i - 1 ) + P ( i - 2 )

对于 范围(20 ):

打印(为nP (我), 结束= “” )

输出:

1, 2, 3, 5, 7, 12, 17, 29, 41, 70, 99, 169, 239, 408, 577, 985, 1393, 2378, 3363, 5741,

如果你仔细观察这些数字,你会发现在这个序列中还有另一个规则。我们可以将 nP 定义为

n磷(n)=2⋅n磷(n-2)+n磷(n-4) 和 n>3 和起始值 1,2,3,5

这是我们kFibonacci班级的另一个简单应用:

nP = kFibonacci ( 4 , ( 1 , 2 , 3 , 5 ), ( 0 , 2 , 0 , 1 ))

for i in range ( 20 ):

print ( nP ( i ), end = ", " )

输出:

1, 2, 3, 5, 7, 12, 17, 29, 41, 70, 99, 169, 239, 408, 577, 985, 1393, 2378, 3363, 5741,

一个有趣的数学事实:对于每个奇数 n 的商 磷(n) 经过 磷(n-1) 是一个近似值 2. 如果n是偶数,商是一个近似值1+12

sqrt2 = 2 ** 0.5

print ( "Square root of 2: " , sqrt2 )

print ( "Square root of 3: " , 1 + 1 / sqrt2 )

for i in range ( 1 , 20 ):

print ( nP ( i ) / nP ( i - 1 ), end = ", " )

输出:

2 的平方根:1.4142135623730951

3 的平方根:1.7071067811865475

2.0,1.5,1.6666666666666667,1.4,1.7142857142857142,1.4166666666666667,1.7058823529411764,1.4137931034482758,1.7073170731707317,1.4142857142857144,1.707070707070707,1.4142011834319526,1.707112970711297,1.4142156862745099,1.707105719237435,1.4142131979695431,1.7071069633883704,1.4142136248948696,1.7071067499256616,

更多关于 Python 中的递归


河内塔

如果您想了解更多关于递归的知识,我们建议您尝试解决以下练习。在你尽力而为之前,请不要盯着解决方案。如果您已经考虑了一段时间的任务,但仍然无法解决该练习,您可以参考我们的示例解决方案。

在我们教程的“高级主题”部分,我们对游戏或谜题“河内之塔”进行了全面的处理。当然,我们通过使用递归函数的函数来解决它。“河内问题”很特别,因为递归解决方案几乎将自己强加于程序员,而游戏的迭代解决方案很难找到和掌握。

练习

练习 1

想想函数 f(n) = 3 * n 的递归版本,即 3 的倍数

练习 2

编写一个递归 Python 函数,返回前 n 个整数的总和。(提示:该函数将类似于阶乘函数!)

练习 3

编写一个实现帕斯卡三角形的函数:

1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

练习 4

斐波那契数列隐藏在帕斯卡三角形内。如果您将以下三角形的彩色数字相加,您将得到第 7 个斐波那契数:

1 1 1 1 2 1 1 3 3 **1** 1 4 **6** 4 1 1 **5** 10 10 5 1 **1** 6 15 20 15 6 1

使用帕斯卡三角形编写一个递归程序来计算斐波那契数列。

练习 5

在 Python 中为 Eratosthenes 的筛子实现递归函数。

Eratosthenes 筛法是一种简单的算法,用于查找指定整数以内的所有素数。它是由古希腊数学家埃拉托色尼创造的。求所有小于或等于给定整数n的素数的算法:

  1. 创建一个从 2 到 n 的整数列表:2, 3, 4, …, n

  2. 从我设置为 2 的计数器开始,即第一个质数

  3. 从 i+i 开始,按 i 递增并从列表中删除这些数字,即 2 i、3 i、4*i 等。

  4. 找出 i 后面的列表的第一个数字。这是下一个质数。

  5. 将 i 设置为在上一步中找到的数字

  6. 重复步骤 3 和 4,直到 i 大于 n。(作为改进:去n的平方根就够了)

  7. 所有仍在列表中的数字都是素数

你可以很容易地看到,如果我们严格使用这个算法,我们将是低效的,例如,我们将尝试去除 4 的倍数,尽管它们已经被 2 的倍数去除了。所以它足以产生所有的倍数直到 n 的平方根的素数。我们可以递归地创建这些集合。

练习 6

写一个递归函数fib_indexfib(),返回斐波那契数列中某个数的索引,如果该数是该数列的元素,则返回-1,如果不包含该数,即

F一世乙(F一世乙_一世nd电子X(n))==n

练习 7

两个连续斐波那契数的平方和也是斐波那契数,例如2和3是斐波那契数列的元素,2 2 + 3 3 = 13对应斐波那契(7)。 用前面的函数求位置斐波那契数列中两个连续数的平方和。

数学解释:设 a 和 b 是两个连续的斐波那契数,a 先于 b。以数字“a”开头的斐波那契数列如下所示:

0个

1个

2 a + b

3 a + 2b

4 2a + 3b

5 3a + 5b

6 5a + 8b

我们可以看到斐波那契数列作为 a 和 b 的因子出现。此序列中的第 n 个元素可以使用以下公式计算:

F(n)=F一世乙(n-1)⋅一个+F一世乙(n)⋅乙

由此我们可以得出结论,对于自然数 n,n>1,以下成立:

F一世乙(2⋅n+1)=F一世乙(n)2+F一世乙(n+1)2

练习 8

tribonacci号码是像斐波那契数,但不是与两个预定条件开始,该序列与三个预定术语开始的,每个术语之后是前述三项的总和。前几个 tribonacci 数是:

0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504, 927, 1705, 3136, 5768, 10609, 19513, 356812, …

所述tetranacci号码与四个预定术语开始,每个术语之后是前述4项的总和。前几个四连数是:

0, 0, 0, 1, 1, 2, 4, 8, 15, 29, 56, 108, 208, 401, 773, 1490, 2872, 5536, 10671, 20569, 39648, …

对于pentanacci、hexanacci、heptanacci、octanacci 等,这以相同的方式继续。

为 tribonacci 和tetranacci 数编写函数。

练习 9:

如果有人想检查递归函数中的参数怎么办?例如阶乘函数。好的,请编写一个递归版本的 factorial 来检查参数。也许你以完美的方式做到了,但也许不是。你能改进你的版本吗?摆脱不必要的测试?

解决方案


练习 1 的解决方案

在数学上,我们可以这样写:

F(1)=3,

F(n+1)=F(n)+3

一个 Python 函数可以这样写:

def mult3 ( n ):

如果 n == 1 :

return 3

else :

return mult3 ( n - 1 ) + 3

对于 范围(1 ,10 ):

打印(mult3 (我))

输出:

3
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

36, 10671, 20569, 39648, …

对于pentanacci、hexanacci、heptanacci、octanacci 等,这以相同的方式继续。

为 tribonacci 和tetranacci 数编写函数。

练习 9:

如果有人想检查递归函数中的参数怎么办?例如阶乘函数。好的,请编写一个递归版本的 factorial 来检查参数。也许你以完美的方式做到了,但也许不是。你能改进你的版本吗?摆脱不必要的测试?

解决方案


练习 1 的解决方案

在数学上,我们可以这样写:

F(1)=3,

F(n+1)=F(n)+3

一个 Python 函数可以这样写:

def mult3 ( n ):

如果 n == 1 :

return 3

else :

return mult3 ( n - 1 ) + 3

对于 范围(1 ,10 ):

打印(mult3 (我))

输出:

3
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-UpSluLyO-1713727341359)]

[外链图片转存中…(img-vybaCf4S-1713727341360)]

[外链图片转存中…(img-Ki5FEpX4-1713727341361)]

[外链图片转存中…(img-VzodOrRU-1713727341361)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值