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.小结
元类主要就是在类和实例创建的时候发挥作用,来实现一些功能。
python元类深入理解的更多相关文章
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- Python 元类 - Metaclasses
Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...
- python元类理解2
恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...
- python 元类理解
原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...
- 深入理解python元类
类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 P ...
- 对python中元类的理解
1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: >>> class ObjectCreator(object): ...
- Python元类__prepare__方法深入理解
学习元类的时候,对__prepare__不是很理解,书上讲解的也不是很详细,最后通过查看stackoverflow的一些帖子对该方法有了一些理解,记录如下: 先看代码: class member_ta ...
- 深入理解 python 元类
一.什么的元类 # 思考: # Python 中对象是由实例化类得来的,那么类又是怎么得到的呢? # 疑问: # python 中一切皆对象,那么类是否也是对象?如果是,那么它又是那个类实例化而来的呢 ...
随机推荐
- redis连接错误3种解决方案System Error MISCONF Redis is configured to save RDB snapshots
redis连接错误System Error MISCONF Redis is configured to save RDB snapshots, but XX 情况1解决办法: 由于强制停止red ...
- 透过字节码分析java基本类型数组的内存分配方式。
我们知道java中new方式创建的对象都是在堆中创建的,而局部变量对应的值存放在栈上.那么java中的int [] arr={1,2,3}是存放在什么地方的呢,int []arr = new int[ ...
- vSphere 5.5.0 U1配置问题:主机的快速统计信息不是最新的(转载)
最近公司新购置了几台DELL服务器用来上桌面虚拟化,前期搭建测试环境进行功能验证,底层自然而然的选择VMware ESXi,当前最新版本为ESXi 5.5.0 U1,单独数据库安装,相对5.1来说,5 ...
- [apue] dup2的正确打开方式
管道与重定向常常需要使用dup与dup2复制句柄,其中dup2又较为常用,但是使用dup2有几个小坑需要注意. int dup2(int oldfd, int newfd); man手册页上是这样讲的 ...
- 【原创】Docker 搭建Maven私服nexus 3.17初始密码登录不上问题/admin登陆不上问题
[原创-转载请说明出处] 博主最近在虚拟机中搭建Maven私服,遇到了一个关键问题就是nexus 3.17版本后初始密码不是admin/admin123. 对于nexus不熟悉的我弄了很长时间!!!心 ...
- 为什么wepy的数据无法渲染到实例里面去
为啥明明WEPY是将数据渲染到视图还会出这个问题呢? 因为只是类似于 Vue 框架,所以不能完全实现数据渲染,尤其当异步操作的时候. (1)WePy 普通数据绑定. WePY使用脏数据检查对setDa ...
- Python旅途——函数的递归和栈的使用
Python--函数之递归.栈的使用 今天主要和大家分享函数的递归,同时引入一个新的概念--栈 1.递归 1.定义 函数的递归指的就是函数自己调用自己,什么是函数自己调用自己呢?我们来看一个栗子: 这 ...
- 華氏溫度轉化為攝氏溫度的簡單JavaScript代碼
今天,跟著W3School學到了"JavaScript函數",代碼都挺簡單的,在運算符調用函數的地方寫了一個小程序.原碼程序是這樣的: <!DOCTYPE html> ...
- maven多仓库配置(公司服务器与阿里云仓库)
1. 问题描述 公司内网搭建的有maven私有服务器,但是碰到好几次只有gav没有jar的情况或者最新版本更新不及时,所以需要公司服务器和远程仓库(阿里云)相结合来满足项目需求. 2. 解决方案: m ...
- Java底层技术系列文章-hashcode深入理解
带着问题去理解: 1. Object类HashCode方法是如何实现的,和String类有什么区别? 2.HashCode和Equals之间的关系? 一.hashCode作用 hashCode方法返回 ...