zoukankan      html  css  js  c++  java
  • python abc模块

    面向对象的设计中,抽象类,接口这些必不可少的东西,在python中是如何提现的呢?

    python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现,在执行的时候python不严格要求你必须是继承指定的父类而来,只要在调用的时候你有相应的方法和属性就可以了,长的像鸭子你就是鸭子。

    也正是基于python这样的特性,python中没有interface的概念,有说interface并不是普遍存在的,而是作为一个特例出现在java中,为的是解决多继承的问题。python支持多继承,自然没有这个需要了。然而我们难免会有这样的需求:子类必须实现某些指定的方法和属性,否则就抛异常。使用一些笨方法自然是可以达到相同的效果,但是python为我们提供了abc模块。

    http://bbs.chinaunix.net/thread-771123-1-1.html

    java中的抽象类是为了实现c++中的抽象类和模板之类的东西
    接口是为了解决java不能多继承的问题

    很显然楼主是从java才开始接触面向对象程序设计的。实际上java的“接口”是一个特例而非普通现象。如果可以多继承的话,那还要接口干什么?

    实际上python才是最符合现实逻辑的“面向对象”
    python允许多继承,正如现实中,你既是公民也是纳税人,我们直接使用这些“类”而不需要特别的创建什么“纳税人接口”
    python中所有的类,都是抽象类,或者说根本不存在抽象类,类方法可以直接使用,“类”本身在定义的时候就已经实例化,你可以通过输入:某类[回车]看到其内存句柄。这是符合事实的,并且时简约明了的。
    而在C++和java当中,一个类定义了以后,肯定是占用了内存空间,但是同时他又没有实例化,如果要使用的话还得实例化一次,又要占用一些内存空间。而类定义所占用的内存空间,使用率很低。
    python中不存在“基类”的概念,也没有单根,更没有基本类型,所有的一切都是对象。
    python是无神论的最完美体现,没有亚当,没有上帝,没有鬼神,没有唯一的主。你爱信什么信什么,爱是什么是什么,没有任何约束,但是不能存在特殊。

    另外,python根本没有意去模仿java的接口,因为那完全没必要,python的标准类就完全包含java中的接口的所有功能。倒是模仿一下c++的模板会有些实际用途。

    好了,说完抽象类,接口的来历,我们看一看python中的abc模块是如何玩儿的:
    python-3.6.0-docs-html/library/abc.html?highlight=abc#module-abc
    https://www.python.org/dev/peps/pep-3119/

    from abc import ABCMeta, abstractmethod, abstractproperty
    
    
    class Drawable(metaclass=ABCMeta):
        """docstring for Drawable"""
    
        @abstractproperty
        def size(self):
            # return 'mysize'
            pass
    
        @abstractmethod
        def draw(self, x, y, scale=1.0):
            # print(x * scale, y * scale)
            pass
    
        def double_draw(self, x, y):
            self.draw(x, y, scale=2.0)
    
    
    class Cicle(Drawable):
        # 1. 使用继承的方法
        """docstring for Cicle"""
    
        def draw(self, x, y, scale=1.0):
            print(x * scale, y * scale)
    
        @property
        def size(self):
            return 'Cicle size'
    
    
    # Cicle如果没有override draw函数和size 属性,那么实例化的时候就会报错
    # TypeError: Can't instantiate abstract class Cicle with abstract methods draw, size
    c = Cicle()
    print(dir(c))
    c.draw(1, 2)
    c.double_draw(1, 2)
    print(isinstance(c, Drawable))  # True
    print(isinstance(c, Drawable))  # True
    
    
    class Rectangle():
        """docstring for Cicle"""
        pass
    
    # 使用抽象类函数的register方法注册具体的class
    # 通过注册的类,可以直接实例化,但是无法访问抽象类的所有成员
    # 其实就是只是让isinstance、issubclass识别注册的类为抽象类的成员和实例
    Drawable.register(Rectangle)
    
    r = Rectangle()
    # r.double_draw(1, 2) 
    # AttributeError: 'Rectangle' object has no attribute 'double_draw'
    print(dir(r))
    print(isinstance(r, Drawable))  # True
    print(issubclass(Rectangle, Drawable))  # True
    
    # ['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'double_draw', 'draw', 'size']
    # 1.0 2.0
    # 2.0 4.0
    # True
    # True
    # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    # True
    # True
    # [Finished in 0.2s]
    
  • 相关阅读:
    Java实现 LeetCode 111 二叉树的最小深度
    Java实现 LeetCode 111 二叉树的最小深度
    Java实现 LeetCode 111 二叉树的最小深度
    Winform最基础的DBHelper类
    Winform最基础的DBHelper类
    Winform最基础的DBHelper类
    在MFC程序中使用XML文件配置工具栏
    C++开发必看 四种强制类型转换的总结
    MFC 在对话框显示图片的多种方法
    用MFC实现WebGUI--(CDHtmlDialog)
  • 原文地址:https://www.cnblogs.com/wancy86/p/6269553.html
Copyright © 2011-2022 走看看