Python如何定义有可选参数的元类


Posted in Python onJuly 31, 2020

问题

你想定义一个元类,允许类定义时提供可选参数,这样可以控制或配置类型的创建过程。

解决方案

在定义类的时候,Python允许我们使用 ``metaclass``关键字参数来指定特定的元类。 例如使用抽象基类:

from abc import ABCMeta, abstractmethod
class IStream(metaclass=ABCMeta):
  @abstractmethod
  def read(self, maxsize=None):
    pass

  @abstractmethod
  def write(self, data):
    pass

然而,在自定义元类中我们还可以提供其他的关键字参数,如下所示:

class Spam(metaclass=MyMeta, debug=True, synchronize=True):
  pass

为了使元类支持这些关键字参数,你必须确保在 __prepare__() , __new__() __init__() 方法中 都使用强制关键字参数。就像下面这样:

class MyMeta(type):
  # Optional
  @classmethod
  def __prepare__(cls, name, bases, *, debug=False, synchronize=False):
    # Custom processing
    pass
    return super().__prepare__(name, bases)

  # Required
  def __new__(cls, name, bases, ns, *, debug=False, synchronize=False):
    # Custom processing
    pass
    return super().__new__(cls, name, bases, ns)

  # Required
  def __init__(self, name, bases, ns, *, debug=False, synchronize=False):
    # Custom processing
    pass
    super().__init__(name, bases, ns)

讨论

给一个元类添加可选关键字参数需要你完全弄懂类创建的所有步骤, 因为这些参数会被传递给每一个相关的方法。 __prepare__() 方法在所有类定义开始执行前首先被调用,用来创建类命名空间。 通常来讲,这个方法只是简单的返回一个字典或其他映射对象。 __new__() 方法被用来实例化最终的类对象。它在类的主体被执行完后开始执行。 __init__() 方法最后被调用,用来执行其他的一些初始化工作。

当我们构造元类的时候,通常只需要定义一个 __new__() __init__() 方法,但不是两个都定义。 但是,如果需要接受其他的关键字参数的话,这两个方法就要同时提供,并且都要提供对应的参数签名。 默认的 __prepare__() 方法接受任意的关键字参数,但是会忽略它们, 所以只有当这些额外的参数可能会影响到类命名空间的创建时你才需要去定义 __prepare__() 方法。

通过使用强制关键字参数,在类的创建过程中我们必须通过关键字来指定这些参数。

使用关键字参数配置一个元类还可以视作对类变量的一种替代方式。例如:

class Spam(metaclass=MyMeta):
  debug = True
  synchronize = True
  pass

将这些属性定义为参数的好处在于它们不会污染类的名称空间, 这些属性仅仅只从属于类的创建阶段,而不是类中的语句执行阶段。 另外,它们在 __prepare__() 方法中是可以被访问的,因为这个方法会在所有类主体执行前被执行。 但是类变量只能在元类的 __new__()__init__() 方法中可见。

以上就是Python如何定义有可选参数的元类的详细内容,更多关于Python定义元类的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python笔记(叁)继续学习
Oct 24 Python
Python动态加载模块的3种方法
Nov 22 Python
通过Python爬虫代理IP快速增加博客阅读量
Dec 14 Python
详解python中requirements.txt的一切
Mar 03 Python
Python中几种导入模块的方式总结
Apr 27 Python
Python实现统计代码行的方法分析
Jul 12 Python
Python双向循环链表实现方法分析
Jul 30 Python
Windows下Anaconda2安装NLTK教程
Sep 19 Python
对python指数、幂数拟合curve_fit详解
Dec 29 Python
python按照多个条件排序的方法
Feb 08 Python
Python学习笔记之字符串和字符串方法实例详解
Aug 22 Python
python 遗传算法求函数极值的实现代码
Feb 11 Python
Python爬虫爬取糗事百科段子实例分享
Jul 31 #Python
Python如何对齐字符串
Jul 30 #Python
Python3爬虫关于代理池的维护详解
Jul 30 #Python
Python读写压缩文件的方法
Jul 30 #Python
Python3爬虫里关于代理的设置总结
Jul 30 #Python
Python 如何创建一个简单的REST接口
Jul 30 #Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
Jul 30 #Python
You might like
php addslashes和mysql_real_escape_string
2010/01/24 PHP
PHP添加Xdebug扩展的方法
2014/02/12 PHP
在laravel框架中实现封装公共方法全局调用
2019/10/14 PHP
PHP设计模式入门之状态模式原理与实现方法分析
2020/04/26 PHP
JS event使用方法详解
2008/04/28 Javascript
使用js检测浏览器是否支持html5中的video标签的方法
2014/03/12 Javascript
jquery $.trim()方法使用介绍
2014/05/21 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
利用Javascript实现简单的转盘抽奖
2017/02/13 Javascript
JS中使用media实现响应式布局
2017/08/04 Javascript
小程序视频列表中视频的播放与停止的示例代码
2018/07/20 Javascript
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
2018/09/13 Javascript
Vue中控制v-for循环次数的实现方法
2018/09/26 Javascript
对 Vue-Router 进行单元测试的方法
2018/11/05 Javascript
解决layui使用layui-icon出现默认图标的问题
2019/09/11 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
2019/09/17 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
Python 内置函数memoryview(obj)的具体用法
2017/11/23 Python
浅谈Python实现贪心算法与活动安排问题
2017/12/19 Python
python通过百度地图API获取某地址的经纬度详解
2018/01/28 Python
python实现斗地主分牌洗牌
2020/06/22 Python
完美解决TensorFlow和Keras大数据量内存溢出的问题
2020/07/03 Python
Python 如何创建一个简单的REST接口
2020/07/30 Python
python判断all函数输出结果是否为true的方法
2020/12/03 Python
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
新西兰购物网站:TheMarket NZ
2020/09/19 全球购物
创业计划书如何编写
2014/02/06 职场文书
商务英语广告词大全
2014/03/18 职场文书
村级四风对照检查材料
2014/08/24 职场文书
2014年加油站站长工作总结
2014/12/23 职场文书
MySQL获取所有分类的前N条记录
2021/05/07 MySQL
MySQL update set 和 and的区别
2021/05/08 MySQL
Python数据分析入门之教你怎么搭建环境
2021/05/13 Python
使用Spring处理x-www-form-urlencoded方式
2021/11/02 Java/Android
nginx之内存池的实现
2022/06/28 Servers
详解flex:1什么意思
2022/07/23 HTML / CSS