一、python中如何创建类?

1. 直接定义类

class A:
   a = 'a'

2. 通过type对象创建

在python中一切都是对象

在上面这张图中,A是我们平常在python中写的类,它可以创建一个对象a。其实A这个类也是一个对象,它是type类的对象,可以说type类是用来创建类对象的类,我们平常写的类都是type类创建的对象,再由创建的对象再去创建我们平常使用的对象,我们可以看看type的官方文档

type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type

type有另一种用法type(name, bases, dict)来创建类 中,name是这个类的名字,bases是这个类的基类(是一个元组),dict是这个类的属性(是一个字典),我们通过type实现上面的例子中A类的创建

A = type('A', (), {'a': 'a'})

二、什么是元类编程?

我们已经知道,类也是对象,那么我们在创建类的时候,可不可以控制类的创建过程?当然是可以的,这就是元类编程。

三、如何实现元类编程?

1. 在要定义的类中使用__new__方法

class A:
def __new__(cls, *args, **kwargs):
cls.a = 'a'
return super().__new__(cls, *args, **kwargs)

这样就实现了创建A类的时候,添加了一个类属性a(注意的是,__new__方法要返回一个创建的对象,当然,我们也可以返回其他东西;另一个注意点是__new__方法要在实例化的时候才会运行,所以,类属性a必须是在A实例化后才会出现)

2. 使用metaclass关键字,使用metaclass关键字的时候,我们要定义一个type类

class B(type):
def __init__(self, *args, **kwargs):
self.a = 'a'
super().__init__(*args, **kwargs) class A(metaclass=B):
pass

我们定义了一个B类继承type,在A类创建的时候传递关键字metaclass=B,就会执行B类种的代码,控制A类的创建,这个例子也是为A类添加了一个类属性a。我们还可以在B类中使用__init__,__call__方法。

四、python中元类编程执行的顺序

class MetaClass(type):
# 定义A类的时候就会调用
def __init__(self, *args, **kwargs):
print('MetaClass __init__')
super().__init__(*args, **kwargs) # 定义A类的时候,就会调用
def __new__(cls, *args, **kwargs):
print('MetaClass __new__')
# *args 里面包含了创建A类的参数
return super().__new__(cls, *args, **kwargs) # A实例化的时候才会去调用call
def __call__(self, *args, **kwargs):
print('MetaClass __call__')
# 这儿其实是去调用A类需要实例化的所有方法
return super().__call__(*args, **kwargs) class A(metaclass=MetaClass):
def __init__(self):
print('A __init__') def __new__(cls, *args, **kwargs):
print('A __new__')
return super().__new__(cls, *args, **kwargs) a = A() # 输出
MetaClass __new__
MetaClass __init__
MetaClass __call__
A __new__
A __init__

五、总结

使用元类编程可以让我们在创建类的时候,给类添加一些额外的信息。但元类编程是python中难以理解的地方之一,而且工作中,大部分时候都是不会用到的,我们普通的类定义方式就可以解决问题了,若果说有99%的时候你需要控制创建类的过程,那就使用元类编程吧。

理解元类,大家可以参考这篇文章 what are metaclass in python?

python 通过元类控制类的创建的更多相关文章

  1. Day 5-8 自定义元类控制类的实例化行为

    __call__方法: 对象后面加括号,触发执行. 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类( ...

  2. Python之元类详细解析

    一.补充内置函数isinstance和issubclass 1.isinstance是判断一个对象是不是由一个对象产生的 class Foo: pass obj=Foo() print(isinsta ...

  3. Python之元类详解

    一.引子 元类属于Python面向对象编程的深层魔法,99%的人都不得要领,一些自以为搞明白元类的人其实也是自圆其说,点到为止,从队元类的控制上来看就破绽百出,逻辑混乱: 二.什么是元类 一切源自于一 ...

  4. python 之元类

    定义类的两种方法: 1.class定义 2.type(类名,类的基类们,类的名称空间) # 定义类的三要素:类名.基类.名称空间 class_name = 'Chinese' class_bases ...

  5. 类和对象的创建过程(元类,__new__,__init__,__call__)

    一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...

  6. 【转】Python 之 元类

    原文链接: https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python      http://python.jo ...

  7. Python中元类

    元类(metaclass) 简单地说,元类就是一个能创建类的类,而类class 是由type创建的,class可以创建对象 type与object的关系详见:python中type和object 1. ...

  8. 转---一文读懂 python 的元类

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  9. python基础----元类metaclass

    1 引子 class Foo: pass f1=Foo() #f1是通过Foo类实例化的对象 python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载cl ...

随机推荐

  1. [Swift]LeetCode482. 密钥格式化 | License Key Formatting

    You are given a license key represented as a string S which consists only alphanumeric character and ...

  2. [Swift]LeetCode564. 寻找最近的回文数 | Find the Closest Palindrome

    Given an integer n, find the closest integer (not including itself), which is a palindrome. The 'clo ...

  3. [Swift]LeetCode957. N天后的牢房 | Prison Cells After N Days

    There are 8 prison cells in a row, and each cell is either occupied or vacant. Each day, whether the ...

  4. 一个简单IP防刷工具类, x秒内最多允许y次单ip操作

    IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...

  5. ubuntu-18.04 设置开机启动脚本

    ubuntu-18.04 设置开机启动脚本 参阅下列链接 https://askubuntu.com/questions/886620/how-can-i-execute-command-on-sta ...

  6. VirtualBox虚拟机克隆迁移步骤

    VirtualBox是常用的虚拟机管理软件,和VMware一样,用的很多.在使用过程中,有的时候需要对虚拟机进行迁移.比如我们原来的服务器,使用的win10操作系统,上面利用VirtualBox安装了 ...

  7. linux静态ip的设置

    我们经常使用虚拟机安装(我使用的linux版本是CentOS6.5),然后配置服务器的web环境,用于程序的调试.默认情况下,linux使用动态ip,每次启动linux时,它的ip地址都有可能发生变化 ...

  8. Carousel轮播图

     <div id="carousel-example-generic" class="carousel slide" data-ride="ca ...

  9. RabbitMQ学习笔记(三) 发布与订阅

    发布与订阅 在我们使用手机发送消息的时候,即可以选择给单个手机号码发送消息,也可以选择多个手机号码,群发消息. 前面学习工作队列的时候,我们使用的场景是一个消息只能被一个消费者程序实例接收并处理,但是 ...

  10. SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1

    在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...