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调用cmd命令行制作刷博器
Jan 13 Python
pycharm使用matplotlib.pyplot不显示图形的解决方法
Oct 28 Python
python制作图片缩略图
Apr 30 Python
浅析python 中大括号中括号小括号的区分
Jul 29 Python
python自动循环定时开关机(非重启)测试
Aug 26 Python
Python3 filecmp模块测试比较文件原理解析
Mar 23 Python
python opencv进行图像拼接
Mar 27 Python
Django ORM filter() 的运用详解
May 14 Python
Keras load_model 导入错误的解决方式
Jun 09 Python
使用keras实现Precise, Recall, F1-socre方式
Jun 15 Python
python装饰器代码深入讲解
Mar 01 Python
撤回我也能看到!教你用Python制作微信防撤回脚本
Jun 11 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
phpmyadmin3 安装配置图解教程
2012/03/29 PHP
PHP自定义大小验证码的方法详解
2013/06/07 PHP
深入理解JavaScript系列(17):面向对象编程之概论详细介绍
2015/03/04 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
2015/12/10 Javascript
js获取本机操作系统类型的两种方法
2015/12/19 Javascript
Javascript随机标签云代码实例
2016/06/21 Javascript
文本框只能输入数字的js代码(含小数点)
2016/07/10 Javascript
footer定位页面底部(代码分享)
2017/03/07 Javascript
整理关于Bootstrap过渡动画的慕课笔记
2017/03/29 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
详解React-Router中Url参数改变页面不刷新的解决办法
2018/05/08 Javascript
webpack4.x打包过程详解
2018/07/18 Javascript
对angularJs中ng-style动态改变样式的实例讲解
2018/09/30 Javascript
解决vue项目router切换太慢问题
2020/07/19 Javascript
[06:53]DOTA2每周TOP10 精彩击杀集锦vol.3
2014/06/25 DOTA
python实现倒计时的示例
2014/02/14 Python
Python读取网页内容的方法
2015/07/30 Python
Python实现将一个正整数分解质因数的方法分析
2017/12/14 Python
Python实现的质因式分解算法示例
2018/05/03 Python
用python生成1000个txt文件的方法
2018/10/25 Python
浅析PEP570新语法: 只接受位置参数
2019/10/15 Python
python中Pexpect的工作流程实例讲解
2021/03/02 Python
英国在线女鞋目的地:SIMMI
2018/12/27 全球购物
介绍一下grep命令的使用
2012/06/28 面试题
毕业生物理教师求职信
2013/10/17 职场文书
医院办公室主任职责
2013/12/29 职场文书
学习保证书范文
2014/04/30 职场文书
员工保密协议书
2014/09/27 职场文书
内乡县衙导游词
2015/02/05 职场文书
党员评议自我评价
2015/03/03 职场文书
《从现在开始》教学反思
2016/02/16 职场文书
Python标准库之typing的用法(类型标注)
2021/06/02 Python
Redis缓存-序列化对象存储乱码问题的解决
2021/06/21 Redis
通过Python把学姐照片做成拼图游戏
2022/02/15 Python
Java的Object类的九种方法
2022/04/13 Java/Android