简介
元类, 一个神奇的概念, 从陌生到熟悉到深陷其魅力仅仅花费我3天时间.
元类是什么?
维基百科说, 元类是一种实体的类的类, 普通的类定义特定实体的属性及行为, 元类定义特定的类的属性及行为.
python说, 元类是继承自type的类.
owef说, 元类是ORM框架、自动切换代理IP、单例模式等场景中常见的一种类.
为了更好的理解并应用元类, 必须懂其意、知其形、善其变, 方可称大师.
(本文非入门贴, 近用于记录元类的相关知识和应用场景)
文章目录
- 预备知识
- 使用场景
- 参考链接
预备知识
- 基础概念
- 类内置方法
基础概念
1.python中一切对象都是type类型的子类型, 包括: int、str、set等
2.元类是由type衍生而出, 所以调用元类的类需要先继承自一个type(自定义类, object, dict, list, set, int, str等), python3默认继承自object, 所以无需显示指定.
3.元类的结构变更操作都在元类的__new__()方法中完成的
类内置方法的作用及调用顺序
1.__new__()、__init__(self)、__call__(self)__new__()负责创建一个实例对象, 在调用类创建对象时, 该方法作为一个类方法被自动调用. 如果该方法返回了一个实例, 实例会自动调用__init__(self)方法对实例进行初始化; 如果无返回值或返回的不是一个实例, 返回值将不会自动调用__init__(self)方法
2.__init__(self)负责对new返回的实例对象进行实例属性的初始化
3.__call__(self)负责实例化对象的函数调用, 在实例化对象被作为函数调用时会调用该方法
综上所述, 类内置方法的调用顺序为: __new__()、__init__(self)、__call__(self)
元类使用最佳场景
- 单例模式
- ORM框架
- 爬虫自动设置IP代理
元类可将一组类的公共属性、方法进行封装,节省子类创建方法时的开销
元类实现单例模式
tips: __new__()方法为类方法, 主要负责改变类的结构, 如预制一些通用函数、改变类的数据结构(tuple、list、dict、set等), 除个别的场景外, 不需要重写__new__方法.
单例模式的核心是在类中定义一个属性_instance用于存储类的唯一实例化的对象, 如果_instance对象不为空则直接返回实例化对象, 否则创建实例化对象并赋值给_instance属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Singleton(type):
  def __init__(self, *args, **kwargs):
    super(Singleton, self).__init__(*args, **kwargs)
  def __call__(cls, *args, **kwargs):
    if not hasattr(cls, "_instance"):
      cls._instance=super(Singleton, cls).__call__(*args, **kwargs)
    return cls._instance
class Spider(metaclass=Singleton):
  def __call__(cls):
    return cls._instance
s1=Spider()
s2=Spider()
print(s1())
print(s2())
单例模式构造的类, 在同一个python运行时上下文中, 不论出现在几个模块中, 均只有一个实例化对象.
Django的ORM框架
爬虫自动设置代理IP
参考文章
https://www.cnblogs.com/tkqasn/p/6524879.html
https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python
http://blog.jobbole.com/21351/
https://jfine-python-classes.readthedocs.io/en/latest/index.html
http://python.jobbole.com/88795/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
http://python.jobbole.com/85126/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
http://python.jobbole.com/86248/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
http://python.jobbole.com/86821/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
http://python.jobbole.com/86566/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
