精华内容
下载资源
问答
  • python抽象基类abc模块

    2019-12-06 16:43:57
    为什么要有抽象类,This is a good question。 抽象类的作用可以在不同的模块相互调用时使用,可以用最精简的方式展示出代码...python中的抽象基类封装在abc模块中,使用six包可以兼容python2和python3,使用方法如...

    为什么要有抽象类,This is a good question。

    抽象类的作用可以在不同的模块相互调用时使用,可以用最精简的方式展示出代码之间的逻辑关系,让模块之间的依赖关系更清晰。可以让开发者不用考虑过多的实现细节,只关注当前抽象类的放方法和描述。方便多人合作开发,让代码可读性更高。

    python中的抽象基类封装在abc模块中,使用six包可以兼容python2和python3,使用方法如下:

    # -*- coding: utf-8 -*-
    import abc
    import six
    
    
    @six.add_metaclass(abc.ABCMeta)
    class A(object):
        @abc.abstractmethod
        def func(self):
            pass
    
    
    class B(A):
        def func(self):
            pass
    
    
    class C(A):
        pass
    
    
    if __name__ == "__main__":
        b = B()
        c = C()

    运行结果:

    Traceback (most recent call last):
      File "/Users/m/data/script/aaa.py", line 24, in <module>
        c = C()
    TypeError: Can't instantiate abstract class C with abstract methods greet

    对A中的func方法加了@abc.abstractmethod装饰器后,其子类中必须重写这个方法,否则会异常。

    实例化B的时候不会报错,因为B重写了所继承的A中的func方法,而C中没有重写func方法,所以会异常

    展开全文
  • python 2 抽象基类

    2020-12-23 17:00:34
    抽象基类的作用就是,让父类中的方法不可实例化,只能继承。但子类想要继承父类中的方法必须 实现该方法,看如下代码。 代码 cat test.py #/usr/bin/env python #coding:utf8 from abc import ABCMeta,abstract...

    抽象基类的作用就是,让父类中的方法不可实例化,只能继承。但子类想要继承父类中的方法必须
    实现该方法,看如下代码。

    代码

    cat test.py 
    #/usr/bin/env python
    #coding:utf8
    from  abc import ABCMeta,abstractmethod
    class Fish():
        __metaclass__ = ABCMeta
        @abstractmethod
        def swim(self):
            print '游泳'
    fish = Fish()
    fish.swim() 
    

    执行

    python test.py 
    Traceback (most recent call last):
      File "test.py", line 9, in <module>
        fish = Fish()
    TypeError: Can't instantiate abstract class Fish with abstract methods swim
    

    代码

    cat test.py 
    #/usr/bin/env python
    #coding:utf8
    from  abc import ABCMeta,abstractmethod
    class Fish():
        __metaclass__ = ABCMeta
        @abstractmethod
        def swim(self):
            print '游泳'
    
    class Goldfish(Fish):
        def run(self):
            print('This is Goldfish!')
    gold = Goldfish()
    gold.run
    

    执行

    [root@localhost nova]# python test.py 
    Traceback (most recent call last):
      File "test.py", line 15, in <module>
        gold = Goldfish()
    TypeError: Can't instantiate abstract class Goldfish with abstract methods swim
    

    代码

    cat test.py 
    #/usr/bin/env python
    #coding:utf8
    from  abc import ABCMeta,abstractmethod
    class Fish():
        __metaclass__ = ABCMeta
        @abstractmethod
        def swim(self):
            print '游泳'
    
    class Goldfish(Fish):
        def run(self):
            print('This is Goldfish!')
    
    class Carp(Fish):
        def swim(self):
            print("From Fish")
        def run(self):
            print('This is Carp!')
     
    carp = Carp()
    carp.swim()
    carp.run()
    

    执行

    [root@localhost nova]# python test.py 
    From Fish
    This is Carp!
    
    展开全文
  • 什么是泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口。

    什么是抽象基类

    有时候某些类型都有一些共同的特征,它们可以被抽象出来形成一个基类(基类又叫作父类),但这个基类本身不能实例化,只能由子类继承并实现其中的抽象方法后实例化子类对象,这样的类叫抽象基类。也就是说我们创建一个类的时候,里面要包含我们所有要用的方法,不然会报错。因为你一旦创建了实例,这个实例只能调用类中的方法,而不能调用类外面的方法了,而且我们在调用某个类的时候,这个类一定要继承相应的父类,不然也是没有用的。

    python中提供了内置模块abc(abstract base class)来模拟实现抽象类。可以通过abc将基类声明为抽象类的方式,然后注册具体类作为这个基类的实现。

    python崇尚鸭子类型,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。在解释性语言中,在定义函数的参数时是无法指定具体参数类型的,另一方面,参数的类型是在解释执行时才能确定。
    鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。对象的类型不再由继承等方式决定,而由实际运行时所表现出的具体行为来决定。

    抽象基类的作用:定义一些共同事物的规则和行为。(其实这和普通的类的作用没什么区别,但是这个类是必须由子类继承才能够使用,类似于JAVA中的接口。)
    那么抽象基类这样实现的目的是什么呢? 假设我们在写一个关于动物的代码。涉及到的动物有鸟,狗,牛。首先鸟,狗,牛都是属于动物的。既然是动物那么肯定需要吃饭,发出声音。但是具体到鸟,狗,牛来说吃饭和声音肯定是不同的,需要具体去实现鸟,狗,牛吃饭和声音的代码。

    抽象基类在python并非在于用来继承,主要用来理解python继承的定义,应该尽量使用鸭子类型。抽象基类常会用来作为父类、检验实例类型(结合isinstance判断)和抛出异常说明。

    静态类型和动态类型

    在上面的赘述中还涉及到了静态类型和动态类型,那么这两者是什么?又有什么区别呢?

    静态语言(强类型语言)
    静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。
    例如:C++、Java、Delphi、C#等。

    强类型定义语言:强制数据类型定义的语言。一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。

    动态语言(弱类型语言)
    动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
    例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。

    弱类型定义语言
    数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。强类型定义语言在速度上可能略逊色于弱类型定义语言,但是强类型定义语言带来的严谨性能够有效的避免许多错误。

    两者区别
    特性
    强类型语言是一旦变量的类型被确定,就不能转化的语言。
    弱类型语言则反之,一个变量的类型是由其应用上下文确定的。

    优势
    静态语言
    由于类型的强制声明,使得IDE有很强的代码感知能力,故,在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中,依托IDE对系统的开发很有保障;由于静态语言相对比较封闭,使得第三方开发包对代码的侵害性可以降到最低。

    动态语言
    思维不受束缚,可以任意发挥,把更多的精力放在产品本身上;
    集中思考业务逻辑实现,思考过程即实现过程;

    可散列

    标准库里的所有映射类型都是利用 dict 来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用作这些映射里的键(只有键有这个要求,值并不需要是可散列的数据类型)。

    原子不可变数据类型(str、bytes 和数值类型)都是可散列类型,frozenset 也是可散列的,因为根据其定义,frozenset 里只能容纳可散列类型。元组的话,只有当一个元组包含的所有元素都是可散列类型的情况下,它才是可散列的。

    如果一个对象是可散列的,那么这个对象:

    1. 支持 hash() 函数,并且通过 hash() 方法所得到的散列值是不变的。
    2. 支持通过 eq() 方法来检测相等性。
    3. 若 a == b 为真,则 hash(a) == hash(b) 也为真。

    eg:

    >>> tt = (1, 2, (30, 40))
    >>> hash(tt)
    8027212646858338501
    >>> tl = (1, 2, [30, 40])
    >>> hash(tl)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> tf = (1, 2, frozenset([30, 40]))
    >>> hash(tf)
    -4118419923444501110
    

    一般来讲用户自定义的类型的对象都是可散列的,散列值就是它们的 id() 函数的返回值,所以所有这些对象在比较的时候都是不相等的。如果一个对象实现了 __eq__方法,并且在方法中用到了这个对象的内部状态的话,那么只有当所有这些内部状态都是不可变的情况下,这个对象才是可散列的。

    根据这些定义,字典提供了多种创建字典的不同方式:

    >>> a = dict(one=1, two=2, three=3)
    >>> b = {'one': 1, 'two': 2, 'three': 3}
    >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
    >>> d = dict([('two', 2), ('one', 1), ('three', 3)])
    >>> e = dict({'three': 3, 'one': 1, 'two': 2})
    >>> a == b == c == d == e
    True
    

    这次的分享就到这里啦,有什么问题请大家指出,我一定会及时的修改!

    展开全文
  • 可以在全局(模块)作用域内定义名称foo,也可以在函数或方法内定义。定义类时情况亦如此:在class语句中定义代码都是在一个特殊命名空间(类命名空间)内执行,而类所有成员都可访问这个命名空间...

    类的命名空间
    下面两条语句大致等价:
    def foo(x): return x * x 
    foo = lambda x: x * x 
    它们都创建一个返回参数平方的函数,并将这个函数关联到变量foo。可以在全局(模块)作用域内定义名称foo,也可以在函数或方法内定义。定义类时情况亦如此:在class语句中定义的代码都是在一个特殊的命名空间(类的命名空间)内执行的,而类的所有成员都可访问这个命名空间。类定义其实就是要执行的代码段,并非所有的Python程序员都知道这一点,但知道这一点很有帮助。例如,在类定义中,并非只能包含def语句。对于成员变量(属性),有些语言支持多种私有程度。
    >>> class C: 
    ...       print('Class C being defined...') 
    ... 
    Class C being defined... 
    >>> 
    这有点傻,但请看下面的代码:
    class MemberCounter: 
        members = 0 
        def init(self): 
            MemberCounter.members += 1 
    >>> m1 = MemberCounter() 
    >>> m1.init() 
    >>> MemberCounter.members 

    >>> m2 = MemberCounter() 
    >>> m2.init() 
    >>> MemberCounter.members 

    上述代码在类作用域内定义了一个变量,所有的成员(实例)都可访问它,这里使用它来计算类实例的数量。注意到这里使用了init来初始化所有实例,这个初始化过程自动化,也就是将init转换为合适的构造函数。
    每个实例都可访问这个类作用域内的变量,就像方法一样。
    >>> m1.members 

    >>> m2.members 

    如果你在一个实例中给属性members赋值,结果将如何呢?
    >>> m1.members = 'Two' 
    >>> m1.members 
    'Two' 
    >>> m2.members 

    新值被写入m1的一个属性中,这个属性遮住了类级变量。这类似于“遮盖的问题”所讨论的,函数中局部变量和全局变量之间的关系。

     

    抽象基类
    然而,有比手工检查各个方法更好的选择。在历史上的大部分时间内,Python几乎都只依赖于鸭子类型,即假设所有对象都能完成其工作,同时偶尔使用hasattr来检查所需的方法是否存在。很多其他语言(如Java和Go)都采用显式指定接口的理念,而有些第三方模块提供了这种理念的各种实现。最终,Python通过引入模块abc提供了官方解决方案。这个模块为所谓的抽象基类提供了支持。一般而言,抽象类是不能(至少是不应该)实例化的类,其职责是定义子类应实现的一组抽象方法。下面是一个简单的示例:
    from abc import ABC, abstractmethod 
    class Talker(ABC): 
       @abstractmethod 
       def talk(self): 
           pass 
    形如@this的东西被称为装饰器,这里的要点是你使用@abstractmethod来将方法标记为抽象的——在子类中必须实现的方法。

    如果你使用的是较旧的Python版本,将无法在模块abc中找到ABC类。在这种情况下,需要导入ABCMeta,并在类定义开头包含代码行__metaclass__ = ABCMeta(紧跟在class语句后面并缩进)。如果你使用的是3.4之前的Python 3版本,也可使用Talker(metaclass=ABCMeta)代替Talker(ABC)。

    抽象类(即包含抽象方法的类)最重要的特征是不能实例化。
    >>> Talker() 
    Traceback (most recent call last): 
     File "<stdin>", line 1, in <module> 
    TypeError: Can't instantiate abstract class Talker with abstract methods talk 
    假设像下面这样从它派生出一个子类:
    class Knigget(Talker): 
        pass 
    由于没有重写方法talk,因此这个类也是抽象的,不能实例化。如果你试图这样做,将出现类似于前面的错误消息。然而,你可重新编写这个类,使其实现要求的方法。
    class Knigget(Talker): 
       def talk(self): 
           print("Ni!") 
    现在实例化它没有任何问题。这是抽象基类的主要用途,而且只有在这种情形下使用isinstance才是妥当的:如果先检查给定的实例确实是Talker对象,就能相信这个实例在需要的情况下有方法talk。
    >>> k = Knigget() 

    >>> isinstance(k, Talker) 
    True 
    >>> k.talk() 
    Ni! 
    然而,还缺少一个重要的部分——让isinstance的多态程度更高的部分。正如你看到的,抽象基类让我们能够本着鸭子类型的精神使用这种实例检查!我们不关心对象是什么,只关心对象能做什么(它实现了哪些方法)。因此,只要实现了方法talk,即便不是Talker的子类,依然能够通过类型检查。下面来创建另一个类。
    class Herring: 
       def talk(self): 
          print("Blub.") 
    这个类的实例能够通过是否为Talker对象的检查,可它并不是Talker对象。
    >>> h = Herring() 
    >>> isinstance(h, Talker) 
    False 
    诚然,你可从Talker派生出Herring,这样就万事大吉了,但Herring可能是从他人的模块中导入的。在这种情况下,就无法采取这样的做法。为解决这个问题,你可将Herring注册为Talker(而不从Herring和Talker派生出子类),这样所有的Herring对象都将被视为Talker对象。
    >>> Talker.register(Herring) 
    <class '__main__.Herring'> 
    >>> isinstance(h, Talker) 
    True 
    >>> issubclass(Herring, Talker) 
    True 
    然而,这种做法存在一个缺点,就是直接从抽象类派生提供的保障没有了。
    >>> class Clam: 
    ...        pass 
    ... 
    >>> Talker.register(Clam) 
    <class '__main__.Clam'> 
    >>> issubclass(Clam, Talker) 
    True 
    >>> c = Clam() 
    >>> isinstance(c, Talker) 
    True 
    >>> c.talk() 
    Traceback (most recent call last): 
     File "<stdin>", line 1, in <module> 
    AttributeError: 'Clam' object has no attribute 'talk'
    换而言之,应将isinstance返回True视为一种意图表达。在这里,Clam有成为Talker的意图。
    本着鸭子类型的精神,我们相信它能承担Talker的职责,但可悲的是它失败了。

     

    接口继承与归一化设计(工厂方法模式

    工厂方法模式:

    在父类中继承abc模块,装饰abc抽象基类,但父类中不去实现其方法,而是去子类中实现,如果子类中没有完全继承实现父类中的方法,会报错,作用在于可以严格匹配一致。

    import abc
    class All_file(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def read(self):
            pass
    
        @abc.abstractmethod
        def write(self):
            pass
    
    class Disk(All_file):
        def read(self):
            print('disk read')
    
        def write(self):
            print('disk write')
    
    class Cdrom(All_file):
        def read(self):
            print('cdrom read')
    
        def write(self):
            print('cdrom write')
    
    
    class Mem(All_file):
        def read(self):
            print('mem read')
    
        def write(self):
            print('mem write')
    
    m1=Mem()
    m1.read()
    m1.write()
    
    展开全文
  • Python映射类型详解

    千次阅读 2020-07-18 13:50:11
    这些抽象基类的主要作用事作为形式化的文档,它们定义了构建一个映射类型所需要的最基本的接口.然后它们还可以跟isinstance一起被用来判定某个数据是不是广义上的映射类型: from collections.abc import
  • Python的映射类型介绍

    2021-04-19 21:30:56
    collection.abc 模块里面有Mapping和MutableMapping这两个抽象基类,他们的作用为dict和类似的类型提供形式接口。其他的映射类型,一般不会直接继承这两个抽象基类,会直接对dict就行扩展。 from collections ...
  • 1、什么是继承? 继承指的是类与类之间的关系,功能之一就是用来解决代码重用...抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度) 继承: 是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个
  • Python」字典与集合

    2020-02-12 21:44:36
      模块collections.abc中的两个抽象基类Mapping与...这些抽象基类的主要作用是作为形式化文档,定义构建一个映射类型所需要的最基本的接口,还可以搭配isinstance运算符来判定某个数据是不是广义上的映射类型。...
  • 抽象基类(abc模块)2.1 抽象基类的作用2.1.1 检查某个类中是否有某种方法2.1.2 强制子类必须实现父类的方法2.2 type与isinstance区别3.类属性与实例属性3.1 基本查找顺序3.2 多继承查询顺序3.3 Python对象自省机制3.4...
  • collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口。 标准库里所有映射类型都是利用 dict 来实现的,它们有个共同的限制,即只有可散列的...
  • Python之abc模块

    万次阅读 2018-08-23 16:40:48
    作用:在代码中定义和使用抽象基类进行API检查。 1. 为什么使用abc? Abstract base classes由一组接口组成,检查比hasattr()更严格。通过定义一个抽象基类,可以为一组子类定义一个通用API。这对于第三...
  • 3.2中,collections.abc模块有Mapping和MutableMapping两个抽象基类Python2.6~3.2隶属于collections模块),作用是为dict和其他类似类型定义形式接口。  它们构建一个映射类型所需最基本接口,可以跟instance...
  • 对于面向对象编程来说,有三个概念一定要知道:封装、继承和多态。Python本身就是一种多态语言,即不同类...接口就是一种抽象的基类(父类),限制继承它类必须实现接口中定义某些方法。 具体代码实现如下: ...
  • collections.abc 模块中有 Mapping 和 MutableMapping这两个抽象基类作用是为dict 和其他类似类型定义形式接口。具体模块如下UML图。 什么是广义映射类型 广义上映射一般继承Mapping 和 Mu...
  • Python 字典和集合

    2017-08-17 14:31:00
     collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口(在Python 2.6 到 Python 3.2 的版本中,这些类还不属于 collections.abc模块,而是隶属...
  • collections.abc模块中有Mapping和MutableMapping这两个抽象基类,它们的作用是为dict和其他类似的类型定义形式接口。 from collections import abc my_dict = {} a = isinstance(my_dict, abc.Mapping) print(a)...
  • Python中IOBase详解

    2018-01-09 14:42:36
      这个类是所有I/O类的抽象基类作用于字节流。没有公共构造函数。   该类为许多方法提供了空抽象实现,派生类可以有选择进行覆盖实现。默认实现代表一个不能读取,写入和查询文件。   IOBase...
  • Python数据结构:字典

    2017-12-03 13:14:33
    这一篇是《流畅的 python》读书笔记。主要介绍: ...collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口。 标准库里所有...
  • 全面深入了解python(五) 1. 字典 dict类型不但在各种在各种程序里广泛使用,也是python...collections.abc模块中有Mapping和mutableMapping这两个抽象基类。它们的作用是为dict和其他类似的类型定义形式接口。 ...
  • 文章目录类继承一、继承介绍1.1、继承应用场景与作用1.1.1、应用场景1.1.2、作用1.2、继承相关定义1.2.1、继承定义1.2.2、继承派生类(子类)1.2.3、继承的基类(父类)1.3、继承分类1.3.1、根据继承...
  • 设计模式(GOF): 每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要和重复出现设计设计模式四个基本要素:模式名称、问题、解决方法、效果 ...隐藏了类内部实现 接口就是一种抽象的基类(父类),...
  • 5:Python3中的抽象基类 1:继承与多态介绍 继承:主要用于复用以前代码,缩短开发周期。 继承就是子类继承父类特征和行为,使得子类对象(实例)具有父类属性和方法,或子类从父类继承方法,使得子类具有...
  • 1 泛映射类型 collections.abc模块中有Mapping和MutableMapping两个抽象基类,他们的作用视为dict和其他类似的类型定义形式接口(在python2.6-3.2中,这两个基类属于collections模块) ...这些抽象基类的主要作用是...
  • 日期:2020年3月14日 作者:Commas 注释:学习就是为了忘记,什么是接口类,怎么将方法变为属性; 如果您想了解更多有关Python的知识,那么...定义一个接口类,我们需要abc模块(抽象基类,Abstract Base Classes)中
  •  描述:创建基类,即抽象接口是为了来实现一个程序架子,完成一系列功能,然后具体内容让子类来完成,如果不能完成,那么在调用时候会直接报错。  作用:一般用来构建程序一些架子,然后进行多人协作...
  • 继续讲一下类

    2019-10-08 06:57:55
    我们昨天大致讲了一下类内容,今天我们还要再讲一下有关类内容。...那么,这个抽象基类有什么作用?主要是用来指定子类需要提供功能。 from abc import ABCMeta >>> class LSFabc(metaclass = A...

空空如也

空空如也

1 2 3
收藏数 43
精华内容 17
关键字:

python抽象基类的作用

python 订阅