发布于2019-08-05 18:16 阅读(938) 评论(0) 点赞(3) 收藏(3)
在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,我们接收并赋值到一个变量上,现在这个变量就指向我们所创建的类,我们可以通过这个变量来使用类。
在python 中,几乎所有的东西都是对象,这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来——type
python在创建类时,会按照如下的流程进行:
Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
那么在__metaclass__中放置什么样的代码可以创建类呢?type,或者任何使用到type或者子类化type的东东都可以。
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__")
1.元类的__new__(),返回创建好的类。当我们想要改变创建方式的时候就要重写这个方法。
2.元类的__init__(),初始化一些类的属性
1.元类的__call__(),创建一个实例时,首先调用这个方法,返回创建好的实例,所以我们可以通过改写这个方法来改变实例创建过程,比如实现单例模式
2.类的__init__(),初始化实例属性
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
能过获取到属性的定义顺序,我们就可以通过简单的方法实现属性到数据的映射,可以更加简单的将类中的属性数据化。
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())
元类主要就是在类和实例创建的时候发挥作用,来实现一些功能。
作者:从新来过
链接:https://www.pythonheidong.com/blog/article/6170/a0a78423fb34748c31a4/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!