Python中的__new__与__init__魔术方法理解笔记

很喜欢Python这门语言。在看过语法后学习了Django 这个 Web 开发框架。算是对 Python 有些熟悉了。不过对里面很多东西还是不知道,因为用的少。今天学习了两个魔术方法:__new__ 和 __init__。

开攻:

如果对 Python 有所简单了解的话应该知道它包含类这个概念的。语法如下:

代码如下:

class ClassName:
    <statement - 1>:
        .
        .  
        .
    <statement - N>

问题来了。像我们学习的 C# 或是 Java 这些语言中,声明类时,都是有构造函数的。类似下面这样子:

代码如下:

public class ClassName{
    public ClassName(){

}
}

当然访问修饰符不一定非得 public ,这不是重点就不啰嗦了。那 Python 中的构造函数是怎样的呢?我自己的理解是它是没有构造函数的。只不过在初始化时会调用一些内部的可被改变的方法。比如:__new__ 和 __init__ 。从字面意思理解 __new__ 应该会在 __init__ 之前执行,实际查了资料后确实是如此的。官方文档中关于 __init__ 方法有这样一句话:

代码如下:

Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__()

意思就是说在创建类时,如果想指定的它的初始状态,那么可以通过定义一个指定名称为 __init__ 的方法去实现这样的功能。这样说来 __new__ 并不是官方推荐的初始化类时要使用的方法。但是 __new__ 却是在 __init__ 之前执行的。官方文档中对 __init__ 介绍的第一句便是:当创建实例时调用 __init__ 方法(Called when the instance is created.),后面又介绍说,如果想调用基类的 __init__方法必须显式的调用,只继承基类在初始化子类时并不会自动调用基类的 __init__ 方法。到此应该算是对 __init__ 方法了解了。

下面我们看一下 __new__ 方法是怎么回事儿。先看一下官方文档:

代码如下:

Called to create a new instance of class cls. __new__() is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of __new__() should be the new object instance (usually an instance of cls).

Typical implementations create a new instance of the class by invoking the superclass's __new__() method using super(currentclass, cls).__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.

If __new__() returns an instance of cls, then the new instance's __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked.

__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

从这里可以看出来,这个方法才是产生类的实例的地方。当实例创建完成就调用 __init__ 方法,初始化类的内部状态值。文档中还提到 __new__ 方法其实是一个静态方法,不用每次定义类的时候都声明这个方法,因为在版本 2.4 之后 object 是所有对象的基类,而 __new__ 是定义在 object 对象内部的静态方法。

到这儿其实就差不多了,就按字面意思理解就可以。 __new__ 用于创建对象,而 __init__ 是在创建完成之后初始化对象状态。前两天看到一个有趣的方法,通过使用 __new__ 应用了单例模式在对象身上。

注意点:在类继承中,当子类和父类都定义了自己的 __new__ 方法时,那么会先调用子类的 __new__ 方法再调用父类的。这一点倒是和 C# 中的继承是一样的。其实仔细想想 Python 中只不过是把初始化和创建对象这两个概念分开了,而 C# 中即没有这么干,只给了构造函数,开发者可以自己看着办。从这一点儿上说我觉得 Python 的做法我更喜欢。

结束:

今天算是又学习到了新知识,自己挺开心的。再实践实践。。。

(0)

相关推荐

  • Python中__new__与__init__方法的区别详解

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1. 新式类对象可以直接通过__class__属性获取自身类型:type 2. 继承搜索的顺序发生了改变,经典类多继承时属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧(即深度优先搜索);新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动 例子: 经典类: 搜索顺序是(D,B,A,C) >>

  • Python类方法__init__和__del__构造、析构过程分析

    最近学习<Python参考手册>学到Class部分,遇到了类的构造析构部分的问题: 1.什么时候构造? 2.什么时候析构? 3.成员变量如何处理? 4.Python中的共享成员函数如何访问? ------------------------ 探索过程: 1.经过查找,Python中没有专用的构造和析构函数,但是一般可以在__init__和__del__分别完成初始化和删除操作,可用这个替代构造和析构.还有一个__new__用来定制类的创建过程,不过需要一定的配置,此处不做讨论. 2.类的成员函

  • 详解Python中的__new__、__init__、__call__三个特殊方法

    __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self) __init__ : 对象的初始化, 是一个实例方法,第一个参数是self. __call__ : 对象可call,注意不是类,是对象. 先有创建,才有初始化.即先__new__,而后__init__. 上面说的不好理解,看例子. 1.对于__new__ class Bar(object): pass class Foo(object): def __new__(cls

  • 详解Python中的__init__和__new__

    一.__init__ 方法是什么?使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: 复制代码 代码如下: # -*- coding: utf-8 -*- class Person(object):    """Silly Person""" def __init__(self, name, age):        self.name = name

  • python中的__init__ 、__new__、__call__小结

    1.__new__(cls, *args, **kwargs)  创建对象时调用,返回当前对象的一个实例;注意:这里的第一个参数是cls即class本身2.__init__(self, *args, **kwargs) 创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用__new__之后,根据返回的实例初始化:注意,这里的第一个参数是self即对象本身[注意和new的区别]3.__call__(self,  *args, **kwargs) 如果类实现了这个方法,相当于把这个类型

  • python中子类继承父类的__init__方法实例

    前言 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的 初始化 . 注意:这个名称的开始和结尾都是双下划线. 父类A class A(object): def __init__(self, name): self.name=name print "name:", self.name def getName(self): return 'A ' + sel

  • 详细解读Python中的__init__()方法

    __init__()方法意义重大的原因有两个.第一个原因是在对象生命周期中初始化是最重要的一步:每个对象必须正确初始化后才能正常工作.第二个原因是__init__()参数值可以有多种形式. 因为有很多种方式为__init__()提供参数值,对于对象创建有大量的用例,我们可以看看其中的几个.我们想尽可能的弄清楚,因此我们需要定义一个初始化来正确的描述问题区域. 在我们接触__init__()方法之前,无论如何,我们都需要粗略.简单地看看在Python中隐含的object类的层次结构. 在这一章,我

  • Python中__init__和__new__的区别详解

    __init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: # -*- coding: utf-8 -*- class Person(object): """Silly Person""" def __init__(self, name, age): self.name = name self.age = age def __

  • Python RuntimeError: thread.__init__() not called解决方法

    在写一个多线程类的时候调用报错 RuntimeError: thread.__init__() not called 复制代码 代码如下: class NotifyTread(threading.Thread):      def __init__(self, params):          threading.Thread.__init__(self)  #here......          self.params = params            def run(self): 

  • Python中__init__.py文件的作用详解

    __init__.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py 文件. 通常__init__.py 文件为空,但是我们还可以为它增加其他的功能.我们在导入一个包时,实际上是导入了它的__init__.py文件.这样我们可以在__init__.py文件中批量导入我们所需要的模块,而不再需要一个一个的导入. # package # __init__.py import re import urllib import sys impo

随机推荐