很喜欢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 的做法我更喜欢。

结束:

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

Python系列之 __new__ 与 __init__的更多相关文章

  1. Python中的__new__和__init__

    Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...

  2. python中的__new__与__init__,新式类和经典类(2.x)

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

  3. python 中的__new__与__init__

    在Python中的class中有两个方法__new__与__init__,有什么区别呢? class TestCls(): """docstring for TestCl ...

  4. python中的__new__、__init__和__del__

    __new__.__init__.__del__三个方法用于实例的创建和销毁,在使用python的类中,我们最常用的是__init__方法,通常称为构造方法,__new__方法几乎不会使用,这篇文章是 ...

  5. Python 中的__new__和__init__的区别

    [同] 二者均是Python面向对象语言中的函数,__new__比较少用,__init__则用的比较多. [异] __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是 ...

  6. python类的__new__和__init__

    python的类,和其他语言有一点不太一样,就是,他把新建一个类和初始化一个类,分成了两个方法: __new__ __init__ 当然,想想就知道,肯定是__new__先发生,然后才是__init_ ...

  7. 详解Python中的__new__、__init__、__call__三个特殊方法(zz)

    __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)__init__ : 对象的初始化, 是一个实例方法,第一个参数是self ...

  8. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  9. 一个案例深入Python中的__new__和__init__

    准备 在Python中,一切皆对象. 既然一切皆对象,那么类也是对象,我们暂且称之为 类对象.来个简单例子(本篇文章的所有案例都是运行在Python3.4中): class foo(): pass p ...

随机推荐

  1. Android 硬编码

    public class TextViewActivity extends Activity { // 声明TextView对象 private TextView textView; @Overrid ...

  2. webpack2.0配置postcss-loader

    使用webpack2.0配置postcssloader 安装postcss-loader npm install --save-dev postcss-loader 然后配置webpack.confi ...

  3. es6基础(3)-正则扩展

    //正则扩展 { let regex=new RegExp('xyz','i'); let regex2=new RegExp(/xyz/i); console.log(regex.test('xyz ...

  4. 字符串截取函数slice, substring, substr

    在日常项目需求中,常常会遇到需要截取字符串操作的工作,而ECMAScript为我们提供了原生的截取字符串的函数,而且提供了三个:slice, substring, substr.我们怎么判断在什么时候 ...

  5. 关于W8.1不能安装VS2015(包括2017等)

    电脑本来是W7 64位+OPENCV3.1,今天突然系统崩溃了,然后感觉W7过时了遇到很多问题直接系统崩溃还得了啊,干脆装了一个W8.1了. 好吧~~本来想直接说问题的,干脆先把装系统给记录一下--& ...

  6. LeetCode 失败的尝试 10. regular expression matching & 正则

    Regular Expression Matching 看到正则就感觉头大,因为正则用好了就很强大.有挑战的才有意思. 其实没有一点思路.循环的话,不能一一对比,匹配模式解释的是之前的字符.那就先遍历 ...

  7. 启动tomcat时cmd窗口一闪而过

    在tomcat的安装目录下 双击startup.bat启动时cmd窗口一闪而过 1.在系统中查看配置JDK的环境变量是否正确 2.进入tomcat的安装目录 在启动tomcat时流程是:startup ...

  8. [多线程]线程基础(对象锁、class锁、同步、异步)

    synchronized.volatile.ReentrantLock.concurrent 线程安全:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法) ...

  9. 读取配置文件properties的几种方式

    介绍几种读取方式:参考:https://www.cnblogs.com/sebastian-tyd/p/7895182.html .基于ClassLoder读取配置文件 注意:该方式只能读取类路径下的 ...

  10. [转]J-Link Commander的妙用

    转自http://maker.zlgmcu.com/portal.php?mod=view&aid=3685 J-Link Commander作为J-Link驱动软件包的一个工具之一,为工程师 ...