Python 使用元类type创建类对象常见应用详解


Posted in Python onOctober 17, 2019

本文实例讲述了Python 使用元类type创建类对象。分享给大家供大家参考,具体如下:

type("123") 可以查看变量的类型;同时 type("类名",(父类),{类属性:值,类属性2:值}) 可以创建一个类。

在Python中不建议一个函数具有不同的功能(重载);type()具有不同的功能是为了兼容之前的版本。

类可以创建实例对象,类对象是由元类创建的。 (元类创建类,类创建实例对象)

type就是元类(type本质上就是一个类)

demo.py(用元类type创建类):

# 通过class关键字创建类
class MyClass1(object):
  name = "张三" # 类属性 (所有实例对象共用)
  age = 23
# 通过type创建类。 type()返回的是创建的类对象的引用。
Test2 = type("MyClass2",(object,),{"name":"张三","age":23}) # Test2是MyClass2类的引用,一般变量名和类名保持一致。
print(Test2()) # <__main__.MyClass2 object at 0x7fa05a4ca9e8>

demo.py(用type创建带有方法的类):

# 实例方法
def print_b(self):
  print(self.num)
# 静态方法
@staticmethod
def print_static():
  print("----haha-----")
# 类方法
@classmethod
def print_class(cls):
  print(cls.num)
# 用type创建类
B = type("B", (object,), {"num":100, "print_b": print_b, "print_static": print_static, "print_class": print_class})
b = B()
b.print_b()   # 100
b.print_static() # ----haha-----
b.print_class()  # 100

元类的应用

在定义一个类的时候可以为其指定__metaclass__属性(指定创建该类的元类),默认使用type元类创建类对象。

通过指定自定义的元类,可以对类的创建进行拦截。可以对类名、继承的父类、属性(方法)做一些预处理。

例如:将类名大写,默认继承object类,添加、修改属性(方法)名(私有属性的伪私有化就是通过修改属性名实现的)。

装饰器是对函数进行功能扩展(不用修改原代码),而元类可以对类进行功能扩展(添加额外的属性/方法)。

demo.py(用函数指定__metaclass__属性):

#-*- coding:utf-8 -*-
def upper_attr(class_name, class_parents, class_attr):
  # class_name 会保存类的名字 Foo
  # class_parents 会保存类的父类 object
  # class_attr 会以字典的方式保存所有的类属性/方法
  # 遍历属性字典,把不是__开头的属性名字变为大写
  new_attr = {}
  for name, value in class_attr.items():
    if not name.startswith("__"):
      new_attr[name.upper()] = value
  # 调用type来创建一个类
  return type(class_name, class_parents, new_attr)
class Foo(object, metaclass=upper_attr): # python3的方式
  # python2.x的方式。
  # __metaclass__ = upper_attr # 设置Foo类的元类为upper_attr
  bar = 'bip'
print(hasattr(Foo, 'bar'))
print(hasattr(Foo, 'BAR'))
f = Foo()
print(f.BAR)

demo.py(用类指定__metaclass__属性):

class UpperAttrMetaClass(type):
  # __new__ 是在__init__之前被调用的特殊方法
  # __new__是用来创建对象并返回之的方法
  # 而__init__只是用来将传入的参数初始化给对象
  # 你很少用到__new__,除非你希望能够控制对象的创建
  # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
  # 如果你希望的话,你也可以在__init__中做些事情
  # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
  def __new__(cls, class_name, class_parents, class_attr):
    # 遍历属性字典,把不是__开头的属性名字变为大写
    new_attr = {}
    for name, value in class_attr.items():
      if not name.startswith("__"):
        new_attr[name.upper()] = value
    # 方法1:通过'type'来做类对象的创建
    return type(class_name, class_parents, new_attr)
    # 方法2:复用type.__new__方法
    # 这就是基本的OOP编程,没什么魔法
    # return type.__new__(cls, class_name, class_parents, new_attr)
# python3的用法
class Foo(object, metaclass=UpperAttrMetaClass):
  bar = 'bip'
# python2的用法
# class Foo(object):
#   __metaclass__ = UpperAttrMetaClass
#   bar = 'bip'
print(hasattr(Foo, 'bar'))
# 输出: False
print(hasattr(Foo, 'BAR'))
# 输出:True
f = Foo()
print(f.BAR)
# 输出:'bip'

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python中is与==判断的区别
Mar 28 Python
Python操作Oracle数据库的简单方法和封装类实例
May 07 Python
python微信公众号之关键词自动回复
Jun 15 Python
python3结合openpyxl库实现excel操作的实例代码
Sep 11 Python
关于Python中定制类的比较运算实例
Dec 19 Python
kafka监控获取指定topic的消息总量示例
Dec 23 Python
Python JSON编解码方式原理详解
Jan 20 Python
python 线性回归分析模型检验标准--拟合优度详解
Feb 24 Python
解决django xadmin主题不显示和只显示bootstrap2的问题
Mar 30 Python
简单了解python列表和元组的区别
May 14 Python
PyCharm最新激活码(2020/10/27全网最新)
Oct 27 Python
python 检测nginx服务邮件报警的脚本
Dec 31 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
Oct 17 #Python
浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估
Oct 17 #Python
Python 3.8正式发布重要新功能一览
Oct 17 #Python
Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】
Oct 17 #Python
python实现复制文件到指定目录
Oct 16 #Python
如何解决django-celery启动后迅速关闭
Oct 16 #Python
Python发送邮件的实例代码讲解
Oct 16 #Python
You might like
php启用zlib压缩文件的配置方法
2013/06/12 PHP
全面解析PHP操作Memcache基本函数
2016/07/14 PHP
PHP创建文件及写入数据(覆盖写入,追加写入)的方法详解
2019/02/15 PHP
使用EXT实现无刷新动态调用股票信息
2008/11/01 Javascript
javascript 学习之旅 (1)
2009/02/05 Javascript
jQuery 方法大全方便学习参考
2010/02/25 Javascript
js弹窗代码 可以指定弹出间隔
2010/07/03 Javascript
最好用的省市二级联动 原生js实现你值得拥有
2013/09/22 Javascript
js禁止页面使用右键(简单示例代码)
2013/11/13 Javascript
jquery中html、val与text三者属性取值的联系与区别介绍
2013/12/29 Javascript
javascript感应鼠标图片透明度显示的方法
2015/02/24 Javascript
JS实现控制表格内指定单元格内容对齐的方法
2015/03/30 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
2015/07/18 Javascript
JavaScript中数组去除重复的三种方法
2016/04/22 Javascript
vue动态生成dom并且自动绑定事件
2017/04/19 Javascript
详谈JS中数组的迭代方法和归并方法
2017/08/11 Javascript
vue项目中使用tinymce编辑器的步骤详解
2018/09/11 Javascript
angular6 利用 ngContentOutlet 实现组件位置交换(重排)
2018/11/02 Javascript
微信小程序当前时间时段选择器插件使用方法详解
2018/12/28 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
Python多线程编程简单介绍
2015/04/13 Python
Python OpenCV读取png图像转成jpg图像存储的方法
2018/10/28 Python
python读取txt文件,去掉空格计算每行长度的方法
2018/12/20 Python
django 微信网页授权认证api的步骤详解
2019/07/30 Python
Django框架组成结构、基本概念与文件功能分析
2019/07/30 Python
利用python实现汉字转拼音的2种方法
2019/08/12 Python
Python 继承,重写,super()调用父类方法操作示例
2019/09/29 Python
python实现一次性封装多条sql语句(begin end)
2020/06/06 Python
廉价连衣裙和婚纱礼服在线销售:Tbdress
2019/02/28 全球购物
必须要使用游标的SQL语句有那些
2012/05/07 面试题
测绘工程本科生求职信
2013/10/10 职场文书
危爆物品安全大检查大整治工作方案
2014/05/03 职场文书
2014年组织委员工作总结
2014/12/01 职场文书
2014年创先争优工作总结
2014/12/11 职场文书
golang 实用库gotable的具体使用
2021/07/01 Golang
剧场版《转生恶役只好拔除破灭旗标》公开最新视觉图 2023年上映
2022/04/02 日漫