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 Socket编程入门教程
Jul 11 Python
按日期打印Python的Tornado框架中的日志的方法
May 02 Python
python控制台中实现进度条功能
Nov 10 Python
浅谈python对象数据的读写权限
Sep 12 Python
浅谈pandas中shift和diff函数关系
Apr 08 Python
Python实现接受任意个数参数的函数方法
Apr 21 Python
Python处理菜单消息操作示例【基于win32ui模块】
May 09 Python
Python 中包/模块的 `import` 操作代码
Apr 22 Python
pytorch 加载(.pth)格式的模型实例
Aug 20 Python
kafka监控获取指定topic的消息总量示例
Dec 23 Python
详解python中groupby函数通俗易懂
May 14 Python
PyCharm 光标变成黑块的解决方式
Feb 06 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下实现伪 url 的超简单方法[转]
2007/09/24 PHP
UCenter Home二次开发指南
2009/05/28 PHP
PHP similar_text 字符串的相似性比较函数
2010/05/26 PHP
PHP编程之设置apache虚拟目录
2016/07/08 PHP
thinkphp5.1框架实现格式化mysql时间戳为日期的方式小结
2019/10/10 PHP
了解一点js的Eval函数
2012/07/26 Javascript
js调用AJAX时Get和post的乱码解决方法
2013/06/04 Javascript
原生js和jQuery随意改变div属性style的名称和值
2014/10/22 Javascript
对Web开发中前端框架与前端类库的一些思考
2015/03/27 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
2016/06/07 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
jQuery.uploadify文件上传组件实例讲解
2016/09/23 Javascript
Bootstrap Img 图片样式(推荐)
2016/12/13 Javascript
使用vue.js写一个tab选项卡效果
2017/03/25 Javascript
jq checkbox 的全选并ajax传参的实例
2017/04/01 Javascript
Vue异步组件使用详解
2017/04/08 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
Zookeeper接口kazoo实例解析
2018/01/22 Python
Python迭代器和生成器定义与用法示例
2018/02/10 Python
Python使用爬虫爬取静态网页图片的方法详解
2018/06/05 Python
python得到电脑的开机时间方法
2018/10/15 Python
django中SMTP发送邮件配置详解
2019/07/19 Python
基于Python2、Python3中reload()的不同用法介绍
2019/08/12 Python
浅谈Python爬虫原理与数据抓取
2020/07/21 Python
理解Django 中Call Stack机制的小Demo
2020/09/01 Python
HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码
2020/04/10 HTML / CSS
HTML5单选框、复选框、下拉菜单、文本域的实现代码
2020/12/01 HTML / CSS
茵宝(Umbro)英国官方商店:英国足球服装生产商
2016/12/29 全球购物
服务中心夜班服务员岗位职责
2013/11/27 职场文书
工厂总经理岗位职责
2014/02/07 职场文书
工商管理专业毕业生求职信
2014/05/26 职场文书
2014年教师节红领巾广播稿
2014/09/10 职场文书
熟背这些句子,让您的英语口语突飞猛进(135句)
2019/09/06 职场文书
python文件目录操作之os模块
2021/05/08 Python
这样写python注释让代码更加的优雅
2021/06/02 Python
Python字典和列表性能之间的比较
2021/06/07 Python