python【第三篇】面向对象
为什么用面向对象
否定的
面向过程:根据业务逻辑从上到下写垒代码,无复用性和扩展性可言,处于行代码级别 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可,但是仅仅处于函数级别。应用场景 –> 各个函数之间是独立且无共用的数据 面向对象:对函数进行分类和封装,复用性和扩展性更高,处于类级别 设计模式 : 对类进行规划,复用性和扩展性最高,处于类级别
主要思想
分而治之: 大项目【任务,需求,软件系统】》子系统》 组件(模块)》数据类型(类),各个击破! 生活中:国家军队 军》师》….. 企业》 老板》高层》中层》 员工 高内聚,低耦合: 关系密切 放在 一起【组件,子系统】 封装变化(细节):细节,复杂,变化! 目的:方便使用者使用、保证代码本身稳定性安全性
设计原则
开-闭原则 (目标) :对扩展开放,对修改关闭 类的单一职责(一个类的定义) 面向接口编程而非面向实现 (写一个类时从哪入手) 优先使用组合而非继承 (复用的最佳实践) 依赖倒置 ( 依赖抽象) 依赖倒转 里氏替换 里氏代换(继承后的重写) 迪米特法则 (类与类交互的原则)
面向对象的三大特性
封装: 如何组织类或模块,让封装的类或组件,尽量只负责一个领域的工作. 继承: 复用方式之一,概念形成统一。通过继承可以管理多个概念 多态: 类、方法等的行为不同的做法。目标一致,实现的方式不同
类与对象
要弄清楚python的面向对象,主要就是要弄清楚 ” 字段、方法、对象、类 “ 几者的内存分配,以及它们之间的权限关系(增删改查,类间的继承权限不在此讨论,在继承部分详细讨论)
内存分配 普通字段(self.x)属于对象 类字段(静态字段)、类方法在类在内存中只有一份(所有对象共用) 权限关系: 类没有对象的任何权限 对象有类成员的部分权限(查,改值不能改引用)
对象方法:约定第一个形参是self的方法;self函数间的self.x变量可互相使用、self函数还可以使用类属性(但不能修改,修改了就是对象属性) 类方法:约定第一个形参是cls的方法;cls函数可以使用类属性、但不能使用对象属性 静态方法:普通方法;不能使用类属性和对象属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#类:一:实例化,二:引用名字(类名.变量名,类名.函数名) #实例:引用名字(实例名.类的变量,实例名.绑定方法,实例名.实例自己的变量名) class Garen: camp='Demacia' def __init__(self,nickname): self.nick=nickname #g1.nick='草丛伦' def attack(self,enemy): # print('---------->',self.nick) #g1.nick print('%s attack %s' %(self.nick,enemy)) # print(Garen.camp) #查 # Garen.camp='aaaaaa' #改 # print(Garen.camp) # # # del Garen.camp #删除 # # print(Garen.camp) # # Garen.x=1 # print(Garen.x) g1=Garen('alex') # print(g1.nick) # g1.nick='asb' # print(g1.nick) # del g1.nick # print(g1.nick) # g1.sex='female' # print(g1.sex)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
类名.__name__# 类的名字(字符串) 类名.__doc__# 类的文档字符串 类名.__base__# 类的第一个父类(在讲继承时会讲) 类名.__bases__# 类所有父类构成的元组(在讲继承时会讲) 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类(仅新式类中)
创建类
普通方式
class Foo(object): def func(self): print 'hello world'
特殊方式(type类的构造函数)
def func(self): print 'hello world' Foo = type('Foo',(object,), {'func': func}) #type第一个参数:类名 #type第二个参数:当前类的基类 #type第三个参数:类的成员
属性
一图胜千言,下面是属性、方法、对象、类的内存分配情况(箭头表示对象可访问类属性)
下面示例代码旨在说明,属性、方法、对象、类的权限关系
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# _*_ coding:utf-8 _*_ class C: class_attr = "class_attr" class_arr_attr = ['C'] # class_arr、class_attr 为类属性 def __init__(self, name): # name为方法属性 self.name = name def hello(self): pass # 对象能访问类属性 print 'calss C can access %s:%s' % (id(C.class_attr), C.class_attr) c1 = C('hy1') print c1.name, 'can access %s:%s' % (id(c1.class_attr), c1.class_attr) c1.class_arr_attr.append('c1') print C.class_attr = "666" # 类外直接修改类中类属性的引用 print 'after modify class_attr,calss C can access %s:%s' % (id(C.class_attr), C.class_attr) print C.class_arr_attr # 对象可以修改类的值而非引用 print # 对象并没有修改属性class_attr,而是给对象本身添加了class_attr属性,不是类中的那个class_attr属性 c2 = C('hy2') print '%s can access %s:%s' % (c2.name, id(c2.class_attr), c2.class_attr) c2.class_attr = "c2" print '%s can access %s:%s' % (c2.name, id(c2.class_attr), c2.class_attr) c2.class_arr_attr.remove('c1') print c2.class_arr_attr # 对象c2删除了类的值而非引用 # print c2.class_arr_attr print # 这里说明,对象不能修改类属性 print 'calss C can access %s:%s' % (id(C.class_attr), C.class_attr) # 类无法访问对象属性 # print C.name # 提示 AttributeError: class C has no attribute 'name'
方法
一图胜千言,下面是属性、方法、对象、类的内存分配情况 (左指向箭头表示对象可访问类属性,右指向箭头表示对象方法虽然在类内存中,但是可访问对象属性)
下面示例代码旨在说明,方法、对象、类的权限关系
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# _*_ coding:utf-8 _*_ class C: class_attr = "class_attr" def __init__(self, name): # 对象方法可以访问对象自身成员 self.name = name def ordinary_func(self): # 对象方法不能访问类属性,对象可以访问 """ 定义普通方法,至少有一个self参数 """ return 'Object %s access 普通方法' % self.name # 对象方法可以访问对象自身成员 @classmethod def class_func(cls): """ 定义类方法,至少有一个cls参数 """ return '类方法' @staticmethod def static_func(): """ 定义静态方法 ,无默认参数""" return '静态方法' # 调用普通方法 c1 = C('hy') print id(c1.ordinary_func()), c1.class_func() # C.ordinary_func() # TypeError: unbound method ordinary_func() must be called with C instance as first argument (got nothing instead) print # 调用类方法, 说明类和对象的类方法在同一块内存 print id(C.class_func()), C.class_func() print id(c1.class_func()), c1.class_func() print # 调用静态方法, 说明类和对象的类方法在同一块内存 print id(c1.static_func()), c1.static_func() print id(C.static_func()), C.static_func()
property属性
作用:把方法变成属性;检查参数(给属性赋值的值)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# _*_ coding:utf-8 _*_ class Student(object): @property # 只读 def score(self): return self._score @score.setter # 只写 def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value s = Student() s.score = 60 print s.score print Student.score # <property object at 0x000000000307FA48>
属性的两种定义方式
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器
- 静态属性 即:在类中定义值为property对象的静态属性
装饰器方式:
在类的普通方法上应用@property装饰器
我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
经典类,具有一种@property装饰器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# ############### 定义 ############### class Goods: @property def price(self): return "wupeiqi" # ############### 调用 ############### obj = Goods() result = obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
新式类,具有三种@property装饰器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# ############### 定义 ############### class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): new_price = self.original_price * self.discount print(new_price) @price.setter def price(self, value): self.original_price = value @price.deleter def price(self): self.original_price = 0 # ############### 调用 ############### obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 1000 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 obj.price del obj.price # 自动执行 @price.deleter 修饰的 price 方法 obj.price
注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
静态属性方式:
创建值为property对象的静态属性
当使用静态属性的方式创建属性时,经典类和新式类无区别
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def get_bar(self): return 'wupeiqi' BAR = property(get_bar) obj = Foo() reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值 print reuslt
property的构造方法中有个四个参数
- 第一个参数是方法名,调用
对象.属性
时自动触发执行方法 - 第二个参数是方法名,调用
对象.属性 = XXX
时自动触发执行方法 - 第三个参数是方法名,调用
del 对象.属性
时自动触发执行方法 - 第四个参数是字符串,调用
对象.属性.__doc__
,此参数是该属性的描述信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def get_bar(self): return 'wupeiqi' # *必须两个参数 def set_bar(self, value): return return 'set value' + value def del_bar(self): return 'wupeiqi' BAR = property(get_bar, set_bar, del_bar, 'description...') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入 del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法 obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...
由于静态属性方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 def get_price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price def set_price(self, value): self.original_price = value def del_price(self, value): del self.original_price PRICE = property(get_price, set_price, del_price, '价格属性描述...') obj = Goods() obj.PRICE # 获取商品价格 obj.PRICE = 200 # 修改商品原价 del obj.PRICE # 删除商品原价 实例
注意:Python WEB框架 Django 的视图中 request.POST 就是使用的静态属性的方式创建的属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class WSGIRequest(http.HttpRequest): def __init__(self, environ): script_name = get_script_name(environ) path_info = get_path_info(environ) if not path_info: # Sometimes PATH_INFO exists, but is empty (e.g. accessing # the SCRIPT_NAME URL without a trailing slash). We really need to # operate as if they'd requested '/'. Not amazingly nice to force # the path like this, but should be harmless. path_info = '/' self.environ = environ self.path_info = path_info self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/')) self.META = environ self.META['PATH_INFO'] = path_info self.META['SCRIPT_NAME'] = script_name self.method = environ['REQUEST_METHOD'].upper() _, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', '')) if 'charset' in content_params: try: codecs.lookup(content_params['charset']) except LookupError: pass else: self.encoding = content_params['charset'] self._post_parse_error = False try: content_length = int(environ.get('CONTENT_LENGTH')) except (ValueError, TypeError): content_length = 0 self._stream = LimitedStream(self.environ['wsgi.input'], content_length) self._read_started = False self.resolver_match = None def _get_scheme(self): return self.environ.get('wsgi.url_scheme') def _get_request(self): warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or ' '`request.POST` instead.', RemovedInDjango19Warning, 2) if not hasattr(self, '_request'): self._request = datastructures.MergeDict(self.POST, self.GET) return self._request @cached_property def GET(self): # The WSGI spec says 'QUERY_STRING' may be absent. raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '') return http.QueryDict(raw_query_string, encoding=self._encoding) # ############### 看这里看这里 ############### def _get_post(self): if not hasattr(self, '_post'): self._load_post_and_files() return self._post # ############### 看这里看这里 ############### def _set_post(self, post): self._post = post @cached_property def COOKIES(self): raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '') return http.parse_cookie(raw_cookie) def _get_files(self): if not hasattr(self, '_files'): self._load_post_and_files() return self._files # ############### 看这里看这里 ############### POST = property(_get_post, _set_post) FILES = property(_get_files) REQUEST = property(_get_request)
访问修饰符
对于类和对象成员,可能被:类内部、类外、子类、对象内部(self方法内)、对象外部(实例化的对象)访问
下面的类成员表示:不带self关键字的属性和方法;对象成员表示:带self关键字的属性和方法
类公有成员:在类内部、类外、子类都能被调用 类私有成员:(以__开头),只能在类中被调用,但是属性还可通过instance.__classmate__attribute访问 对象公有:被对象内外部调用 对象私有成员:被对象内部调用 内置成员:定义类时系统默认生成,由前后双下划线组成。
内部类的实例化
1.直接使用外部类调用内部类 inObject= outClass.inClass() 2.先实例化外部类,再实例化内部类 outObject = outClass() inObject = outObject().inClass()
魔术方法
class Foo: def __init__(self, *args, **kwargs) //用于类实例化时初始化,所有代码之前执行 def __repr__(self, *args, **kwargs): //Foo()调用 return 'repr' def __str__(self, *args, **kwargs): //print Foo()调用 return 'return object' def __call__(self, *args, **kwargs): //Foo()()调用 return 'return call' def __del__(self, *args, **kwargs): //用于释放资源,所有代码之前后执行 return 'repr'
继承
经典类vs新式类
2.x中:经典类:深度优先
3.x中:经典类和新式类:广度优先
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: n = 'A' def f2(self): print("f2 from A") class B(A): n = 'B' def f1(self): print("from B") def f2(self): print("f2 from B") class C(A): n = 'C' def f2(self): print("f2 from C") class D(B,C): pass d = D() d.f2() ################输出################ # f2 from B 3.x
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: n = 'A' def f2(self): print("f2 from A") class B(A): n = 'B' def f1(self): print("from B") # def f2(self): # print("f2 from B") class C(A): n = 'C' def f2(self): print("f2 from C") class D(B,C): pass d = D() d.f2() ################输出################ # f2 from C 3.x
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: n = 'A' def f2(self): print("f2 from A") class B(A): n = 'B' def f1(self): print("from B") # def f2(self): # print("f2 from B") class C(A): n = 'C' # def f2(self): # print("f2 from C") class D(B,C): pass d = D() d.f2() ################输出################ # f2 from A 3.x
init继承
子类默认继承父类init
默认init是隐式定义的,可以要显式定义(重写)
不带参数(如需带参数需要显式定义init),用于赋初值,初始化一个对象时就自动调用init()
多余一个参数时,子类不会继承父类init,若要继承需要显示重写init子类(要在init内显示调用父类init,调用的语法有两种)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/python #_*_ coding:utf8 _*_ class People(object): color = 'yelow' def __init__(self): print "People init" def think(self): self.color = 'black' print 'I am a %s' % self.color def test(self): print 'Testing...' class Chinese(People): pass cn = Chinese()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/python #_*_ coding:utf8 _*_ class People(object): color = 'yelow' def __init__(self,c): print "People init " def think(self): self.color = 'black' print 'I am a %s' % self.color def test(self): print 'Testing...' class Chinese(People): def __init__(self): People.__init__(self,'red') cn = Chinese()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class People(object): color = 'yelow' def __init__(self, c): print "People init " def think(self): self.color = 'black' print 'I am a %s' % self.color def test(self): print 'Testing...' class Chinese(People): def __init__(self): # People.__init__(self,'red') super(Chinese, self).__init__('red') print 666 cn = Chinese() ### People init 666
super
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class People(object): color = 'yelow' def __init__(self): print "People init " def think(self): self.color = 'black' print 'I am a %s' % self.color def test(self): print 'Testing...' class Chinese(People): # def __init__(self): # People.__init__(self,'red') def think_2(self): super(Chinese, self).think() cn = Chinese() cn.think_2()
多继承
python支持多继承(一个类可以继承多个父类) 当父类中出现多个自定义的inti方法时,多重继承只执行第一个类的init方法
组合
软件重用的重要方式除了继承之外还有另外一种方式,即:组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
>>> class Equip: #武器装备类 ... def fire(self): ... print('release Fire skill') ... >>> class Riven: #英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类 ... camp='Noxus' ... def __init__(self,nickname): ... self.nickname=nickname ... self.equip=Equip() #用Equip类产生一个装备,赋值给实例的equip属性 ... >>> r1=Riven('锐雯雯') >>> r1.equip.fire() #可以使用组合的类产生的对象所持有的方法 release Fire skill
多态
多态定义:子类对象的父类引用可以访问子类对象的成员
多态作用:统一子类的类型
python不支持多态并且也用不到多态,因为python是弱类型,多态的概念是应用于Java和C#这一类强类型语言中,由于在Java或C#中定义变量时,必须指定变量的类型,所以通过父类确定类型实现,而不是像python通过函数来实现多态
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Jx(object): pass class Nanchang(Jx): def address(self): print 'Fuzhou' class Fuzhou(Jx): def address(self): print 'Fuzhou' Fz = Fuzhou() Jx jx = Fz # python是动态类型,这行是伪代码 jx.address()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Python伪代码实现Java或C#的多态 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不支持某种形式的自省功能,dir和type内建函数,将很难正常工作。还有那些特殊属性,像__dict__,__name__及__doc__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys class WebServer(object): def __init__(self,host,port): self.host = host self.port = port def start(self): print("Server is starting...") def stop(self): print("Server is stoppind...") def restart(self): self.stop() self.start() if __name__ == "__main__": server = WebServer('localhost',333) if sys.argv[1] == 'start': server.start() elif sys.argv[1] == 'stop': server.stop() elif sys.argv[1] == 'restart': server.restart() else: print("请输入 stop|start|restart") ######################## PS D:\PythonProject\0313> python.exe .\str.py stop Server is stoppind... PS D:\PythonProject\0313> python.exe .\str.py start Server is starting... PS D:\PythonProject\0313> python.exe .\str.py restart Server is stoppind... Server is starting... PS D:\PythonProject\0313> python.exe .\str.py st 请输入 stop|start|restart
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys class WebServer(object): def __init__(self,host,port): self.host = host self.port = port def start(self): print("Server is starting...") def stop(self): print("Server is stoppind...") def restart(self): self.stop() self.start() if __name__ == "__main__": server = WebServer('localhost',333) cmd_dic = { 'start':server.start, 'stop':server.stop, 'restart':server.restart } if sys.argv[1] in cmd_dic: cmd_dic[sys.argv[1]]() else: print("请输入 stop|start|restart") ############################## PS D:\PythonProject\0313> python.exe .\str.py stop Server is stoppind... PS D:\PythonProject\0313> python.exe .\str.py start Server is starting... PS D:\PythonProject\0313> python.exe .\str.py restart Server is stoppind... Server is starting... PS D:\PythonProject\0313> python.exe .\str.py st 请输入 stop|start|restart
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys class WebServer(object): def __init__(self,host,port): self.host = host self.port = port def start(self): print("Server is starting...") def stop(self): print("Server is stoppind...") def restart(self): self.stop() self.start() if __name__ == "__main__": server = WebServer('localhost',333) if hasattr(server,sys.argv[1]): func = getattr(server,sys.argv[1]) func() else: print("请输入 stop|start|restart") ########################### PS D:\PythonProject\0313> python.exe .\str.py stop Server is stoppind... PS D:\PythonProject\0313> python.exe .\str.py start Server is starting... PS D:\PythonProject\0313> python.exe .\str.py restart Server is stoppind... Server is starting... PS D:\PythonProject\0313> python.exe .\str.py st 请输入 stop|start|restart
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo(object): def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' def test_run(name): print("test_run is running") obj = Foo() # #### 检查是否含有成员 #### # if hasattr(obj, 'name') or hasattr(obj, 'func'): # print("has name and func attr") # # # #### 获取成员 #### # print(getattr(obj, 'name')) # print(getattr(obj, 'func')()) # #### 设置成员 #### setattr(obj, 'age', 18) setattr(obj, 'show', test_run) print(getattr(obj, 'name')) print(getattr(obj, 'func')()) print(getattr(obj, 'age')) obj.show('alex') getattr(obj, 'show')('alex') # #### 删除成员 #### # delattr(obj, 'name') # delattr(obj, 'func')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # -*- coding:utf-8 -*- def dev(): return 'dev'
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import home as obj #obj.dev() func = getattr(obj, 'dev') func()
抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' #一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # # t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)