细说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. js 代码大全(各种方法、属性)

    事件源对象event.srcElement.tagNameevent.srcElement.type捕获释放event.srcElement.setCapture(); event.srcElemen ...

  2. scrapy中间件之随机user-agent

    import random class UserAgentMiddleware(object): def __init__(self): self.user_agent_list = [ " ...

  3. RMQ 2d 模板

    #include<iostream> #include<cstdio> #include<string.h> #include<string> #inc ...

  4. Mac下安装nginx并配置SSL实现Https的访问

    一.nginx安装 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/insta ...

  5. git 与gitlab

    1.gitlab 创建project ,命名为test2 2.git push项目 git remote add ******* mkdir test1 cd test1 git init nano ...

  6. 微信支付之扫码支付、公众号支付、H5支付、小程序支付相关业务流程分析总结

    前言 很久以来,一直想写一篇微信支付有关的总结文档:一方面是总结自己的一些心得,另一方面也可以帮助别人,但是因种种原因未能完全理解透彻微信支付的几大支付方式,今天有幸做一些总结上的文章,也趁此机会,将 ...

  7. Redis 实战之主从复制、高可用、分布式

      目录 简介 持久化 主从复制 高可用 Redis-Sentinel .NET Core开发 分布式 Redis-Cluster 配置说明 常见问题 简介 本节内容基于 CentOS 7.4.170 ...

  8. 【POJ2486】Apple Tree

    题目大意:给定一棵 N 个节点的有根树,点有点权,边权均为1.现允许从根节点出发走 K 步,求可以经过的点权之和最大是多少. 题解:可以将点权看作是价值,将可以走的步数看作是重量,则转化成了一个树上背 ...

  9. Vue使用animate.js

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. HIVE 必知必会

    hive: 基于hadoop,数据仓库软件,用作OLAP OLAP:online analyze process 在线分析处理OLTP:online transaction process 在线事务处 ...