python面向对象生动讲解_Python面向对象语法精讲
本专题的内容结构:
第一部分主要是:面向对象基础
第二部分主要是:面向对象进阶
第一部分的结构:
unit1:面向对象编程模式:
(1),面向对象编程思想
(2),面向对象的三个特征
(3),Python面向对象术语
unit2:Python类的构建:
(1),类的基本构建
(2),类的属性和方法
(3),类的构造函数和析构函数
unit3:实例1:银行ATM等待时间分析
(1),对象的设计和构建
(2),生活现象的程序分析
unit4:Python类的封装
(1),私有属性和公开属性
(2),私有方法和公开方法
(3),保留属性和保留方法
unit5:Python类的继承:
(1),子类,父类与超类
(2),类的方法重载和属性重载
(3),类的多继承
第二部分的结构:
unit1:Python类的运算:
(1),运算符的理解
(2),各类运算符的重载
unit2:Python类的多态:
(1),多态的理解
(2),参数类型的多态
(3),参数形式的多态
unit3:实例2:图像的四则运算
(1),PIL库和Numpy 库实践
(2),图像的加减乘除操作
unit4:Python对象的引用
(1),引用的理解
(2),浅拷贝和深拷贝
unit5:Python类的高级话题:
(1),类的特殊装饰器
(2),命名空间的理解
(3),类的名称修饰
第一部分的内容:
unit1:面向对象编程模式:
(1),万物皆对象:
自然意义上的对象:独立的存在 或 作为目标的事物
>独立性:对象都存在清晰的边界,重点在于划分边界
>功能性:对象都能表现出一些功能,操作或行为
>交互性:对象之间存在交互,如:运算和继承
Python语言的“万物皆对象”:
>Python语言中所有数据类型都是对象,函数是对象,模块是对象
>Python所有类都是继承于最基础类object
>Python语言中数据类型的操作功能都是类方法的体现
(2),面向对象编程思想:
OOP :Object-Oriented Programming
>OOP :面向对象编程,一种编程思想,重点在于高抽象的 复用代码
>OOP 把对象当做程序的基本单元,对象包含数据和操作数据的函数
>OOP 本质是把问题解决抽象为以对象为中心的计算机程序
注:
>OOP在较大规模或复杂项目中十分有用,OOP可以提高协作产量
>OOP最主要的价值在于代码复用
>OOP只是一种编程方式,并非解决问题的高级方法
面向过程 vs 面向对象
>面向过程:以解决问题的过程步骤为核心编写程序的方式
>面向对象:以问题对象构建和应用为核心编写程序的方式
>所有OOP能解决的问题,面向过程都能解决
小例子:
(3),面向对象的三个特征:
OOP的三个特征:
>封装:属性和方法的抽象,用数据和操作数据的方法来形成对象逻辑
>继承:代码复用的高级抽象,用对象之间的继承关系来形成代码复用
>多态:方法灵活性的抽象,让对象的操作更加灵活,更多复用代码
它能让更少的对象名称来支持更多的对象操作
它们都是表达了代码抽象和代码复用,
封装的理解:
封装Encapsulation:属性和方法的抽象
>属性的抽象:对类的属性(变量)进行定义,隔离及保护
>方法的抽象:对类的方法(函数)进行定义,隔离及保护
>目标是形成一个类/对象 对外可操作属性和方法的接口
继承的理解:
继承 Inheritance:代码复用的高级抽象
>继承是面向对象程序设计精髓之一
>实现了以类为单位的高抽象级别代码复用
>继承是新定义的类 能够几乎完全使用原有类属性和方法的过程
多态的理解:
多态 Polymorphism :仅针对方法,方法灵活性的抽象
>参数类型的多态:一个方法能够处理多个类型的能力
>参数形式的多态:一个方法能够接受多个参数的能力
>多态是 OOP的一个传统概念,Python天然支持多态,不需要特殊语法
其他语言中要用特定的语法用多态,但是Python中设计的弱类型天然支持多态
对多态的理解重点是概念和思路上的理解,更能理解Python对类的方法灵活性的抽象是如何表达的,
(4),Python面向对象术语:
先简要过一遍,后会介绍:
类 Class 和 对象 Object :
>类:逻辑抽象和产生对象的模板,一组变量和函数的特定编排
>对象:具体表达数据及操作的实体,相当于程序中的"变量"
>实例化:从类到对象的过程,所有"对象"都源于某个"类"
对象: 对象具体分为: 类对象和实例对象
类对象 vs 实例对象 :
>类对象:Class Object,当一个类建立之后,系统会维护个Python类基本信息的数据结构
>实例对象:Instance Object,Python类实例后产生的对象,简称:对象
>这是一组概念,类对象全局只有一个(保存类的基本信息),实例对象可以生成多个
属性: 存储数据的“变量”,分为 :类属性 和实例属性
方法: 操作数据的"函数",
包括:类方法,实例方法,自由方法,静态方法,保留方法
三个特性:封装继承多态
继承:基类,派生类,子类,父类,超类,重载
命名空间:程序元素作用域的表达
构造和析构:生成对象和删除对象的过程
(5),Python面向对象实例入门:
是上面的那个例子,计算价格的和,
出现新的保留字class
它可以定义抽象的Product 类,
1 classProduct():2 def __init__(self,name):3 self.name =name4 self.label_price =05 self.real_price =06
7 c = Product("电脑")8 d = Product("打印机")9 e = Product("投影仪")10 c.label_price,c.real_price = 10000,8000
11 d.label_price,d.real_price = 2000,1000
12 e.label_price,e.real_price = 1500,900
13 s1 ,s2 =0,014 for i in[c,d,e]:15 s1+=i.label_price16 s2+=i.real_price17 print(s1,s2)
View Code
unit2:Python类的构建:
python类的构建需要关注的地方:
就是上面的那个图:它包含了构建一个类所要关注的方方面面:
(1),类的基本构建:
使用class保留字定义类:
class <类名>:
[可以写个类描述字符串"documentation string"]
<语句块>
注:类定义不限位置,可以包含在分支或其他从属语句块中,执行时存在即可
可以放在全局部分,也可以放在分支,函数,等从属语句块中,由于Python语言是脚本语言,
所以在某个对象引用之前,只要是类被定义就可以。
类构造之类的名字:可以是任意有效标识符,建议采用大写单词的组合
如:ClassName ,BasicAuto ,BasicCreature
类构造之类描述:在类的定义后首行,以独立字符串形式定义
定义可以通过<类名>.__doc__属性来访问
注:像这种前后都有两个下划线的属性是Python给类保留的属性,
class DemoClass:
"This is a demo for Python class"
pass
print(DemoClass.__doc__)
>>>This is a demo for Python class
介绍一个概念:类对象
大家不要把类和对象拆开,类对象是一个名词,(Class Object)
>类定义完成后,默认生成一个类对象
与其他语言不同,python的类只要定义完就会生成一个对象,但这个对象呢?只是与这个类唯一对应的,
每一个类只唯一对应一个类对象,这个类对象是存储这个类的基本信息的
>每个类唯一对应一个类对象,用于存储这个类的基本信息
>类对象是type类的实例,表达为type类型
什么是type类型呢?
它是编译器提供了一种类型,
class DemoClass:
"This is a demo for Python class"
print("hello DemoClass")
print(type(DemoClass))
输出:
hello DemoClass
我们发现,我们只是定义了这个类,但是它也执行print("hello DemoClass)
这时因为在python中只要这个类被定义了, 就会生成一个表达它信息的 类对象
这个类对象是内置包含在类的定义中的,
那么这个类对象的生成使得类定义中的一些语句被执行,
因此,我们一般不在类的定义中直接包含语句,而是通过属性和方法来增加操作功能
类对象并不是使用类的常用方式,
使用类的方式最常用的是:通过创建实例对象来使用类的功能
<对象名> = <类名>([<参数>])
进一步采用<对象名>.<属性名>和<对象名>.<方法名>()体现类的功能
实例对象的类型:
它所生成时的那个类的类型
class DemoClass:
"This is a demo for Python class"
pass
print(type(DemoClass))
cn = DemoClass()
print(type(cn))
输出:
所以,实例对象和类对象是不一样的 ,
实例对象是最常用的方式,
了解Python类的构造函数
>类的构造函数用于从类创建实例对象的过程
>类的构造函数为实例对象创建提供了参数输入方式
>类的构造函数为实例属性的定义和赋值提供了支持
了解Python类的属性和方法:
>类的属性:类中定义的变量,采用描述类的一些特性参数
>类的方法:类中定义且与类相关的函数,用来给出类的操作功能
>属性和方法是类对外交互所提供的两种接口方式
(2),类的构造函数:
类的构造函数是从类生成实例对象所使用的函数,
Python中使用预定义的__init__()作为构造函数,
clsaa <类名>:
def __init__(self,<参数列表>)
<语句块>
类实例化时所使用的函数,可以接收参数并完成初始化操作
class DemoClass:
def __init__(self,name):
print(name)
dc1 = DemoClass("老王")
dc2 = DemoClass("老李")
输出:
老王
老李
注:通过构造函数__init__()可以为Python对象提供参数
还有,构造函数默认有个参数self ,它内部使用的,默认保留的,
__init__()的使用说明:
>参数:第一个参数约定是self,表示类实例自身,其他参数都是实例参数
>函数名:Python解释器内部定义的,由双下划线开始和结束
>返回值:构造函数没有返回值,或返回None ,否则产生TypeError异常
self在类定义内部代表类的实例
>self是Python面向对象中约定的一个类参数
>self代表类的实例,在类内部,self用于组合访问实例相关的属性和方法
>相比较而言,类名代表类对象本身
(3),类的属性:
属性是类内部定义的变量
>类属性:类对象的属性,由所有实例对象共享
>实例属性:实例对象的属性,由各实例所独享
类的属性和实例属性是如何定义的?
我们知道属性是变量,类中有两个地方可以放变量,
第一个是在class的全局命名空间:
<类属性名> =<类属性初值>
第二个是在函数/方法中定义的它就是实例属性:
class <类名>:
<类属性名>=<类属性初值>
def __init__(self,<参数列表>):
self.<实例属性名> = <实例属性初值>
...
class DemoClass:
count = 0 #直接在类中定义或赋值 无论在类内类外,访问类属性都要用<类名>.<属性名>来访问
def __init__(self,name,age):
self.name = name
self.age = age
DemoClass.count +=1
dc1 = DemoClass("老王",45)
dc2 = DemoClass("老李",51)
print("总数:",DemoClass.count)
print(dc1.name,dc2.name)
我们已经知道,类属性在类内,类外都是<类名>.<类属性>
而对于实例属性:
在类内部,用self.<属性名>访问
在类外部,用<对象名>.<属性名>访问
注:在类外,类属性也是可以用<对象名>.<属性名>来访问的
class DemoClass:
def __init__(self,name):
self.name = name
#注:构造函数没有返回值
def luckey(self):
s = 0
for c in self.name:
s+=ord(c)%100
return s
dc1 = DemoClass("Wang")
dc2 = DemoClass("Li")
print(DemoClass.__dict__) #类对象的属性字典
print(dc1.__dict__) #实例对象的属性字典
print(dc2.__dict__) #实例对象的属性字典
print(DemoClass.__dir__(DemoClass)) #类对象的属性列表
print(dc1.__dir__()) #实例对象的属性列表
(4),类的方法:
方法是类内部定义的函数:
>实例方法:实例对象的方法,由各实例对象独享,最常用的形式
>类方法:类对象的方法,由所有实例对象共享
>自由方法:类中的一个普通函数,由类所在命名空间管理,类对象独享
>静态方法:类中的一个普通函数,由类对象和实例对象共享
>保留方法:由双下划线开始和结束的方法,保留使用,如__len__()
方法1:实例方法:
实例方法是类内部定义的函数,与实例对象相关
class <类名>:
def <方法名>(self,<参数列表>):
...
实例方法采用<对象名>.<方法名>(<参数列表>)方式使用
class DemoClass:
def __init__(self,name):
self.name = name
#注:构造函数没有返回值
def luckey(self):
s = 0
for c in self.name:
s+=ord(c)%100
return s
dc1 = DemoClass("Wang")
dc2 = DemoClass("Li")
print(dc1.name,"'s lucky number is :",dc1.luckey())
print(dc2.name,"'s lucky number is :",dc2.luckey())
输出:
Wang 's lucky number is : 197
Li 's lucky number is : 81
方法2:类方法:
类方法是与类对象相关的函数,由所有实例对象共享
class <类名>:
@classmethod装饰器
def <方法名>(cls,<参数列表>):
...
类方法采用<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)方式使用
>类方法至少包含一个参数,表示类对象,建议使用cls
>@classmethod是装饰器,类方法定义必须要有
>类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法
class DemoClass:
count =0
def __init__(self,name):
self.name = name
DemoClass.count +=1
#注:构造函数没有返回值
@classmethod
def getChrCount(cls):
s = "0123456789"
return s[DemoClass.count]
dc1 = DemoClass("Wang")
dc2 = DemoClass("Li")
print(DemoClass.getChrCount())
print(dc1.getChrCount()) #类方法是可以被实例对象调用的,因为它归类对象和实例对象共同所有
输出:
2
2
方法3,自由方法:
是定义在类命名空间中的普通函数
class <类名>:
def <方法名>(<参数列表>):
...
#注:这里既没有self,也没有cls
自由方法采用<类名>.<方法名>(<参数列表>)方式使用,这时的<类名>代表的是命名空间
换句话说,自有方法是什么,它是在<类名>这个命名空间中定义的一个函数,访问它只能用
<函数名>.方法名来访问,
注:类对象自己独有
>自由方法不需要self,cls这类参数,可以没有参数
>自由方法只能操作类属性和类方法,不能操作实例属性和实例方法
>自由方法的使用只能用<类名>
严格来说,自由方法就不应该算是方法,它就是个函数,只不过是定义在类的命名空间中
为了统一说法,所以我们叫它自由方法,
class DemoClass:
count =0
def __init__(self,name):
self.name = name
DemoClass.count +=1
#注:构造函数没有返回值
def func():
DemoClass.count *=100
return DemoClass.count
dc1 = DemoClass("Wang")
print(DemoClass.func())
输出:100
方法4:静态方法:
我们知道,自由方法只能由类对象来使用,有没有办法让实例对象使用普通的函数(没有self,cls)呢?
可以,就是在自由方法的基础上加上一个装饰器@classmethod就可以了,
它是定义在类中的普通函数,能够被所有实例对象共享
class <类名>:
@staticmethod
def <方法名>(<参数列表>):
...
静态方法采用<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)方式使用
>静态方法可以没有参数,可以理解为定义在类中的普通函数
>@staticmethod是装饰器,静态方法必须用它
>静态方法只能操作 类属性和其他类 方法,不能操作实例属性和实例方法
>相比于自由方法,静态方法能够使用<类名>和<对象名>两种方式调用
class DemoClass:
count =0
def __init__(self,name):
self.name = name
DemoClass.count +=1
#注:构造函数没有返回值
@staticmethod
def func():
DemoClass.count *=100
return DemoClass.count
dc1 = DemoClass("Wang")
print(dc1.func())
print(DemoClass.func())
记时,方法3和方法4一起记
方法5:保留方法:
保留方法由双下划线开始和结束的方法,保留使用
class <类名>:
def <保留方法名>(self,<参数列表>):
...
保留方法一般都对应类的某种操作,使用操作符调用它
其实构造函数本身也是保留方法,
class DemoClass:
count =0
def __init__(self,name):
self.name = name
DemoClass.count +=1
#注:构造函数没有返回值
def __len__(self):
return len(self.name)
dc1 = DemoClass("Wang")
print(len(dc1))
输出:4
__len__ ()方法对应内置函数len()函数操作
理解:
这时Python解释器保留方法,已经对应,只需要编写代码即可
重写保留方法:
class DemoClass:
count =0
def __init__(self,name):
self.name = name
DemoClass.count +=1
#注:构造函数没有返回值
def __len__(self):
return 5
dc1 = DemoClass("Wang")
print(len(dc1))
输出:5
终结总结:
我们可以理解为len()只能计算基本数据类型的长度,对于类的长度它不能计算
我们就让他去调用类的保留方法__len__()
len(dc1)其实它还是调用的是dc1.__len__()方法
然后:这个保留方法内部计算了一个基础类型的长度len(name)
(5),类的析构函数:
当一个对象不用的时候,我们要对它释放空间,
Python使用预定义的__del__()作为析构函数
class <类名>:
def __del__(self):
<语句块>
...
析构函数在“真实” 删除实例对象时被调用
“真实”后面会介绍
例子:
class DemoClass:
def __init__(self,name):
self.name = name
def __del__(self):
print("再见",self.name)
dc1 = DemoClass("Wang")
del dc1
输出:
再见Wang
删除对象就是使用保留字del
使用del删除对象且对象被真实删除 时调用析构函数__del__()
>函数名和参数:Python解释器内部约定,保留方法
>调用条件:当实例对象被“真实删除”时,才调用该函数语句
>“真实删除”:当前对象的引用数为0或当前程序退出(垃圾回收)
例子:
import time
class DemoClass:
def __init__(self,name):
self.name = name
def __del__(self):
print("再见",self.name)
dc1 = DemoClass("Wang")
dc2 = dc1 #引用
del dc1
print(dc2.name)
while(True):
time.sleep(1) #使程序不退出
输出:
Wang
这就是只有当真实删除时才会调用析构函数
当然,一般构建对象的时候,我们不用写析构函数,python的垃圾回收机制已经很灵活了。
Python类的内存管理:
>在删除对象前,Python解释器会检查引用次数
>检查删除之后是否引用次数为0,不为0则仅删除当前引用;为0,则删除对象
>如果程序退出,则由垃圾回收机制删除对象
那么如何对一个对象的引用数量进行获取呢?
python提供了一个sys.getrefcount(<对象名>)获得对象的引用次数
>返回对象引用次数的方法,辅助删除对象时的分析
>sys.getrefcount()函数返回值为 被 引用值+1
>非特定目的,不建议自己写析构函数,利用Python垃圾回收机制就行
import sys
class DemoClass:
def __init__(self,name):
self.name = name
def __del__(self):
print("再见",self.name)
dc1 = DemoClass("Wang")
dc2 = dc1 #引用
print(sys.getrefcount(dc1))
输出:3 (比真实多1)
unit3:实例1:银行ATM等待时间分析:
需求分析:
可扩展为泊松分布:
1 importrandom as rd2 '''
3 整体思路:4 1,需要一个全局时间5 2,以ATM每次处理结束的时间为时间驱动事件6 3,需要一个等待队列,维护客户到达时间7 4,时间变化时,驱动等待队列变化8 '''
9 classATM():10 def __init__(self,maxtime = 5):11 self.t_max =maxtime12 def getServCompleteTime(self,start= 0):#完成一次业务的时间 start 可赋值给真实的时间,
13 #这样就是绝对的时间了
14 return start + rd.randint(1,self.t_max)15
16 classCustomers():17 def __init__(self,n):18 self.count =n19 self.left =n20 def getNextArrvTime(self,start = 0,arrvtime = 10): #下一个人到达的时间
21 if self.left !=0:22 self.left -=1
23 return start +rd.randint(1,arrvtime)24 else:25 return026 def isOver(self): #判断n 个客户是否都到达了
27 return True if self.left == 0 elseFalse28
29 c = Customers(100) #100个客户
30 a =ATM()31 wait_list =[] #存放用户到达时间
32 wait_time =0 #总共等待时间
33 cur_time= 0 #当前时间
34 cur_time +=c.getNextArrvTime()35 wait_list.append(cur_time)36 while len(wait_list) !=0 or notc.isOver():37 if wait_list[0] <= cur_time: #用户提前到了
38 next_time = a.getServCompleteTime(cur_time) #下次时间
39 delwait_list[0]40 else:41 next_time = cur_time +1
42
43 if not c.isOver() and len(wait_list) ==0:44 next_arrv =c.getNextArrvTime(cur_time)45 wait_list.append(next_arrv)46
47 if not c.isOver() and wait_list[-1]
<
<<
<
<
<<
<
<<<<
<
<<
<
<<
<
<<
<
<<
<<<<
<
<<
<
<
<
<
<<
<
<
<<
<<
<<
<<<
<
<
<
<<&
<
&other
<<
<
<<
<<<<<
<<
<
<
<
<<
<
<
<
python面向对象生动讲解_Python面向对象语法精讲相关推荐
- 【数据分析师-python基础】python基础语法精讲
python基础语法精讲 1 从数字开始 1.1 理解整数.浮点数.复数几种类型对象 1.2 掌握运算及其相关的常用函数 2 变量.表达式和语句 2.1 变量作用及定义的方法 2.2 变量命名原则和习 ...
- Python 3.X 完全零基础入门精讲 全套视频教程
简介 零基础小白快速学程序员大爱语言――Python,易学易用易就业!!! 目标人群:熟悉电脑基本操作,编程零基础或已具备Python或其它编程语言的人群. 课程目标:绝对零基础Python3.x 入 ...
- r语言 新增一列数字类型_R语言实战之R语言基础语法精讲(一)
R是用于统计分析.绘图的语言和操作环境.R是属于GNU系统的一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.在学习R数据科学之前,我们首先要对R语言的基础语法有一个良好的了 ...
- easypoi 语法_高中语法精讲系列七丨高中英语八大语法之“名词性从句”要点归纳...
在句子中起名词作用的从句叫名词性从句,包括主语从句.宾语从句.表语从句和同位语从句. 一. 主语从句 在句子中充当主语的从句叫主语从句,通常由从属连词(that, whether)和连接代词(what ...
- SQL语法精讲(包括建库、建表、建视图、查询、增加、删除、修改)
SQL语法精讲(包括建库.建表.建视图.查询.增加.删除.修改) SQL分类: DDL-数据定义语言(CREATE,ALTER,DROP,DECLARE) DML-数据操纵语言(SELECT,DELE ...
- python封装功能讲解_python学习28——面向对象实例讲解与封装
面向对象实例讲解 classSchool: school_name= 'OLDBOY' def __init__(self, nickname, addr): self.nickname=nickna ...
- python面向对象的含义_Python面向对象(一)
什么是对象?对象:独立性.功能性.交互性万物皆对象,均继承于Object类OOP:面向对象编程,本质含义在于复用代码,在较大规模或复杂项目中有用,提高写作产量面向对象和面向过程的对比编程实例 面向过程 ...
- python面向对象编程中_Python面向对象编程中关于类和方法
类和实例 python是一个面向对象的语言,而面向对象最重要的概念就是类和实例, 记得刚学习的时候不太理解这些概念,直到老师说了一句"物以类聚". 没错就是类, 归类 物以类聚 类 ...
- python交互界面实例_Python面向对象编程扑克牌发牌程序,另含大量Python代码!
1. 题目 编写程序, 4名牌手打牌,计算机随机将52张牌(不含大小鬼)发给4名牌手,在屏幕上显示每位牌手的牌. 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后, ...
最新文章
- 19-flutter的ListView 和 GridView的使用
- 理工科毕业设计献礼,MATLAB从入门到精通之矩阵是如何实现寻访与赋值的
- s3c2440芯片累加汇编语言,s3c2440 --跑马灯 C+汇编代码
- jmeter 线程执行顺序_性能测试之jmeter逻辑控制种类详解一
- arcgis python 教程-ArcGIS Python 入门到精通,视频教程下载
- 硬盘服务器哪个好用吗,服务器用固态硬盘好还是机械硬盘好
- DHCP协议的运行过程
- 迈瑞医疗前三季归母净利81亿:同比增21.6% 营收233亿
- 修改音频采样率和单双通道
- matlab求解常微分方程的实验,实验五__用matlab求解常微分方程
- 火狐 dns_如何在Firefox中通过HTTPS启用DNS
- spark sql boardcast join 生效问题探索
- 微软office与WPS Office如此相似,微软为什么不告金山侵权呢?
- 下周一直播 | 深度学习算法可视化调优实战演示
- 十三届蓝桥青少组省赛Python-20220423
- shell 常用工具指令
- 【cpu100%查不到具体的进程】
- TQ210——文件系统
- Delphi编程实现SQL Server挂起清除
- 2022年逆向物流行业分析
热门文章
- Syntax error, annotations are only available if source level is 1.5 or greater.
- C++(六)——继承
- 作业调度算法--短作业优先 操作系统_处理器管理_编程题
- 打印折痕方向(二叉树应用)
- django中序列化器字段参数、关联字段
- android文件系统\busybox文件系统的启动介绍
- python生成随机字符串
- 7、CSS 属性选择器
- 17、MySQL函数简介
- 牛客竞赛语法入门班函数与递归习题【未完结】