细说python类3——类的创建过程

https://blog.csdn.net/u010576100/article/details/50595143

2016年01月27日 18:37:24 u010576100 阅读数:4711 标签: classpython创建类 更多

个人分类: python
 

先来介绍一下python的__call__函数,call的作用是什么呢?举个例子来说明一下:

>>> class A(object):
...   def __init__(self):
...     print 'a'
...   def __call__(self):
...     print 'call'
... 
>>> a=A()
a
>>> a()
call

据说a()这么使用的时候相当于执行a.__call__(),我们暂且这么理解,具体原因请参考专业文档,这里看可能a()没啥用,请继续向后看。

接下来,说一下类的type,

>>> class B:
...   def __init__(self):
...     print 'b'
... 
>>> b=B()
b
>>> type(B)
<type 'classobj'>
>>> B
<class __main__.B at 0x7fdf94c086b0>
>>> type(b)
<type 'instance'>
>>> type(type(B))
<type 'type'>

>>> B
<class __main__.B at 0x7fdf94c086b0>

由上面例子可以看出类,实例的数据类型。

之后用type函数,创建一个类,type()函数,大致需要以下几个参数,第一个是类的name,第二个是这个类的父类,之后是属性。这里name指的是<class __main__.B at 0x7fdf94c086b0>这里面__main__后面跟的字符。为了保持一致,通常与类的名字一样。

>>> A=type('A',(object,),{'name':'aaa'})

>>> A
<class '__main__.A'>

可以看出我们的类A已经创建成功

>>> type(A)
<type 'type'>

但是为什么type(A)类型还是type,而不是<type 'classobj'>呢?因为type(A)和type(type('A',(object,),{'name':'aaa'}))是一样的,我猜classobj就是一个别名,但是我们用最原始的方法没显示别名,所以只显示type,但这不重要,重点是类已经创建了。那么我们自己封装一个类继承type去创建类呢?

>>> class MyType(type):
...   def __init__(self,name,bases,dict):
...     print 'mytype'
...   def __call__(self,*args,**kwargs):
...     print 'mytype call'
这里我们参数和type的源码一致,相当于重写了type的init和call,之后写一个B类,把B的__metaclass__指向myType,

>>> class B:
...   __metaclass__=MyType
...   def __init__(self):
...     print 'b'

>>> b=B()
mytype call
>>> b

实例化一个b,可以看到,执行了MyType的init,但是b并没有生成任何东西。

这里解释一下,当执行b=B()时,需要先找到类内部的__metaclass__并执行,按照__metaclass__顺序先来执行__init__创建一个最初的类,类需要实例化,当我们实例化时会调用metaclass的__call__函数(这样使用B(),就解释了上面的call方法),__call__函数内部正常会调用B类里面的__new__方法来创建一个类的对象,之后会调用B里面的__init__函数给对象进行最初的包装(把相关的参数赋值等操作),最后返回这个类的对象,再把这个对象付赋给b,这样就完成了实例化的过程。因为MyType的__call__方法只打印了一串信息,所以这个实例没有值。也就是说正常创建一个实例对象的其实是new而不是init,init只是起到一个赋值的作用。下面代码模拟一下类的实例化过程:

def __call__(self,*args,**kwargs):
    print 'mytype call'
    re=self.__new__(self,*args,**kwargs)
    self.__init__(re)
    return re
class B:
  __metaclass__=MyType
  def __init__(self):
    self.name='b'
    print 'B'
  def __new__(cls,*args,**kwargs):
    return object.__new__(cls,*args,**kwargs)
  def Func(self):
    print 'Func'
  def __call__(self):
    print 'call'
b=B()
print b
print b.name

执行结果如下:

mytype
mytype call
B
<__main__.B object at 0x7fd84d7ae710>
b

细说python类3——类的创建过程的更多相关文章

  1. 类和对象的创建过程(元类,__new__,__init__,__call__)

    一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...

  2. python原类、类的创建过程与方法

    今天为大家介绍一下python中与class 相关的知识-- 获取对象的类名 python是一门面向对象的语言,对于一切接对象的python来说,咱们有必要深入的学习与了解一些知识 首先大家都知道,要 ...

  3. 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

    原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...

  4. python 通过元类控制类的创建

    一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...

  5. 深入理解Java对象的创建过程:类的初始化与实例化

    摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...

  6. python之定义类创建实例

    https://www.cnblogs.com/evablogs/p/6688938.html 类的定义 在Python中,类通过class关键字定义,类名以大写字母开头 1 2 >>&g ...

  7. springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

    springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 1.1 异常处理思路 系统中异常包括两类:预期异常和运行时异常RuntimeEx ...

  8. Java对象的创建过程:类的初始化与实例化

    一.Java对象创建时机 我们知道,一个对象在可以被使用之前必须要被正确地实例化.在Java代码中,有很多行为可以引起对象的创建,最为直观的一种就是使用new关键字来调用一个类的构造函数显式地创建对象 ...

  9. 理解python的元类

    看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...

随机推荐

  1. 2019-11-29-VisualStudio-使用新项目格式快速打出-Nuget-包

    title author date CreateTime categories VisualStudio 使用新项目格式快速打出 Nuget 包 lindexi 2019-11-29 10:15:25 ...

  2. 微服务中的rpc 请求写法

    1.采用restmplate 的postForObject RestTemplate template = new RestTemplate(); HttpEntity<List<Map& ...

  3. canvas 计算文字宽度(常用于文字换行)

    var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); ctx.font= ...

  4. python 后台 安装 富文本编辑

    前言 当然需要安装一些后台只能输入一些文本编辑器,不然这样多少不美观呀 当然python 有 safe 可以把后台的标签转换 , 还有 striptags   这个是换成html 格式的,但不会加粗或 ...

  5. Hibernate基本原理理解

    什么是Hibernate? Hibernate,翻译过来是冬眠的意思,正好现在已经进入秋季,世间万物开始准备冬眠了.其实对于对象来说就是持久化. 扫盲------------------------- ...

  6. js 定义函数

    //AA(); //可执行 function AA() { test(); //报错 var test = function test() { console.log(); } } AA(); //可 ...

  7. ThoughtWorks.QRCode 生成二维码名片(实现二维码内容换行)

    最近在写一个很简单的功能,按照Vcard的格式,生成二维码名片.本来以为分分钟完事的事情,替换数据,直接调用dll去生成二维码. 测试时,发现生成的二维码使用微信扫描得到的名片信息为空,反向解析发现, ...

  8. 【BZOJ4565】 [Haoi2016]字符合并

    Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字 符和分数由这 k 个字符确定.你需要求出你能获得的最大分数. I ...

  9. Spring Boot教程(三)消费Restful的web服务

    构架工程 创建一个springboot工程,去消费RESTFUL的服务.这个服务是 http:///gturnquist-quoters.cfapps.io/api/random ,它会随机返回Jso ...

  10. logstash之Input插件

    1:stdin标准输入和stdout标准输出 首先执行命令: bin/logstash -e 'input { stdin { } } output { stdout { codec   => ...