python元类深入理解

1.python 中的类

在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象,python也为我们提供了手动创建类的方法,type()。type()这个方法对我们来说并不陌生,我们所熟知的用法是:class = type(instance),当传入一个参数时,type()返回这个参数的类。而今天我们要用到的是type的另一个功能。type("classname",(object,),{"name":"jiao"})。当给type传入三个参数时,就是一个手动创建类的方式。

class A():
    def __init__(self,name):
        self.name = name
        print("创建了一个实例")

a = type("a",(A,),{"name":"jiao"})
print(a)              #<class ‘__main__.a‘>
print(a.name)          #jiao
print(a("jiang"))      #创建了一个实例
                        #<__main__.a object at 0x00000280A973AA58>

type接收三个参数分别是:

classname: 要创建的class 的名称

object:要创建类的父类所组成的元组

sttr_dict: 要创建类的属性

type返回一个class,我们接收并赋值到一个变量上,现在这个变量就指向我们所创建的类,我们可以通过这个变量来使用类。

2.python 中的type

在python 中,几乎所有的东西都是对象,这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来——type

3.__metaclass__属性

python在创建类时,会按照如下的流程进行:

Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。

那么在__metaclass__中放置什么样的代码可以创建类呢?type,或者任何使用到type或者子类化type的东东都可以。

4.自定义元类

class UpperAttrMetaClass(type):
    def __new__(cls,class_name,class_parents,class_attr, *args, **kwargs):
        print("__new__")
        class_attr[‘name‘] = "jiao"
        return type.__new__(cls,class_name,class_parents,class_attr)

    def __init__(self,*args,**kwargs):
        print("__init__")
        super().__init__(*args, **kwargs)
        self.__cache = {}

    def __call__(self, *args, **kwargs):
        print("__call__")
        if args in self.__cache:
            return self.__cache[args]
        else:
            obj = super().__call__(*args)
            self.__cache[args] = obj
            return obj

class A(metaclass=UpperAttrMetaClass):
    def __init__(self,name):
        self.name = name
        print("a.__init__")

5.类的创建流程

1.元类的__new__(),返回创建好的类。当我们想要改变创建方式的时候就要重写这个方法。

2.元类的__init__(),初始化一些类的属性

6.实例创建流程

1.元类的__call__(),创建一个实例时,首先调用这个方法,返回创建好的实例,所以我们可以通过改写这个方法来改变实例创建过程,比如实现单例模式

2.类的__init__(),初始化实例属性

7.元类的应用

1.单例模式

class Singleton(type):
    def __init__(cls,*args,**kwargs):
        cls.__instance = None
        super().__init__(*args,**kwargs)

    def __call__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = super().__call__(*args,**kwargs)
            return cls.__instance
        else:
            return cls.__instance

class Spam(metaclass=Singleton):
    def __init__(self):
        print("Creating Spam")
2.缓存模式
import weakref

class Cached(type):
    def __init__(cls,*args,**kwargs):
        super().__init__(*args,**kwargs)
        cls.__cache = weakref.WeakValueDictionary()

    def __call__(cls, *args, **kwargs):
        if args in cls.__cache:
            return cls.__cache[args]
        else:
            obj = super().__call__(*args)
            cls.__cache[args] = obj
            return obj

class Spams(metaclass=Cached):
    def __init__(self,name):
        print("Creating Spam({!r})".format(name))
        self.name = name

3.获取属性的定义顺序

能过获取到属性的定义顺序,我们就可以通过简单的方法实现属性到数据的映射,可以更加简单的将类中的属性数据化。

from collections import OrderedDict

class Typed:
    _excepted_type = type(None)

    def __init__(self,name=None):
        self._name = name

    def __set__(self, instance, value):
        if not isinstance(value,self._excepted_type):
            raise TypeError("Excepted"+str(self._excepted_type))
        instance.__dict__[self._name] = value

class Integer(Typed):
    _excepted_type = int

class Float(Typed):
    _excepted_type = float

class String(Typed):
    _excepted_type = str

class OrderedMeta(type):

    def __new__(cls, clsname,bases,clsdict):
        d = dict(clsdict)
        order = []
        for name,value in clsdict.items():
            if isinstance(value,Typed):
                value._name = name
                order.append(name)
                d[‘_order‘] = order
       return type.__new__(cls,clsname,bases,d)

    @classmethod
    def __prepare__(metacls, name, bases):
        return OrderedDict()

#注:__prepare__该方法会在类定义一开始的时候调用,调用时以类名和基类名称作为参数,它必须返回一个映射对象,供处理类定义体时调用

#eg.
class Structure(metaclass=OrderedMeta):

    def as_csv(self):
        return ‘,‘.join(str(getattr(self,name)) for name in self._order)

class Stock(metaclass=OrderedMeta):
    name = String()
    shares = Integer()
    price = Float()
    def __init__(self,name,shares,price):
        self.name = name
        self.shares = shares
        self.price = price

s = Stock("haha",23,23.3)
print(s.name)
s = Stock(34,23,34)
# print(s.as_csv())
 

8.小结

元类主要就是在类和实例创建的时候发挥作用,来实现一些功能。

原文地址:https://www.cnblogs.com/jiaojianglong/p/11260944.html

时间: 2024-08-09 20:52:10

python元类深入理解的相关文章

python元类__metaclass__

<pre name="code" class="python">#python元类,类的创建过程 #首先调用type.__new__ #然后调用类的构造函数 class.__init__ def toString(c): s=""; if type(c)==tuple: s="tuple:" for i in c: s+=str(i) s+="," return s elif type(c) =

深入理解python元类

类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 Python 中这一点也是成立的. >>> class ObjectCreator(object): ... pass ... >>> my_object = ObjectCreator() >>> print my_object <__main__.

对python中元类的理解

1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: >>> class ObjectCreator(object): - pass - >>> my_object = ObjectCreator() >>> print my_object <__main__.ObjectCreator object at 0x8974f2c> 但是,Python中的类还远不止如此.类同样也是一

Python元类__prepare__方法深入理解

学习元类的时候,对__prepare__不是很理解,书上讲解的也不是很详细,最后通过查看stackoverflow的一些帖子对该方法有了一些理解,记录如下: 先看代码: class member_table(dict): def __init__(self): self.member_names = [] def __setitem__(self, key, value): if key not in self: self.member_names.append(key) dict.__seti

python元类分析

刚开始接触到Python新式类中的元类的概念的时候很是纠结了下..不知道这是个啥东西... 用以下几个定义来说明吧: (1)Python中,类也是对象..只不过这种对象比较的特殊,他用于创建别的对象 (2)元类也是一种类,只不过它更特殊...他是用来创建别的类的类...(呵呵,是不是很拗口) 先来看一段代码吧: class Fjs(object): def __init__(self, name): self.name = name def hello(self): print "hello b

python 元类的简单解释

本文转自博客:http://www.cnblogs.com/piperck/p/5840443.html 作者:piperck python 类和元类(metaclass)的理解和简单运用 (一) python中的类 首先这里讨论的python类,都基于继承于object的新式类进行讨论. 首先在python中,所有东西都是对象.这句话非常重要要理解元类我要重新来理解一下python中的类 class Trick(object): pass 当python在执行带class语句的时候,会初始化一

Python元类

学懂元类,首先要知道两句话: 道生一,一生二,二生三.三生万物 我是谁?我从哪里来?我要到那里去? 在Python的世界里,拥有一个永恒的道:type,如此广袤无垠的Python生态圈,都是由type产生出来的. 道生一,一生二,二生三,三生万物. 道:即就是type 一:即是metaclass 二:即是class(或者实例生成器) 三:即是instance 1 关于类 道和一,是我们今天讨论的命题,而二.三.和万物,则是我们常常使用的类.实例.属性和方法,用hello world来举例: 1

python元类深入解析

元类 什么是元类 元类是类的类,是类的模板(就如对象的模板是类一样) 元类的实例为类,类的实例为对象 元类是用来产生类的 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,是运行时动态创建的 __new__() 我们之前说类实例化第一个调用的是__init__,但__init__其实不是实例化一个类的时候第一个被调用 的方法.当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__方法. __new__方法接受的参数虽

Python元类的一些应用

最近刚接触python的元类,网络上有比较详细的介绍,这里是在看Django时候发现一点关于元类的应用,做个笔记. from django.utils import six class A(type):     def __new__(cls, name, parents, attrs):         return type.__new__(cls, name, parents, attrs) class C(six.with_metaclass(A)):     pass 创建C类的时候,