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的Flask框架中实现单元测试的教程
Apr 20 Python
Python实现TCP/IP协议下的端口转发及重定向示例
Jun 14 Python
Python3实现抓取javascript动态生成的html网页功能示例
Aug 22 Python
Python+树莓派+YOLO打造一款人工智能照相机
Jan 02 Python
tensorflow实现简单的卷积神经网络
May 24 Python
python实现将汉字保存成文本的方法
Nov 16 Python
介绍一款python类型检查工具pyright(推荐)
Jul 03 Python
python实现指定ip端口扫描方式
Dec 17 Python
Python闭包与装饰器原理及实例解析
Apr 30 Python
PHP基于phpqrcode类库生成二维码过程解析
May 28 Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
Jul 14 Python
python数字图像处理实现图像的形变与缩放
Jun 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
Session保存到数据库的php类分享
2011/10/24 PHP
php blowfish加密解密算法
2016/07/02 PHP
JavaScript修改css样式style
2008/04/15 Javascript
仿迅雷焦点广告效果(JQuery版)
2008/11/19 Javascript
URL地址中的#符号使用说明
2011/02/12 Javascript
鼠标滚轮控制网页横向移动实现思路
2013/03/22 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
2015/03/26 Javascript
JS实现简单的图书馆享元模式实例
2015/06/30 Javascript
微信小程序 地图(map)实例详解
2016/11/16 Javascript
jQuery实现模拟flash头像裁切上传功能示例
2016/12/11 Javascript
Bootstrap实现的经典栅格布局效果实例【附demo源码】
2017/03/30 Javascript
jquery 校验中国身份证号码实例详解
2017/04/11 jQuery
Angular2里获取(input file)上传文件的内容的方法
2017/09/05 Javascript
JS打印彩色菱形的实例代码
2018/08/15 Javascript
解决webpack多页面内存溢出的方法示例
2019/10/08 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2全新版本永雾林渊开启新篇章
2020/12/24 DOTA
python打开url并按指定块读取网页内容的方法
2015/04/29 Python
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
Python 字符串、列表、元组的截取与切片操作示例
2019/09/17 Python
python+selenium+PhantomJS抓取网页动态加载内容
2020/02/25 Python
python 工具 字符串转numpy浮点数组的实现
2020/03/14 Python
PyQt5 文本输入框自动补全QLineEdit的实现示例
2020/05/13 Python
全球航班旅行搜索网站:Cheapflights
2017/05/19 全球购物
Roxy荷兰官方网站:冲浪、滑雪板、服装和配件
2019/10/22 全球购物
new修饰符是起什么作用
2015/06/28 面试题
会计专业推荐信
2013/10/29 职场文书
十佳教师事迹材料
2014/01/11 职场文书
综合实践活动总结
2014/05/05 职场文书
通报表扬范文
2015/01/17 职场文书
2015年学校教育教学工作总结
2015/04/22 职场文书
毕业论文致谢怎么写
2015/05/14 职场文书
小学运动会通讯稿
2015/07/18 职场文书
班委竞选稿范文
2015/11/21 职场文书
2016年9月份红领巾广播稿
2015/12/21 职场文书
python第三方网页解析器 lxml 扩展库与 xpath 的使用方法
2021/04/06 Python