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的Django框架中forms表单类的使用方法详解
Jun 21 Python
python 打印出所有的对象/模块的属性(实例代码)
Sep 11 Python
python实现的AES双向对称加密解密与用法分析
May 02 Python
python处理按钮消息的实例详解
Jul 11 Python
Python实现将文本生成二维码的方法示例
Jul 18 Python
利用Python批量提取Win10锁屏壁纸实战教程
Mar 27 Python
Django压缩静态文件的实现方法详析
Aug 26 Python
Python3 实现串口两进程同时读写
Jun 12 Python
Python图像处理PIL各模块详细介绍(推荐)
Jul 17 Python
Django将默认的SQLite更换为MySQL的实现
Nov 18 Python
ansible-playbook实现自动部署KVM及安装python3的详细教程
May 11 Python
Python如何实现FTP功能
May 28 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
ThinkPHP的模版中调用session数据的方法
2014/07/01 PHP
ThinkPHP模板循环输出Volist标签用法实例详解
2016/03/23 PHP
Linux下快速搭建php开发环境
2017/03/13 PHP
php利用ob_start()清除输出和选择性输出的方法
2018/01/18 PHP
PHP大文件切割上传功能实例分析
2019/07/01 PHP
laravel validate 设置为中文的例子(验证提示为中文)
2019/09/29 PHP
javascript 兼容所有浏览器的DOM扩展功能
2012/08/01 Javascript
Seajs的学习笔记
2014/03/04 Javascript
详解AngularJS的通信机制
2015/06/18 Javascript
javascript比较两个日期相差天数的方法
2015/07/23 Javascript
莱鸟介绍javascript onclick事件
2016/01/06 Javascript
JQuery的Pager分页器实现代码
2016/05/03 Javascript
每日十条JavaScript经验技巧(二)
2016/06/23 Javascript
纯javascript版日历控件
2016/11/24 Javascript
javascript中活灵活现的Array对象详解
2016/11/30 Javascript
JavaScript组成、引入、输出、运算符基础知识讲解
2016/12/08 Javascript
jquery.zclip轻量级复制失效问题
2017/01/08 Javascript
JS传参及动态修改页面布局
2017/04/13 Javascript
使用vue-cli编写vue插件的方法
2018/02/26 Javascript
vue 2.1.3 实时显示当前时间,每秒更新的方法
2018/09/16 Javascript
微信小程序下拉框功能的实例代码
2018/11/06 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
微信小程序以7天为周期连续签到7天功能效果的示例代码
2020/08/20 Javascript
js+canvas实现图片格式webp/png/jpeg在线转换
2020/08/22 Javascript
解决vue侦听器watch,调用this时出现undefined的问题
2020/10/30 Javascript
Python break语句详解
2014/03/11 Python
玩转python爬虫之URLError异常处理
2016/02/17 Python
python 爬取免费简历模板网站的示例
2020/09/27 Python
运行Python编写的程序方法实例
2020/10/21 Python
Html5写一个简单的俄罗斯方块小游戏
2019/12/03 HTML / CSS
工程师求职简历的自我评价分享
2013/10/10 职场文书
管理心得体会
2013/12/28 职场文书
三严三实对照检查材料
2014/08/25 职场文书
党支部三严三实对照检查材料思想汇报
2014/09/29 职场文书
2015年中个人总结范文
2015/03/10 职场文书
小学安全工作总结2015
2015/05/18 职场文书