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的urllib库提交WEB表单
Feb 24 Python
python处理cookie详解
Feb 07 Python
使用python实现拉钩网上的FizzBuzzWhizz问题示例
May 05 Python
Python数组条件过滤filter函数使用示例
Jul 22 Python
Python 专题六 局部变量、全局变量global、导入模块变量
Mar 20 Python
对Python生成汉字字库文字,以及转换为文字图片的实例详解
Jan 29 Python
Python如何爬取实时变化的WebSocket数据的方法
Mar 09 Python
django多对多表的创建,级联删除及手动创建第三张表
Jul 25 Python
Python turtle绘画象棋棋盘
Aug 21 Python
520使用Python实现“我爱你”表白
May 20 Python
python实现mask矩阵示例(根据列表所给元素)
Jul 30 Python
scrapy redis配置文件setting参数详解
Nov 18 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实时显示输出
2008/10/02 PHP
thinkphp3.x中display方法及show方法的用法实例
2016/05/19 PHP
PHP中register_shutdown_function函数的基础介绍与用法详解
2017/11/28 PHP
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
JavaScript中对象property的删除方法介绍
2014/12/30 Javascript
JQuery中使文本框获得焦点的方法实例分析
2015/02/28 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
2016/09/21 Javascript
js基础之DOM中document对象的常用属性方法详解
2016/10/28 Javascript
angularjs实现的前端分页控件示例
2017/02/10 Javascript
微信小程序 弹框和模态框实现代码
2017/03/10 Javascript
基于EasyUI的基础之上实现树形功能菜单
2017/06/28 Javascript
js编写简单的聊天室功能
2017/08/17 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
详解Vue CLI3配置之filenameHashing使用和源码设计使用和源码设计
2018/08/31 Javascript
微信小程序实现单选选项卡切换效果
2020/06/19 Javascript
jQuery实现的五星点评功能【案例】
2019/02/18 jQuery
layer.alert回调函数执行关闭弹窗的实例
2019/09/11 Javascript
js实现图片上传到服务器和回显
2020/01/19 Javascript
微信小程序利用for循环解决内容变更问题
2020/03/05 Javascript
VueCli生产环境打包部署跨域失败的解决
2020/11/13 Javascript
python抓取豆瓣图片并自动保存示例学习
2014/01/10 Python
跟老齐学Python之玩转字符串(3)
2014/09/14 Python
解读Python中degrees()方法的使用
2015/05/18 Python
解读Python编程中的命名空间与作用域
2015/10/16 Python
python并发2之使用asyncio处理并发
2017/12/21 Python
python实现简单tftp(基于udp协议)
2018/07/30 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
2018/08/31 Python
Python使用pyshp库读取shapefile信息的方法
2018/12/29 Python
使用pyinstaller打包PyQt4程序遇到的问题及解决方法
2019/06/24 Python
Python 使用 docopt 解析json参数文件过程讲解
2019/08/13 Python
创业计划书模版
2014/02/05 职场文书
活动总结范文
2014/08/30 职场文书
公司离职证明标准范本
2014/10/05 职场文书
公安领导班子四风问题个人整改措施思想汇报
2014/10/09 职场文书
追讨欠款律师函
2015/06/24 职场文书
Python 恐龙跑跑小游戏实现流程
2022/02/15 Python