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中使用mongoengine操作MongoDB教程
Apr 24 Python
Django学习笔记之Class-Based-View
Feb 15 Python
Python语言描述最大连续子序列和
Dec 05 Python
Windows下安装Django框架的方法简明教程
Mar 28 Python
python通过Windows下远程控制Linux系统
Jun 20 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
Dec 03 Python
python制作mysql数据迁移脚本
Jan 01 Python
keras模型可视化,层可视化及kernel可视化实例
Jan 24 Python
Python可以实现栈的结构吗
May 27 Python
python安装读取grib库总结(推荐)
Jun 24 Python
python查询MySQL将数据写入Excel
Oct 29 Python
重构Python代码的六个实例
Nov 25 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
CI框架无限级分类+递归的实现代码
2016/11/01 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
PHP实现二维数组中的查找算法小结
2018/06/09 PHP
JavaScript面向对象编程
2008/03/02 Javascript
JQuery 中几个类选择器的简单使用介绍
2013/03/14 Javascript
使用JS取得焦点(focus)元素代码
2014/03/22 Javascript
JS实现iframe自适应高度的方法(兼容IE与FireFox)
2016/06/24 Javascript
详解bootstrap用dropdown-menu实现上下文菜单
2017/09/22 Javascript
深入浅析Vue中的slots/scoped slots
2018/04/03 Javascript
Vue触发式全局组件构建的方法
2018/11/28 Javascript
Nginx设置为Node.js的前端服务器方法总结
2019/03/27 Javascript
Node.js中Koa2在控制台输出请求日志的方法示例
2019/05/02 Javascript
深入探索VueJS Scoped CSS 实现原理
2019/09/23 Javascript
微信小程序之左右布局的实现代码
2019/12/13 Javascript
Javascript原生ajax请求代码实例
2020/02/20 Javascript
JavaScript数组排序功能简单实现
2020/05/14 Javascript
如何检测JavaScript中的死循环示例详解
2020/08/30 Javascript
vue全局使用axios的操作
2020/09/08 Javascript
Python验证企业工商注册码
2015/10/25 Python
Python中asyncore异步模块的用法及实现httpclient的实例
2016/06/28 Python
Python使用pydub库对mp3与wav格式进行互转的方法
2019/01/10 Python
python中报错&quot;json.decoder.JSONDecodeError: Expecting value:&quot;的解决
2019/04/29 Python
完美解决pycharm导入自己写的py文件爆红问题
2020/02/12 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
2020/08/31 Python
HTML5 Canvas如何实现纹理填充与描边(Fill And Stroke)
2013/07/15 HTML / CSS
Marlies Dekkers内衣荷兰官方网店:荷兰奢侈内衣品牌
2020/03/27 全球购物
linux面试题参考答案(9)
2015/01/07 面试题
高中体育教学反思
2014/01/29 职场文书
房地产销售员岗位职责
2015/04/11 职场文书
上诉状格式
2015/05/23 职场文书
圣诞晚会主持词
2015/07/01 职场文书
2019年手机市场的调研报告2篇
2019/10/10 职场文书
幼师必备:幼儿园期末教师评语50条
2019/11/01 职场文书
java项目构建Gradle的使用教程
2022/03/24 Java/Android
云服务器部署 Web 项目的实现步骤
2022/06/28 Servers
js 实现Material UI点击涟漪效果示例
2022/09/23 Javascript