python【第三篇】面向对象

为什么用面向对象

否定的

面向过程:根据业务逻辑从上到下写垒代码,无复用性和扩展性可言,处于行代码级别
函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可,但是仅仅处于函数级别。应用场景 –> 各个函数之间是独立且无共用的数据
面向对象:对函数进行分类和封装,复用性和扩展性更高,处于类级别
设计模式 : 对类进行规划,复用性和扩展性最高,处于类级别

主要思想

分而治之:
 
    大项目【任务,需求,软件系统】》子系统》 组件(模块)》数据类型(类),各个击破!
    生活中:国家军队 军》师》…..
   企业》 老板》高层》中层》 员工
 
高内聚,低耦合:
 
    关系密切   放在 一起【组件,子系统】
    封装变化(细节):细节,复杂,变化!
    目的:方便使用者使用、保证代码本身稳定性安全性

设计原则

开-闭原则 (目标) :对扩展开放,对修改关闭
类的单一职责(一个类的定义)
面向接口编程而非面向实现 (写一个类时从哪入手)
优先使用组合而非继承 (复用的最佳实践)
依赖倒置 ( 依赖抽象) 依赖倒转
里氏替换 里氏代换(继承后的重写)
迪米特法则 (类与类交互的原则)

向对象的三大特性 

封装: 如何组织类或模块,让封装的类或组件,尽量只负责一个领域的工作.
继承: 复用方式之一,概念形成统一。通过继承可以管理多个概念
多态: 类、方法等的行为不同的做法。目标一致,实现的方式不同

类与对象

  要弄清楚python的面向对象,主要就是要弄清楚 ” 字段、方法、对象、类 “ 几者的内存分配,以及它们之间的权限关系(增删改查,类间的继承权限不在此讨论,在继承部分详细讨论)

内存分配
    普通字段(self.x)属于对象
	类字段(静态字段)、类方法在类在内存中只有一份(所有对象共用)

权限关系:
    类没有对象的任何权限
    对象有类成员的部分权限(查,改值不能改引用)

 

对象方法:约定第一个形参是self的方法;self函数间的self.x变量可互相使用、self函数还可以使用类属性(但不能修改,修改了就是对象属性)

类方法:约定第一个形参是cls的方法;cls函数可以使用类属性、但不能使用对象属性

静态方法:普通方法;不能使用类属性和对象属性

  

#类:一:实例化,二:引用名字(类名.变量名,类名.函数名)
#实例:引用名字(实例名.类的变量,实例名.绑定方法,实例名.实例自己的变量名)

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)
类与对象的基础语法
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
python为类内置的特殊属性

创建类

 普通方式

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第三个参数:类的成员

属性

一图胜千言,下面是属性、方法、对象、类的内存分配情况(箭头表示对象可访问类属性)

下面示例代码旨在说明,属性、方法、对象、类的权限关系

# _*_ 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'
View Code

方法

一图胜千言,下面是属性、方法、对象、类的内存分配情况 (左指向箭头表示对象可访问类属性,右指向箭头表示对象方法虽然在类内存中,但是可访问对象属性)

下面示例代码旨在说明,方法、对象、类的权限关系

# _*_ 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()
View Code

property属性

作用:把方法变成属性;检查参数(给属性赋值的值)

# _*_ 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>
View Code

属性的两种定义方式

属性的定义有两种方式:

  • 装饰器 即:在方法上应用装饰器
  • 静态属性 即:在类中定义值为property对象的静态属性

装饰器方式:

在类的普通方法上应用@property装饰器

我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
经典类,具有一种@property装饰器 

# ############### 定义 ###############    
class Goods:

    @property
    def price(self):
        return "wupeiqi"
# ############### 调用 ###############
obj = Goods()
result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
View Code

新式类,具有三种@property装饰器

# ############### 定义 ###############
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
View Code

注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
      新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法

由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

静态属性方式:

创建值为property对象的静态属性 

当使用静态属性的方式创建属性时,经典类和新式类无区别

class Foo:

    def get_bar(self):
        return 'wupeiqi'

    BAR = property(get_bar)

obj = Foo()
reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
print reuslt
View Code

property的构造方法中有个四个参数

  • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
  • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
  • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
  • 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
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...
View Code

由于静态属性方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

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 就是使用的静态属性的方式创建的属性

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)
Django源码

访问修饰符

对于类和对象成员,可能被:类内部、类外、子类、对象内部(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中:经典类和新式类:广度优先

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
2.x
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
2.x
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
2.x

init继承

子类默认继承父类init

默认init是隐式定义的,可以要显式定义(重写)

不带参数(如需带参数需要显式定义init),用于赋初值,初始化一个对象时就自动调用init()

多余一个参数时,子类不会继承父类init,若要继承需要显示重写init子类(要在init内显示调用父类init,调用的语法有两种)

#!/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()
View Code
#!/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()
View Code
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
View Code

super

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()
super:对象的父类

多继承

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通过函数来实现多态

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()
java多态伪代码
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
View Code

反射

定义:反射是通过字符串的形式操作对象(模块、类)相关的成员

 

优点:自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的。如果传一个对象给你,你可以查出它有什么能力,这是一项强大的特性。如果Python不支持某种形式的自省功能,dir和type内建函数,将很难正常工作。还有那些特殊属性,像__dict__,__name__及__doc__

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
不使用反射
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
改进
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
使用反射
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')
反射四种语法实例

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def dev():
    return 'dev'
home.py
import home as obj
 
#obj.dev()
 
func = getattr(obj, 'dev')
func() 
index.py

抽象类

与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。

 

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的。

#_*_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)
View Code

 

posted @ 2017-03-18 12:38  沐风先生  阅读(339)  评论(0编辑  收藏  举报