1.抽象基类:

继承的约束与协议

__doc__ = """
抽象基类: 继承的约束与协议# 抽象基类 --- 有点java的味道,也有点golang的味道,继承,协议,接口1.抽象基类不能实例化2.必要时可以要求子类实现基类指定的抽象方法# 抽象基类的目的:1.处理继承问题方面更加规范、系统2.明确调用之间的相互关系3.使得继承层次更加清晰4.限定子类实现的方法# 参考
https://www.osgeo.cn/cpython/library/abc.html   # 介绍
https://www.python.org/dev/peps/pep-3119/   # 缘由
https://www.cnblogs.com/traditional/p/11731676.html # 使用
"""import abcclass Base(abc.ABC):@abc.abstractmethod  # 要求子类实现指定协议,抽象方法用@abstractmethod装饰器标记,而且定义体中通常只有文档字符串.def my_protocol(self):"""要求子类实现的自定义协议"""def not_protocol(self):"""不要求子类实现的自定义协议"""@classmethoddef __subclasshook__(cls, subclass):  # 同时作用于isinstance和issubclass"""此方法应返回 True , False 或 NotImplemented .如果它回来 True , the 子类 被认为是ABC的一个子类。如果它回来 False , the 子类 不被认为是ABC的一个子类,即使它通常是ABC的一个子类。如果它回来 NotImplemented ,子类检查继续使用常规机制。"""# print("subclass.__mro__:", subclass.__mro__)  # 继承树if cls is Base:if any("my_protocol" in B.__dict__ for B in subclass.__mro__):return Trueelse:return Falsereturn NotImplemented# 显式继承Base
class MyClass(Base):"""子类"""def my_protocol(self):pass# 显式继承Base
class MyClass2(Base):"""子类"""def my_protocol(self):pass@Base.register
class MyClass3():"""虚拟子类:issubclass和isinstance等函数都能识别,但是注册的类不会从抽象基类中继承任何方法或属性."""k = MyClass()
print(isinstance(k, Base))  # True
print(issubclass(MyClass, Base))  # Truek2 = MyClass2()
print(isinstance(k2, Base))  # True
print(issubclass(MyClass2, Base))  # Truek3 = MyClass3()
print(isinstance(k3, Base))  # False
print(issubclass(MyClass3, Base))  # False

2.元类:

用来拦截和修改 继承此元类 的子类的 创建

__doc__ = """
元类: 用来拦截和修改 继承此元类 的子类的 创建# 为一个类定义确定适当的元类是根据以下规则:1.如果没有基类且没有显式指定元类,则使用 type();2.如果给出一个显式元类而且 不是 type() 的实例,则其会被直接用作元类;3.如果给出一个 type() 的实例作为显式元类,或是定义了基类,则使用最近派生的元类。# 目的了解元类的目的前需要先知道普通继承的作用与特点:继承的特点:<1>减少代码量和灵活指定型类<2>子类具有父类的方法和属性<3>子类不能继承父类的私有方法或属性<4>子类可以添加新的方法<5>子类可以修改父类的方法可以看到所有涉及到变动的特点都需要子类中实现,这样的话,对于某些固定模式的变动就需要子类中重复实现,增加子类中的代码量,或者所有子类固定继承某一个中间类,并在中间类的__new__中根据子类模式去创建,元类就可以理解为python中单独提出来的中间类,而一切类的创建最终都会调用type.__new__(cls, classname, bases, attrs)元类的使用就是在子类创建时拦截并修改,可以依据子类的特点增加或修改属性.# 参考:
https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__new__
https://docs.python.org/zh-cn/3/reference/datamodel.html#metaclasses"""import abc
from six import add_metaclass, with_metaclass  # py2和py3的桥梁,元类相关的变化很大,可通过six做兼容.Meta = abc.ABCMeta# 通用做法。
@add_metaclass(Meta)
class MyClass(object):pass# 在Python 3 等价于
class MyClass(object, metaclass=Meta):pass# 在Python 2.x (x >= 6)中等价于
class MyClass(object):__metaclass__ = Metapass# 或者直接调用装饰器,这里也能看出来装饰器就是个方法包装而已。
class MyClass(object):passMyClass = add_metaclass(Meta)(MyClass)# 再或者用 with_metaclass
class MyClass(object, with_metaclass(Meta)):passdef with_metaclass(meta, *bases):  # 代码摘自sqlalchemy中对元类的包装,采用了类似six.with_metaclass的方式"""Create a base class with a metaclass.Drops the middle class upon creation.Source: http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/"""class metaclass(meta):__call__ = type.__call____init__ = type.__init__def __new__(cls, name, this_bases, d):if this_bases is None:return type.__new__(cls, name, (), d)return meta(name, bases, d)return metaclass("temporary_class", None, {})# 举例部分# 继承type 创建元类
class SayMetaClass(type):# 用type动态生成类的的三个重要参数:类名称、父类、属性def __new__(cls, name, bases, attrs):# 创造"天赋"attrs['say_' + name] = lambda self, value, saying=name: print(saying + ',' + value + '!')# 类名称、父类、属性 生成元类return type.__new__(cls, name, bases, attrs)# 继承元类 创建类
# class Hello(object, metaclass=SayMetaClass):
class Hello(object, with_metaclass(SayMetaClass)):pass# 创建实列
hello = Hello()
# 调用实例方法
hello.say_Hello('world!')# 普通类的创建与继承
class Man:def __new__(cls, name, age):  # 静态方法print('Man.__new__ called.', getattr(cls, 'work_copy'))  # 能传过来return super(Man, cls).__new__(cls)  # -->self# 对比普通类的继承与创建class Person(Man):"""普通继承对象是由 __new__() 和 __init__() 协作构造完成的 (由 __new__() 创建,并由 __init__() 定制),所以 __init__() 返回的值只能是 None,否则会在运行时引发 TypeError。"""def __new__(cls, name, age, work):  # 可以不写,默认继承了Man.__new__print('Person.__new__ called.')cls.work_copy = work# return super(Person, cls).__new__(cls, name, age)  # -->Man.__new__cls = super(Person, cls).__new__(cls, name, age)  # 根据需要修改新创建的实例再将其返回cls.work = work  # 可以看到,__new__也是可以做__init__的数值绑定的return clsdef __init__(self, name, age, work):  # 参数与__new__必须一致,__new__的后续构造print('Person.__init__ called.')self.name = nameself.age = age# self.work = workdef __str__(self):return '<Person: %s %s %s>' % (self.name, self.age, self.work)zhangsan = Person('zhangsan', 24, '张三')
print(zhangsan)

Python学习:抽象类以及元类相关推荐

  1. 【Python面试题】-元类

    [Python面试题]-元类 1.Python 中类方法.类实例方法.静态方法有何区别? 类方法:是类对象的方法,在定义时需要在上方使用"@classmethod"进行装饰,形参为 ...

  2. Python进阶:理解元类创建类ABCMeta

    Python进阶:Python进阶:理解元类创建类ABCMeta 一.理解元类(Meta class) 1.1 元类直观理解 1.2 Python官方文档给出的元类描述 二.理解抽象基类(ABC, A ...

  3. 两句话轻松掌握python最难知识点——元类

    两句话掌握python最难知识点--元类 千万不要被所谓"元类是99%的python程序员不会用到的特性"这类的说辞吓住.因为每个中国人,都是天生的元类使用者 学懂元类,你只需要知 ...

  4. python的抽象类详解_Python抽象类以及元类

    抽象基类: 继承的约束与协议 __doc__ = """ 抽象基类: 继承的约束与协议 # 抽象基类 --- 有点java的味道,也有点golang的味道,继承,协议,接 ...

  5. Python基础笔记_Day12_Python元类、type动态创建类、Python动态创建方法、Python运算符、Python发邮件、短信

    Day12_Python元类.type动态创建类.Python动态创建方法.Python运算符重载.Python发邮件.短信 12.01_Python语言基础(类对象)(熟悉) 12.02_Pytho ...

  6. python学习,什么是类?

    一.介绍 在 Python 中,面向对象编程主要有两个主题,就是类和类实例 类与实例: 类与实例相互关联着:类是对象的定义,而实例是"真正的实物",它存放了类中所定义的对象 的具体 ...

  7. Python面向对象魔法、元类简介及使用

    文章目录 一.反射实战案例 二.面向对象魔法方法 三.魔法方法笔试题 四.元类简介 五.产生类的两种方式 六.元类基本使用 七.元类进阶 一.反射实战案例 1.获取配置文件中所有大写的配置 小写的直接 ...

  8. python——type()、metaclass元类和精简ORM框架

    1.type()函数 #type()函数既可以返回一个对象的类型,又可以创建出新的类型, # 比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object).. ...

  9. python学习高级篇(part10)--类对象的特殊方法和特殊属性

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__del__()` 类对象的特殊方法之`__getattr__()` 类对象的特殊方法之`__getitem__ ...

最新文章

  1. C++中的空类与空结构体大小
  2. 常用的adb命令收集
  3. linux内核模块配置,如何为linux内核模块开发配置clang_complete?
  4. HDU - 4578Transformation——线段树+区间加法修改+区间乘法修改+区间置数+区间和查询+区间平方和查询+区间立方和查询
  5. [OT]我的2010(加班无极限)
  6. python3 enumerate()函数笔记
  7. java中identifiers什么意思_javassist.是什么意思
  8. 软件工程基础之需求分析
  9. AngularJS------Error: Cannot find module '@angular-devkit/core'
  10. Pattern 模式器: Matcher 匹配器
  11. c++获取子类窗口句柄位置_C++中各种获取窗口句柄的方法
  12. discuz源代码分析
  13. 情感分类介绍及发展方向
  14. google翻译的一个错误
  15. 解读arduino读取模拟信号实例
  16. android 获取粗略位置_从Android上的GPS提供商处获取*粗略*位置
  17. 形容词记忆(二):ful,ous,ant后缀常用词
  18. Quasi-Newton拟牛顿法(共轭方向法)
  19. c语言中scanf(%d%*c, n);的意思。
  20. Go Moudle笔记

热门文章

  1. 应用大数据 助绿色出行
  2. 谨纪念第一次面试,电话面试,百度一面。。
  3. 重磅 | 中国电信发布5G时代区块链智能手机白皮书
  4. MATLAB实现遗传算法、模拟退火遗传算法求解避障路径规划问题——计算智能作业
  5. nvidia控制面板点了没反应win7_控制面板无响应怎么办_为什么nvidia控制面板打不开图文步骤...
  6. Flink - 尚硅谷- 大数据高级 Flink 技术精讲 - 2
  7. 学堂在线 python_Python作业1:Scrapy爬取学堂在线+链家二手房
  8. 学堂在线《工程伦理》第十一章课后习题及答案(仅供参考)
  9. 图文并茂的前端面试分享(成渝地区专用)
  10. Spark中使用c3p0连接池