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 相关文章推荐
TensorFlow平台下Python实现神经网络
Mar 10 Python
浅谈pyqt5中信号与槽的认识
Feb 17 Python
详解Python中的测试工具
Jun 09 Python
在Python中使用MongoEngine操作数据库教程实例
Dec 03 Python
基于python使用tibco ems代码实例
Dec 20 Python
使用TensorFlow直接获取处理MNIST数据方式
Feb 10 Python
Python HTMLTestRunner测试报告view按钮失效解决方案
May 25 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
Jun 18 Python
Keras 中Leaky ReLU等高级激活函数的用法
Jul 05 Python
linux mint中搜狗输入法导致pycharm卡死的问题
Oct 28 Python
python 模拟登录B站的示例代码
Dec 15 Python
python如何调用php文件中的函数详解
Dec 29 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.NET的入门教程
2006/10/09 PHP
学习php过程中的一些注意点的总结
2013/10/25 PHP
Yii框架上传图片用法总结
2016/03/28 PHP
如何通过View::first使用Laravel Blade的动态模板详解
2017/09/21 PHP
让innerHTML的脚本也可以运行起来
2006/07/01 Javascript
div层的移动及性能优化
2010/11/16 Javascript
jQuery validate插件实现ajax验证重复的2种方法
2016/01/22 Javascript
javascript显示上周、上个月日期的处理方法
2016/02/03 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
使用vue-cli编写vue插件的方法
2018/02/26 Javascript
vue+axios 前端实现的常用拦截的代码示例
2018/08/23 Javascript
微信小程序实现签到功能
2018/10/31 Javascript
Vue项目中使用WebUploader实现文件上传的方法
2019/07/21 Javascript
Vue.js中provide/inject实现响应式数据更新的方法示例
2019/10/16 Javascript
vue3 源码解读之 time slicing的使用方法
2019/10/31 Javascript
JavaScript 引用类型实例详解【数组、对象、严格模式等】
2020/05/13 Javascript
Element Steps步骤条的使用方法
2020/07/26 Javascript
python如何通过protobuf实现rpc
2016/03/06 Python
VSCode下好用的Python插件及配置
2018/04/06 Python
对Python 文件夹遍历和文件查找的实例讲解
2018/04/26 Python
Python3实现转换Image图片格式
2018/06/21 Python
Python读取英文文件并记录每个单词出现次数后降序输出示例
2018/06/28 Python
pycham查看程序执行的时间方法
2018/11/29 Python
详解python执行shell脚本创建用户及相关操作
2019/04/11 Python
如何将你的应用迁移到Python3的三个步骤
2019/12/22 Python
Python可视化工具如何实现动态图表
2020/10/23 Python
python实现网页录音效果
2020/10/26 Python
详解Pytorch显存动态分配规律探索
2020/11/17 Python
HTML5 audio标签使用js进行播放控制实例
2015/04/24 HTML / CSS
您的时尚,您的生活方式:DTLR Villa
2019/12/25 全球购物
法学专业自我鉴定
2014/02/05 职场文书
婚纱摄影师求职信
2014/03/07 职场文书
单位工程竣工验收方案
2014/03/16 职场文书
团日活动总结范文
2014/04/25 职场文书
领导班子三严三实对照检查材料
2014/09/25 职场文书
工程质检员岗位职责
2015/04/08 职场文书