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实现将英文单词表示的数字转换成阿拉伯数字的方法
Jul 02 Python
解决Scrapy安装错误:Microsoft Visual C++ 14.0 is required...
Oct 01 Python
python实现媒体播放器功能
Feb 11 Python
python编程使用协程并发的优缺点
Sep 20 Python
Django框架使用mysql视图操作示例
May 15 Python
python 实现返回一个列表中出现次数最多的元素方法
Jun 11 Python
Django模板Templates使用方法详解
Jul 19 Python
Python使用指定端口进行http请求的例子
Jul 25 Python
python实现最速下降法
Mar 24 Python
PyQt5 控件字体样式等设置的实现
May 13 Python
Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性(推荐)
Jul 03 Python
Django Form常用功能及代码示例
Oct 13 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使用$_POST或$_SESSION[]向js函数传参
2014/09/16 PHP
Centos7安装swoole扩展操作示例
2020/03/26 PHP
jquery创建一个ajax关键词数据搜索实现思路
2013/02/26 Javascript
给Flash加一个超链接(推荐使用透明层)兼容主流浏览器
2013/06/09 Javascript
MyEclipse取消验证Js的两种方法
2013/11/14 Javascript
JavaScript中通过prototype属性共享属性和方法的技巧实例
2015/03/13 Javascript
每天一篇javascript学习小结(Boolean对象)
2015/11/12 Javascript
AngularJS入门教程之控制器详解
2016/07/27 Javascript
jQuery使用siblings获取某元素所有同辈(兄弟姐妹)元素用法示例
2017/01/30 Javascript
vue学习笔记之指令v-text &amp;&amp; v-html &amp;&amp; v-bind详解
2017/05/12 Javascript
浅谈Koa服务限流方法实践
2017/10/23 Javascript
JS中双击和单击事件冲突的解决方法
2018/04/09 Javascript
Js中将Long转换成日期格式的实现方法
2018/06/05 Javascript
js form表单input框限制20个字符,10个汉字代码实例
2019/04/12 Javascript
vue登录注册实例详解
2019/09/14 Javascript
[35:44]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG
2014/05/26 DOTA
[01:15:00]LGD vs Mineski Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
[49:08]OpTic vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
浅谈python迭代器
2017/11/08 Python
pyqt5 获取显示器的分辨率的方法
2019/06/18 Python
python分割一个文本为多个文本的方法
2019/07/22 Python
Django 权限认证(根据不同的用户,设置不同的显示和访问权限)
2019/07/24 Python
python Django编写接口并用Jmeter测试的方法
2019/07/31 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
2020/05/19 Python
解决TensorFlow程序无限制占用GPU的方法
2020/06/30 Python
机械化及自动化毕业生的自我评价分享
2013/11/06 职场文书
关于赌博的检讨书
2014/01/08 职场文书
实习单位接收函模板
2014/01/10 职场文书
小区停车场管理制度
2014/01/27 职场文书
小学生成长感言
2014/01/30 职场文书
2014年党员公开承诺书范文
2014/03/28 职场文书
授权委托书
2014/07/31 职场文书
创先争优演讲稿
2014/09/15 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
关于感恩的歌曲整理(8首)
2019/08/14 职场文书
JS轻量级函数式编程实现XDM二
2022/06/16 Javascript