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 中一切皆对象,那么类是否也是对象?如果是,那么它又是那个类实例化而来的呢 ...
随机推荐
- JavaWEB路径总结
这篇文章是小编一直想写的一篇,主要是对web阶段中各个路径进行的一些总结,希望读者看过之后对于路径方面有一个清晰的认识.首先声明一点:世界上一切东西都是相对的,对于这点而言,相信大家并不陌生,从初中开 ...
- Java NIO学习系列二:Channel
上文总结了Java NIO中的Buffer相关知识点,本文中我们来总结一下它的好兄弟:Channel.上文有说到,Java NIO中的Buffer一般和Channel配对使用,NIO中的所有IO都起始 ...
- CI框架使用(一)
CI框架的使用是很简单,也 是mvc模式.其中有好多类直接调用. 在使用帮助函数的时候,都需要手动加载,或者是在配置文件中加一个自动加载 $this->load->helper('ur ...
- python的自定义函数
今天想把上次参考着网上教程写的scrapy爬虫改写成requests和beautifulsoup的普通爬虫,写着写着发现自己对python的自定义函数还不是太熟悉(自己TCL了.........流泪) ...
- Java日志脱敏框架 sensitive-v0.0.4 系统内置常见注解,支持自定义注解
项目介绍 日志脱敏是常见的安全需求.普通的基于工具类方法的方式,对代码的入侵性太强.编写起来又特别麻烦. 本项目提供基于注解的方式,并且内置了常见的脱敏方式,便于开发. 特性 基于注解的日志脱敏. 可 ...
- java Http工具类
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...
- SpringBoot系列——Logback日志,输出到文件以及实时输出到web页面
前言 SpringBoot对所有内部日志使用通用日志记录,但保留底层日志实现.为Java Util Logging.Log4J2和Logback提供了默认配置.在不同的情况下,日志记录器都预先配置为使 ...
- C语言学习书籍推荐《C程序设计语言(第2版•新版)》下载
克尼汉 (作者), 等 (作者, 译者), 徐宝文 (译者) 下载地址:点我 <C程序设计语言(第2版•新版)>是由C语言的设计者Brian W.Kernighan和Dennis M.Ri ...
- java学习笔记(基础篇)--java关键字与数据类型
java关键字与数据类型 Java语言的关键字是程序代码中的特殊字符.包括: . 类和接口的声明--class, extends, implements, interface . 包引入和包声明--i ...
- Spring Cloud Alibaba | Sentinel: 服务限流基础篇
目录 Spring Cloud Alibaba | Sentinel: 服务限流基础篇 1. 简介 2. 定义资源 2.1 主流框架的默认适配 2.2 抛出异常的方式定义资源 2.3 返回布尔值方式定 ...