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 相关文章推荐
easy_install python包安装管理工具介绍
Feb 10 Python
举例简单讲解Python中的数据存储模块shelve的用法
Mar 03 Python
Python解惑之True和False详解
Apr 24 Python
Python自定义简单图轴简单实例
Jan 08 Python
Python实现邮件的批量发送的示例代码
Jan 23 Python
python粘包问题及socket套接字编程详解
Jun 29 Python
python opencv实现证件照换底功能
Aug 19 Python
详解python中的模块及包导入
Aug 30 Python
python实现横向拼接图片
Mar 23 Python
Python字典实现伪切片功能
Oct 28 Python
Django执行源生mysql语句实现过程解析
Nov 12 Python
Window10上Tensorflow的安装(CPU和GPU版本)
Dec 15 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
Yii获取当前url和域名的方法
2015/06/08 PHP
php中preg_match的isU代表什么意思
2015/10/01 PHP
记录几个javascript有关的小细节
2007/04/02 Javascript
html5 canvas js(数字时钟)实例代码
2013/12/23 Javascript
javascript中拼接HTML字符串的最快、最好的方法
2014/06/07 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
JavaScript动态加载样式表的方法
2015/03/21 Javascript
JQuery选中checkbox方法代码实例(全选、反选、全不选)
2015/04/27 Javascript
js数组去重的方法汇总
2015/07/29 Javascript
jquery实现图片放大镜功能
2015/11/23 Javascript
Three.js基础部分学习
2017/01/08 Javascript
自定义vue全局组件use使用、vuex的使用详解
2017/06/14 Javascript
使用RN Animated做一个“添加购物车”动画的方法
2018/09/12 Javascript
js实现多个倒计时并行 js拼团倒计时
2019/02/25 Javascript
关于微信小程序获取小程序码并接受buffer流保存为图片的方法
2019/06/07 Javascript
ES6模板字符串和标签模板的应用实例分析
2019/06/25 Javascript
浅谈vue websocket nodeJS 进行实时通信踩到的坑
2020/09/22 NodeJs
vue+openlayers绘制省市边界线
2020/12/24 Vue.js
python类装饰器用法实例
2015/06/04 Python
使用python编写简单的小程序编译成exe跑在win10上
2018/01/15 Python
python3实现多线程聊天室
2018/12/12 Python
在linux下实现 python 监控usb设备信号
2019/07/03 Python
python super的使用方法及实例详解
2019/09/25 Python
在Python中画图(基于Jupyter notebook的魔法函数)
2019/10/28 Python
Python动态声明变量赋值代码实例
2019/12/30 Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
2020/06/02 Python
软件测试笔试题
2012/10/25 面试题
经贸日语毕业生自荐信
2013/11/03 职场文书
物理专业本科生自荐信
2014/01/30 职场文书
草船借箭教学反思
2014/02/03 职场文书
党员批评与自我批评
2014/02/12 职场文书
成龙洗发水广告词
2014/03/14 职场文书
2014年资料员工作总结
2014/11/18 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
工程部岗位职责
2015/02/10 职场文书
Python中使用Lambda函数的5种用法
2021/04/01 Python