一、概述
1、面向过程:根据业务逻辑从上到下垒代码
2、函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
3、面向对象:对函数进行分类和封装,让开发“更快更好更强...”
综上:
- 函数编程:【执行函数】
- 面向对象:【创建对象】【通过对象执行方法】
注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面向对象编程也支持函数式编程
二、创建类和对象
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。
# 创建类 class Foo: def Bar(self): print 'Bar' def Hello(self, name): print 'i am %s' %name # 根据类Foo创建对象obj obj = Foo() obj.Bar() #执行Bar方法 obj.Hello('wupeiqi') #执行Hello方法
- class是关键字,表示类
- 创建对象,类名称后加括号即可
- 类中的函数第一个参数必须是self,类中定义的函数叫做方法。
事例:
class Account: def login(self): user = input('请输入用户名:') pwd = input('请输入密码:') if user == 'alex' and pwd == 'sb': print('登录成功') else: print('登录失败') obj = Account() obj.login()
三、面向对象的三大特性
面向对象的三大特性是指:封装、继承和多态。
(一)封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
- 将内容封装到某处
- 从某处调用被封装的内容
第一步:将内容封装到某处
a. 将数据封装到对象中,以供自己在方法中调用
class FileHandler: def __init__(self,file_path): self.file_path = file_path self.f = open(self.file_path, 'rb') def read_first(self): self.f.read() def read_last(self): self.f.read() def read_second(self): self.f.read() obj = FileHandler('C:/xx/xx.log') obj.read_first() obj.read_last() obj.read_second() obj.f.close()
b. 将数据封装到对象中,以供其他函数调用
def new_func(arg): arg.k1 arg.k2 arg.k6 class Foo: def __init__(self,k1,k2,k6): self.k1 = k1 self.k2 = k2 self.k6 = k6 obj = Foo(111,22,333) new_func(obj)
事例:
import re class UserInfo: def __init__(self,name,pwd,email): self.name = name self.pwd = pwd self.email = email user_list = [] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') ret = re.search('[0-9A-Za-z][w-.]+@[0-9a-zA-Z]+(.[0-9A-Za-z-]+)*.[0-9a-zA-Z]{2,6}',email) if ret: obj = UserInfo(user,pwd,email) user_list.append(obj) if len(user_list) == 3: break else: print('邮箱格式不正确,请重新输入!') for i in user_list: print('我叫%s,邮箱是%s' % (i.name,i.email))
class User: def __init__(self,name,pwd): self.name = name self.pwd = pwd class Account: def __init__(self): self.user_list = [] def login(self): num = 1 while num <= 3: user = input('请输入用户名:') pwd = input('请输入密码:') for i in self.user_list: if user == i.name and pwd == i.pwd: print('登陆成功') return else: print('您输入的用户名或密码不合法') continue num += 1 def register(self): user = input('请输入注册用户名:') pwd = input('请输入注册密码:') obj1 = User(user,pwd) self.user_list.append(obj1) print('注册成功') def run(self): i = 1 while i <= 2: self.register() i += 1 self.login() if __name__ == '__main__': obj = Account() obj.run()
(二)继承(提高代码的重用性)
class Base: # 父类,基类 def f2(self): print('f2') class Foo(Base): # 子类,派生类 def f1(self): print('f1') obj = Foo() obj.f1() obj.f2()
继承原则:先在自己类中找,没有就去父类找,如果有多个父类,按照从左往右的顺序找。
深坑1:
class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): print('foo.f2') # 1. 是否执行 obj = Foo() obj.f2() #foo.f2 obj.f1() #base.f1 # 2. 是否执行 obj = Base() obj.f1() #base.f1 obj.f2() # 错
深坑2:
class Base: def f1(self): print('base.f1') class Foo(Base): def f3(self): print('foo.f3') def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. #foo.f2 #foo.f3
深坑3:
class Base: def f1(self): print('base.f1') def f3(self): print('foo.f3') class Foo(Base): def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找,没有就去父类中找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. # foo.f2 # foo.f3
深坑4:
class Base: def f1(self): print('base.f1') def f3(self): self.f1() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. print('base.f3') class Foo(Base): def f1(self): print('foo.f1') def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. # foo.f2 # foo.f1 # base.f3 obj2 = Base() obj2.f3() # base.f1 # base.f3
class Base1: def f1(self): print('base1.1') def f2(self): print('base1.f2') class Base2: def f1(self): print('base2.f1') def f2(self): print('base2.f2') def f3(self): print('base2.f3') self.f1() class Foo(Base1,Base2): def f0(self): print('foo.f0') self.f3() obj = Foo() obj.f0() #foo.f0 # base2.f3 # base1.1
总结:
1. 多继承先找左边
2. self到底是谁,self是那个类的对象,那么就从该类开始找(自己没有就找父类)
(三)多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' # 由于在Java或C#中定义函数参数时,必须指定参数的类型 # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类 # 而实际传入的参数是:S1对象和S2对象 def Func(F1 obj): """Func函数需要接收一个F1类型或者F1子类的类型""" print obj.show() s1_obj = S1() Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show Python伪代码实现Java或C#的多态
四、类的成员
(一)变量:
- 实例变量(字段)
- 公有实例变量(字段)
class Foo: def __init__(self,name): self.name = name #公有实例变量 def func(self): print(self.name) print(obj.name) obj = Foo('冯崇') print(obj.name) obj.func() #冯崇 # 冯崇 # 冯崇
- 私有实例变量(字段)
class Foo: def __init__(self,name): self.__name = name #私有实例变量 def func(self): print(self.name) #冯崇 print(obj.name) #冯崇 obj = Foo('冯崇') # print(obj.name) 外部调用,报错 obj.func()
- 类变量(静态字段)
- 公有类变量(静态字段)
class Foo: name = 'alex' #公有类变量 def __init__(self,age): self.age = age def func(self): print(Foo.name) #alex obj = Foo(18) print(obj.name) #alex print(Foo.name) #alex obj.func()
- 私有类变量(静态字段)
class Foo: __name = 'alex' #私有类变量 def __init__(self,age): self.age = age def func(self): print(Foo.__name) #alex obj = Foo(18) print(obj.__name) #报错 print(Foo.__name) #报错 obj.func()
准则:
实例变量(字段)访问时,使用对象访问,即: obj1.name
类变量(静态字段)访问时,使用类方法,即: Foo.country (实在不方便时,才使用对象)
易错点:
class Foo: # 类变量(静态字段) country = "中国" def __init__(self, name): # 实例变量(字段) self.name = name def func(self): pass obj1 = Foo('季红') obj2 = Foo('王晓东') # 练习1 obj1.name = 'alex' print(obj1.name) # alex print(obj2.name) # 王晓东 # 练习2 obj1.country = '美国' print(obj1.country) # 美国 print(obj2.country) # 中国 # 练习3 Foo.country = '美国' print(obj1.country) # 美国 print(obj2.country) # 美国
如何验证儿子都不知道私有字段的存在?
无法访问:
class Base(object): __secret = "受贿" class Foo(Base): def func(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.func()
可以访问:
class Base(object): __secret = "受贿" def zt(self): print(Base.__secret) class Foo(Base): def func(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.zt()
(二)方法
--实例方法
--公有实例方法
class Foo(object): def __init__(self, name): #实例变量 self.name = name def func(self): #实例方法 print(self.name) obj = Foo('冯崇') obj.func()
--私有实例方法
class Foo(object): def __init__(self): pass def __display(self,arg): print('私有方法',arg) #私有实例方法 def func(self): #公有实例方法 self.__display(123) obj = Foo() # obj.__display(123) # 外部无法访问 obj.func() #可以访问
--静态方法
--公有静态方法
class Foo(object): def __init__(self, name): self.name = name # 实例方法 def func(self): print(self.name) # 静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法 @staticmethod def display(a1,a2): return a1 + a2 obj = Foo('冯崇') obj.func() ret = Foo.display(1,3) print(ret)
--私有静态方法
class Foo(object): def __init__(self): pass @staticmethod def __display(arg): print('私有静态 方法',arg) def func(self): Foo.__display(123) @staticmethod def get_display(): Foo.__display(888) # Foo.__display(123) 报错 obj = Foo() obj.func() #可以访问 Foo.get_display() #可以访问
总结
1. 编写时:
- 方法上方写 @staticmethod
- 方法参数可有可无
2. 调用时:
- 类.方法名() *
- 对象.方法名()
3. 什么时写静态方法?
- 无需调用对象中已封装的值.
--类方法
--公有类方法
class Foo(object): # 类方法,cls是类 @classmethod def show(cls,x1,x2): print(cls,x1,x2) # 执行类方法 Foo.show(1,8)
--私有类方法
class Foo: @classmethod def __func(cls,name): print(cls,name) @classmethod def func1(cls): Foo.__func('alex') # Foo.__func('冯崇') #报错 Foo.func1() #<class '__main__.Foo'> alex
总结
1. 定义时:
- 方法上方写: @classmethod
- 方法的参数: 至少有一个cls参数
2. 执行时:
- 类名.方法名() # 默认会将当前类传到参数中.
3. 什么时用?
- 如果在方法中会使用到当前类,那么就可以使用类方法.
(三)属性(通过方法改造出来)
class Foo(object): def __init__(self): pass @property def start(self): return 1 @property def end(self): return 10 obj = Foo() print(obj.start) print(obj.end)
总结:
1. 编写时
- 方法上方写 @property
- 方法参数:只有一个self
2. 调用时:无需加括号 对象.方法
3. 应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property
五、组合(嵌套)
角色:学校,课程,班级
要求:
1. 创建北京,上海,深圳 3所学校
2. 创建课程(课程包括:周期,价格)
- 北京:linux,python,go 3个课程
- 上海:linux,python 2个课程
- 深圳:python 1个课程
3. 根据课程开设班级(班级包括:开班时间,结课时间,班级人数,开班介绍)
-北京linux开设:linux运维11期,linux运维12期
-北京python开设:全站11期,全站15期
-北京go开设:全站21期,全站65期
-上海linux开设:linux运维1期,linux运维2期
-上海python开设:全栈1期,全栈2期
-深圳python开设:全栈1期
class School: def __init__(self, address): self.address = address bj = School('北京校区') sh = School('上海校区') sz = School('深圳校区') class Course(object): def __init__(self, name, period, price, school=None): self.name = name self.period = period self.price = price self.school = school py1 = Course('Python全栈', '六个月', 19999, bj) py2 = Course('Python全栈', '六个月', 19999, sh) py3 = Course('Python全栈', '六个月', 19999, sz) l1 = Course('Linux运维', '六个月', 19999, bj) l2 = Course('Linux运维', '六个月', 19999, sh) g1 = Course('Go开发', 119,'六个月', bj) class Grade(object): def __init__(self, name,start_time,end_time, people, introduce, course=None): self.name = name self.start_time = start_time self.end_time = end_time self.people = people self.introduce = introduce self.course = course grl1 = Grade('linux运维11期 ','2018-9-1','2019-3-1',89,'introduce',l1) grl2 = Grade('linux运维12期 ','2018-10-1','2019-4-1',100,'introduce',l1) grl3 = Grade('linux运维1期 ','2018-9-1','2019-3-1',89,'introduce',20,l2) grl4 = Grade('linux运维2期 ','2018-10-1','2019-4-1',100,'introduce',l2) grp1 = Grade('全栈11期 ','2018-4-1','2018-10-1',89,'introduce',py1) grp2 = Grade('全栈15期 ','2018-9-1','2019-3-1',89,'introduce',py1) grp3 = Grade('全栈1期 ','2018-9-1','2019-3-1',89,'introduce',py2) grp4 = Grade('全栈2期 ','2018-9-1','2019-3-1',89,'introduce',py2) grp5 = Grade('全栈1期 ','2018-9-1','2019-3-1',89,'introduce',py3) grg1 = Grade('全栈21期 ','2018-9-1','2019-3-1',89,'introduce',g1) grg1 = Grade('全栈65期 ','2020-9-1','2021-3-1',89,'introduce',g1)
组合补充:
# 1. 类或对象是否能做字典的key class Foo: pass user_info = { Foo:1, Foo():5 } print(user_info) #{<class '__main__.Foo'>: 1, <__main__.Foo object at 0x000000000223D9E8>: 5}
# 2. 对象中到底有什么? class Foo(object): def __init__(self,age): self.age = age def display(self): print(self.age) #8 #9 data_list = [Foo(8),Foo(9)] for item in data_list: print(item.age,item.display()) #8 None #9 None
# 3. class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) class RoleConfig(StarkConfig): def changelist(self,request): print('666') # 创建了一个列表,列表中有三个对象(实例) # [ StarkConfig对象(num=1), StarkConfig对象(num=2), RoleConfig对象(num=3) ] config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)] for item in config_obj_list: print(item.num) #1 2 3
# ### 4. class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) class RoleConfig(StarkConfig): pass # 创建了一个列表,列表中有三个对象(实例) # [ StarkConfig对象(num=1), StarkConfig对象(num=2), RoleConfig对象(num=3) ] config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)] for item in config_obj_list: item.changelist(168) # 1 168 # 2 168 # 3 168
# #### 5 class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) # 创建了一个列表,列表中有三个对象(实例) # [ StarkConfig对象(num=1), StarkConfig对象(num=2), RoleConfig对象(num=3) ] config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)] for item in config_obj_list: item.changelist(168) # 1 168 # 2 168 # 666 3
# #### 6 class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)] config_obj_list[1].run() #2 999 config_obj_list[2].run() # 666 3
# #### 7 class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) class AdminSite(object): def __init__(self): self._registry = {} def register(self,k,v): self._registry[k] = v site = AdminSite() site.register('lyd',StarkConfig(19)) site.register('yjl',StarkConfig(20)) site.register('fgz',RoleConfig(33)) for k,row in site._registry.items(): row.changelist(5) # 19 5 # 20 5 # 666 33
### 8 class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) class AdminSite(object): def __init__(self): self._registry = {} def register(self,k,v): self._registry[k] = v site = AdminSite() site.register('lyd',StarkConfig(19)) site.register('yjl',StarkConfig(20)) site.register('fgz',RoleConfig(33)) for k,row in site._registry.items(): row.run() # 19 999 # 20 999 # 666 33
## 9 class UserInfo(object): pass class Department(object): pass class StarkConfig(object): def __init__(self,num): self.num = num def changelist(self,request): print(self.num,request) def run(self): self.changelist(999) class RoleConfig(StarkConfig): def changelist(self,request): print(666,self.num) class AdminSite(object): def __init__(self): self._registry = {} def register(self,k,v): self._registry[k] = v(k) site = AdminSite() site.register(UserInfo,StarkConfig) site.register(Department,StarkConfig) for k,row in site._registry.items(): row.run() # <class '__main__.UserInfo'> 999 # <class '__main__.Department'> 999
六、主动调用其它类的成员
第一种方法:
class Base(object): def f1(self): print('5个功能') class Foo(object): def f1(self): print('3个功能') Base.f1(self) #主动调用 obj = Foo() obj.f1()
第二种方法:按照类的继承顺序,找下一个.
class Base(object): def f1(self): print('5个功能') class Foo(Base): def f1(self): super().f1() #主动调用 print('3个功能') obj = Foo() obj.f1()
class Foo(object): def f1(self): super().f1() print('3个功能') class Bar(object): def f1(self): print('6个功能') class Info(Foo,Bar): pass obj = Info() obj.f1() #6个功能 #3个功能
七、类的特殊成员
class Foo(object): def __init__(self,name): self.name = name def __call__(self, *args, **kwargs): return args,kwargs def __getitem__(self, item): return item def __setitem__(self, key, value): print(key,value) #冯崇 美女 def __delitem__(self, key): print(key) def __add__(self, other): return self.name + other.name def __enter__(self): print(111) return 222 def __exit__(self, exc_type, exc_val, exc_tb): print(333) # 1.类名()会立即执行__init__方法 对对象的数据进行初始化 obj = Foo('冯崇') print(obj.name) # 2.对象名()会立即执行__call__方法 有返回值 ret = obj(11,22,33,name = 'alex') print(ret) #((11, 22, 33), {'name': 'alex'}) # 3.对象名[]会立即执行__getitem__方法 有返回值 ret = obj[345] print(ret) #345 # 4.对象名[] = ...会立即执行__setitem__方法 没有返回值 obj['冯崇'] = '美女' # 5.del 对象名[] 会立即执行__delitem__方法 没有返回值 del obj[123] # 6.对象+对象 会自动执行__add__方法 有返回值 obj1 = Foo('胜男') ret = obj + obj1 print(ret) #冯崇胜男 # 7.with 对象 会自动执行__enter__/__exit__ as f 可以用来接收返回值 with obj as f: print(f) print('我是大美女') # 111 # 222 # 我是大美女 # 333 #8.真正的构造方法__new__ Foo() 会立即执行 class Foo(object): def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kwargs): ret = object.__new__(cls) print(ret) #<__main__.Foo object at 0x000000000250DC88> return ret obj = Foo('冯崇',18) print(obj.name) #冯崇 obj = Foo('冯崇',18) print(obj) #<__main__.Foo object at 0x000000000250DC88> #obj与ret是一个对象 # 9. __str__ 为创建的对象名设置一个新的显示方法 class Foo(object): def __str__(self): return 'f1' obj = Foo() print(obj) #f1 # 10. __dict__ 以列表的形式打印出对象中封装的所有数据 class Base(object): def __init__(self,name,age): self.name = name self.age = age obj = Base('冯崇',18) print(obj.__dict__) #{'name': '冯崇', 'age': 18} # 11. __doc__ 查看注释内容 class Foo(object): ''' 用来计算方法与函数的数量 ''' pass obj = Foo() print(obj.__doc__) # 12. __iter__ 在类中定义__iter__ ,并返回一个迭代器,可以把不可迭代的对象变成可迭代的对象 class Foo(object): def __iter__(self): # return iter([11,22,33,44]) yield 11 yield 22 yield 33 yield 44 obj = Foo() for item in obj: print(item) #11 22 33 44
八、issubclass type isinstance 的应用
(一)issubclass
class Base(object): pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar,Foo)) # 检查第一个参数是否是第二个参数的 子子孙孙类 #True print(issubclass(Bar,Base)) #True print(issubclass(Base,Base)) #深坑:注意当输入两个相同的类名时,结果仍为True
(二)type:获取当前对象是由那个类创建
class Foo(object): pass class Bar(object): pass def func(*args): foo_counter =0 bar_counter =0 for item in args: if type(item) == Foo: foo_counter += 1 elif type(item) == Bar: bar_counter += 1 return foo_counter,bar_counter # result = func(Foo(),Bar(),Foo()) # print(result) v1,v2 = func(Foo(),Bar(),Foo()) print(v1,v2)
(三)isinstance 判断第一个参数是否是第二个参数的实例
class Base(object): pass class Foo(Base): pass obj1 = Foo() print(isinstance(obj1,Foo)) #True # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 print(isinstance(obj1,Base)) #True # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 print(isinstance(Base,type)) #True #注意类和对象都是相对而言的,类Base是由type创建的,所以对于type而言,Base相当于他的对象. obj2 = Base() print(isinstance(obj2,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 print(isinstance(obj2,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
总结:
给你一个参数,判断对象是不是由某一个指定类? type --> type(obj) == Foo
给你一个参数,判断对象是不是由某一个指定类或其父类? isinstance --> instance(obj,Foo)
九、约束
1. 接口的作用?
接口中不能写代码,主要用于约束继承它的类必须实现接口中定义的所有方法。
interface IFoo: def f1(self,x1):pass def f2(self,x1):pass interface IBar: def f3(self,x1):pass def f4(self,x1):pass class Foo(IFoo,IBar):# 实现了2个接口 def f1(self,x1):pass def f2(self,x1):pass def f3(self,x1):pass def f4(self,x1):pass
2. 抽象类和抽象方法的作用?
抽象类和抽象方法主要用于约束继承它的派生类必须实现它其中的抽象方法。
抽象类中可以定义其派生类中都要用到的方法。
3. 抽象类加抽象方法 和 接口的区别?
1. 接口主要用于java和c#语言中,其中不能编写任何的代码,主要用于约束继承它的类必须实现接口中定义的所有方法.
编写时需要在类前方引入关键字interface,派生类可同时继承多个接口.
2.抽象类和抽象方法在java和c#语言中有,同时python中也存在,在编写时需要引入特定的模块,通过from abc import ABCMate,abstractmethod实现.
主要用于约束继承抽象类的派生类必须实现它其中的抽象方法.
5. python中应该如何约束派生类中指定的方法?
有两种方法可以实现:
1.在基类中主动抛异常.其执行代码如下:(约束派生类,保证派生类中必须编写send方法,不然执行可能会报错)
class Base(object): ''' 必须继承Base,然后其中必须编写send方法,用于完成具体业务逻辑. ''' def send(self): raise NotImplementedError('.send() 必须被重写') class Foo(Base): def send(self): pass
2.通过抽象类和抽象方法实现, 保证继承抽象类的派生类必须实现其中的抽象方法. 执行代码如下:
from abc import ABCMeta,abstractmethod class Base(mateclass = ABCMeta): #抽象类 def f1(self): print('成功') @abstractmethod def f2(self): #抽象方法 pass class Foo(Base): def f2(self): print(666)