zoukankan      html  css  js  c++  java
  • 细说python类3——类的创建过程

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

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

    先来介绍一下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

    delphi lazarus opengl 网页操作自动化, 图像分析破解,游戏开发
  • 相关阅读:
    wget一个小技巧
    【iOS官方文档翻译】UICollectionView与UICollectionViewFlowLayout
    NSDate获取当前时区的时间
    怎样把一个字典的数据添加到另一个字典中?
    CoreLocation基本使用
    iOS开发--一步步教你彻底学会『iOS应用间相互跳转』
    Save Image to UserDefaults(用NSUserDefaults保存图片)
    SDWebImage源码解析
    获取cell或者cell中的控件在屏幕中的位置
    Git命令详解 123
  • 原文地址:https://www.cnblogs.com/delphi-xe5/p/10173232.html
Copyright © 2011-2022 走看看