类的创建

前面的随笔都是关于类的知识,通过类创建对象,那这个类到底是怎么产生的呢?

1、 传统创建类

class Foo(object):
def __init__(self,name):
self.name = name f = Foo("shuaigaogao")

  

f 是通过 Foo 类实例化的对象,其实,不仅 f 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象,按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

print(type(f))    #输出:<class '__main__.Foo'>  表示:f 对象由Foo类创建
print(type(Foo)) #输出:<class 'type'> 表示:Foo类对象由 type 类创建

所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建

2 、type创建类

说明:  type创建类的格式,类名 = type('类名',(父类,),{'方法名':方法的内存地址})

def func(self):  #创建方法
print("hello {0}".format(self.name)) def __init__(self,name): #创建构造方法
self.name = name #通过type创建类,如果是经典类的话则写成:Foo = type("Foo",(),{"talk":func,"__init__":__init__})
Foo = type("Foo",(object,),{"talk":func,"__init__":__init__})
f = Foo("shuaigaogao") #创建对象
f.talk() #输出
hello shuaigaogao  

总结:类 是由 type 类 实例化产生的

值得注意的是,新式类的写法,在继承父类那边,你继承一个父类后面就要加一个逗号,加逗号,它就把它当做一个元组,不加逗号,就是一个值了

__new__方法

1 、概念

new方法是类自带的一个方法,可以重构,__new__方法在实例化的时候也会执行,并且先于__init__方法之前执行

class Foo(object):

    def __init__(self,name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs)
return object.__new__(cls) f = Foo("shuaigaogao") #输出
Foo __new__ <class '__main__.Foo'> shuaigaogao #执行了new方法
Foo __init__ #执行了__init__方法

  

2、 new方法作用

作用:所有对象都是通过new方法来实例化的,new里面调用了init方法,所以在实例化的过程中先执行的是new方法,而不是init方法。

①重构__new__方法

class Foo(object):

    def __init__(self,name):
self.name = name
print("Foo __init__") def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs) f = Foo("shuaigaogao") #实例化 #输出
Foo __new__ <class '__main__.Foo'> shuaigaogao

由上面的例子看出,没有执行__init__方法

②重构__new__方法,并继承父类的__new__方法

class Foo(object):

    def __init__(self,name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): #cls相当于传入类Foo
print("Foo __new__",cls, *args, **kwargs)
return object.__new__(cls) #继承父类的__new__方法,这边必须以返回值的形式继承 f = Foo("shuaigaogao") #输出
Foo __new__ <class '__main__.Foo'> shuaigaogao

由上面不难看出,大多数情况下,你都不要去重构你的__new__方法,因为你父类中已经有__new__方法了,已经帮你写好了怎么去创建类,如果你重写的话,就会覆盖父类的里面的__new__方法。但是你重构可以增加一点小功能,但是你覆盖了以后还是需要继承父类回来,要不然你的这个实力就创建不了。

3、使用场景

我想对我自己写的一些类进行定制,就在它实例化之前就进行定制,就可以用到__new__方法,new方法就是用来创建实力的,重构new方法,必须以返回值的形式继承父类的new方法。

①需求:我在创建对象时候,同时创建一个类变量

class Foo(object):

    def __init__(self,name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): #cls相当于是传入的类名Foo
cls.name = "shuaigaogao" #创建对象是定义静态变量
print(cls.name)
return object.__new__(cls) #继承父类的__new__方法 f = Foo("shuaigaogao")
print(Foo.name) #输出
shuaigaogao
Foo __init__
shuaigaogao

__metaclass__方法

metaclass这个属性叫做元类,它是用来表示这个类是由谁来帮他实例化创建的,说白了,就是相当于自己定制一个类。

class MyType(type):
def __init__(self,*args,**kwargs): print("Mytype __init__",*args,**kwargs) def __call__(self, *args, **kwargs):
print("Mytype __call__", *args, **kwargs)
obj = self.__new__(self)
print("obj ",obj,*args, **kwargs)
print(self)
self.__init__(obj,*args, **kwargs)
return obj def __new__(cls, *args, **kwargs):
print("Mytype __new__",*args,**kwargs)
return type.__new__(cls, *args, **kwargs) class Foo(object,metaclass=MyType): #python3统一用这种
#__metaclass__ = MyType #python2.7中的写法 def __init__(self,name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs):
print("Foo __new__",cls, *args, **kwargs)
return object.__new__(cls) f = Foo("shuaigaogao")
print("f",f)
print("fname",f.name) #输出
Mytype __new__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x0000025EF0EFD6A8>,
'__init__': <function Foo.__init__ at 0x0000025EF0EFD620>, '__qualname__': 'Foo', '__module__': '__main__'}
Mytype __init__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x0000025EF0EFD6A8>,
'__init__': <function Foo.__init__ at 0x0000025EF0EFD620>, '__qualname__': 'Foo', '__module__': '__main__'}
Mytype __call__ shuaigaogao
Foo __new__ <class '__main__.Foo'>
obj <__main__.Foo object at 0x0000025EF0F05048> shuaigaogao
<class '__main__.Foo'>
Foo __init__
f <__main__.Foo object at 0x0000025EF0F05048>
fname shuaigaogao

创建过程如下:

更多__metaclass__知识:点击

总结:

  类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

【python】-- 类的创建、__new__、__metaclass___的更多相关文章

  1. 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑

    上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...

  2. 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解

    上节介绍了__new__()方法这个比构造方法还重要的方法的语法,本节通过案例来详细剖析__new__()方法的细节以及它与构造方法之间的关系. 一.    案例说明 本节以圆Cir类为例来说明,为了 ...

  3. python 类中__init__,__new__,__class__的使用详解

    1.python中所有类默认继承object类,而object类提供了很多原始的内置属性和方法,所有用户定义的类在python 中也会继承这些内置属性.我们可以通过dir()进行查看.虽然python ...

  4. python 类的创建

  5. 第8章 Python类中常用的特殊变量和方法目录

    第8章 Python类中常用的特殊变量和方法 第8.1节 Python类的构造方法__init__深入剖析:语法释义 第8.2节 Python类的__init__方法深入剖析:构造方法案例详解 第8. ...

  6. python类、继承

    Python 是一种面向对象的编程语言.Python 中的几乎所有东西都是对象,拥有属性和方法.类(Class)类似对象构造函数,或者是用于创建对象的"蓝图". 一.python ...

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

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

  8. Python类的__new__()

    本篇主要想要详细的介绍一下关于类的魔法方法__new__()方法. 在学习之前我们看一下Python3中关于object基类的__new__() 方法: @staticmethod # known c ...

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

    细说python类3——类的创建过程 https://blog.csdn.net/u010576100/article/details/50595143 2016年01月27日 18:37:24 u0 ...

随机推荐

  1. 手动安装minGW

    minGW是C语言编译包,将GCC编译器在Windows平台上编译软件提供支持. 手工安装minGW是一件很繁琐的事情,但是搞懂它很有用,因为C语言本身是一个很小的语法系统,全靠 各种库在支持,安装m ...

  2. Atitit .linux 取回root 密码q99

    Atitit .linux 取回root 密码q99 1.1. 停止mysql1 1.2. mysqld_safe路径1 1.3. Mysql配置文件路径1 1.4. Mysql路径1 1.5. 安全 ...

  3. 二次开发第N天。。。。。。。。自动分页问题

    phpcms\modules\content\fields\pages\form.inc.php 注意修改时,如果是gbk版本可以直接用记事本修改保存!如果是utf8 要用工具修改,或者保存的时候要记 ...

  4. poj Ping pong LA 4329 (树状数组统计数目)

    Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2302   Accepted: 879 Descript ...

  5. lua 小技巧

    lua 小技巧 把常用的工具函数添加到 _G 里面,所有的文件都可以直接调用: ``` lua -- 在 a 文件中将工具函数添加到 _G: _G.IsEmptyStr = function(str) ...

  6. JSP、servlet、SQL三者之间的数据传递

    JSP.servlet.SQL三者之间的数据传递 博客分类: web开发 JSPservletSQL数据库连接池web开发  前言: 最近一直在做WEB开发,现总结一下这一段时间的体会和感触. 切记, ...

  7. Entity简单使用

    urlEntity: //定义 package com.example.cc.ecustapp.Model; /** * Created by weijiawang on 2016/3/8. */pu ...

  8. 使用java语言如何更好的使用多线程?

    ① 高并发.任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换. ② 并发不高.任务执行时间长的业务要区分开看: 假如是业务时间长集中在I/O操作上,也就是I/O密集型的 ...

  9. iOS 给tableView设置contentInset不生效?

    给tableView设置contentInset的时候如果tableView中内容比较多,超过一个屏幕,设置的contentInset是生效的,但是呢,如果页面内容比较少,我们会发现设置content ...

  10. linux学习笔记29---命令watch

    watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行.在Linux下,watch是周期性的执行下个 ...