Python中类调用__new__()类方法来创建实例,调用__init__()方法来初始化对象,对象的销毁则调用__del__()方法。

__new__()方法第一个参数为类cls,通常返回cls的一个实例,然后新实例的__init__()方法将以类似于__init__(self[, ...])的方式被调用,self是创建的新的实例,其它的参数和传递给__new__()的参数一样。

如果__new__()方法不返回cls 的实例,那么__init__()将不会被调用。

对于一个类来说:

class Foo(object):
def __init__(self, name):
self.name = name f = Foo('bar')

当进行f = Foo('bar')的操作时,实际上执行以下步骤来创建和初始化实例:

f = Foo.__new__(Foo, 'bar')
if isinstance(f, Foo):
Foo.__init__(f, 'bar')

__new__(cls[, ...])

__new__()方法是一个静态类方法,以实例的类为第一个参数。其余的参数是传递给对象构造表达式的参数,与传递给__init__()的相同。

一般通过使用super(currentclass, cls).__new__(cls[, ...])来调用超类的__new__()方法创建类的一个新的实例。

用户自定义对象的时候,很少定义__new__()方法。如果定义的话,一般是在定义元类或者定义一些继承自不可变的内置数据类型(整数、字符串、元组等)的对象的时候。

定义一些不可变数据类型的时候,因为对象是不可变的,那么在__init__()中是无法对对象进行修改的,而__new__()方法是在实例创建之前执行的:

class Upperstr(str):
def __new__(cls, value=''):
return str.__new__(cls, value.upper())

上述Upperstr类创造的字符串实例全是大写的:

>>> u = Upperstr('hello world')
>>> u
'HELLO WORLD'

也可以在单例模式中使用__new__()方法创建唯一的实例,放在类变量中,以后每次创建都返回这一个实例:

class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_inst'):
cls._inst=super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._inst

__init__(self[, ...])

__init__()方法用来初始化对象的属性,在实例创建完成时调用。参数为传递给类构造器表达式的那些参数。如果基类具有__init__()方法,那么继承的类的__init__()方法,而且必须显式调用:BaseClass.__init__(self, [args...])。

构造器的一个特殊限制是不可以返回任何值,这样做将导致运行时抛出一个TypeError。

__init__()方法一般含有大量的self.attr = attr的赋值语句:

class Foo(object):
def __init__(self, name, color, num=1):
self.name = name
self.color = color
self.num = num f = Foo('bar', 'yellow')

如果不想重复这样的赋值操作,有以下几个办法:

class Foo(object):
def __init__(self, name, color, num=1):
print locals() f = Foo('bar', 'yellow')

__init__()方法的局部命名空间如下:

{'color': 'yellow', 'self': <__main__.Foo object at 0x00000000055C4780>, 'num': 1, 'name': 'bar'}

self变量为创建的实例本身,其余要给实例赋值的变量name,color,num均在其中。而实例属性是存储在实例的__dict__变量中,我们只需要将这些要赋值的变量放入__dict__即可:

class Foo(object):
def __init__(self, name, color, num=1):
self.__dict__.update(locals())
del self.__dict__['self']
>>> f = Foo('bar', 'yellow')
>>> f.name
'bar'
>>> f.color
'yellow'
>>> f.num
1

这样当实例属性很多的时候,就简洁了很多。但当使用特性或者描述符来包装对象的属性时,会产生问题,因为特性或者描述符包装的属性并不保存于__dict__之中,解决方案是使用setattr内置函数:

def attr_from_locals(locals_dict):
self = locals_dict.pop('self')
for k,v in locals_dict.items():
setattr(self, k, v) class Foo(object):
def __init__(self, name, color, num=1):
attr_from_locals(locals())

如果__init__()方法中使用了一些不用赋值给实例的本地变量的时候,再使用locals()会包含这些本地变量,我们可以再精准的传递__init__()中的参数。

通过一个函数f的f.__code__属性可以得到函数的字节码对象c,字节码对象的属性c.co_varnames可以得到局部变量名称的元组(函数参数在前,函数内局部变量在后),c.co_argcount可以得到函数位置参数的数量,利用切片可以去除函数内局部变量:

def attr_from_locals(locals_dict):
self = locals_dict.pop('self')
code = self.__init__.__func__.__code__
args = code.co_varnames[1:code.co_argcount]
for k in args:
setattr(self, k, locals_dict[k]) class Foo(object):
def __init__(self, name, color, num=1):
x = 1
attr_from_locals(locals()) f = Foo('bar', 'yellow')

可以看到x变量并未赋值给实例:

>>> f.name
'bar'
>>> f.color
'yellow'
>>> f.num
1
>>> f.x Traceback (most recent call last):
File "<pyshell#87>", line 1, in <module>
f.x
AttributeError: 'Foo' object has no attribute 'x'

__del__(self)

当实例要被销毁的时候,会调用对象的__del__()方法。注意当使用del a这样的语句时,并不会调用__del__()方法,只是减少一个引用计数,当对象的引用计数减至0时,才会调用__del__()。

__del__()方法也很少有必要定义,定义了此方法的实例,无法被python的循环垃圾收集器收集。

需要执行清除操作时(关闭文件、关闭网络连接等)可以定义,当然更好的办法是定义一个close()方法显式的执行关闭操作。

Python中的对象行为与特殊方法(一)对象的创建与销毁的更多相关文章

  1. Python中的str与unicode处理方法

    Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客    python2.x中处理 ...

  2. python中的魔术属性与魔法方法

    1.魔法属性 · 1.1__doc__魔法属性  表示类的描述信息 class Fo: """ 这是今天第一个魔术属性__doc__""" ...

  3. 第7.22节 Python中使用super调用父类的方法

    第7.22节 Python中使用super调用父类的方法 前面章节很多地方都引入了super方法,这个方法就是访问超类这个类对象的.由于super方法的特殊性,本节单独谈一谈super方法. 一.su ...

  4. Python中异步协程的使用方法介绍

    1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...

  5. python中常用的导包的方法和常用的库

    python中常用的导包的方法               导入包和包名的方法:1.import package.module 2.from package.module import  * 例一: ...

  6. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

  7. Python中os和shutil模块实用方法集…

    Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...

  8. Python中os和shutil模块实用方法集锦

    Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...

  9. python中执行shell的两种方法总结

    这篇文章主要介绍了python中执行shell的两种方法,有两种方法可以在Python中执行SHELL程序,方法一是使用Python的commands包,方法二则是使用subprocess包,这两个包 ...

  10. Python中常见字符串去除空格的方法总结

    Python中常见字符串去除空格的方法总结 1:strip()方法,去除字符串开头或者结尾的空格>>> a = " a b c ">>> a.s ...

随机推荐

  1. Appium环境搭建(一)

    python环境做测试,需要准备工具如下: 1.python2.7(这里使用的是python2你也可以选更高版本) 2.Appium(Window版) 3.Android SDK 4.Appium_P ...

  2. PHP socket通信之UDP

    服务端: //服务器信息 $server = 'udp://127.0.0.1:9998'; //消息结束符号 $msg_eof = "\n"; $socket = stream_ ...

  3. gitlab4.0->5.0->6.0->7.14->8.0->8.2升级

    参考官方文档: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update 本地服务器为4.0.1版本  1)4.0.1->4. ...

  4. MFC AfxMessageBox MessageBox MessageBoxA 默认标题修改

    在工程的资源里添加String Table资源,AFX_IDS_APP_TITLE,然后设置其值即可,AFX_IDS_APP_TITLE的值就是AfxMessageBox.MessageBox.Mes ...

  5. python 定义类 简单使用

    在test.py文件里面 #coding=utf-8 #类的定义 class user: #定义私有属性 __name = '' __age = 0 #定义基本属性 sex = '' #定义构造函数 ...

  6. Nginx使用rewrite重新定向

    [Rewrite重定向]Nginx使用rewrite重新定向   使用nginx做重新定向. nginx参考网址:http://blog.sina.com.cn/s/blog_97688f8e0100 ...

  7. Toolkit tool 获取屏幕、显示在屏幕中心

    2018-11-11  15:30:05开始写 Toolkit tool = Toolkit.getDefaultToolkit(); Dimension d = tool.getScreenSize ...

  8. Linux 运维测试及第三应用及测试工具

    一 .第三方应用及测试工具链接地址 https://pan.baidu.com/s/1rLQ5NCZvxcy93YQ4fGFaBQ 1.linux LSI系列raid卡监测工具 1)使用参数详解链接: ...

  9. 即时通信系统中实现聊天消息加密,让通信更安全【低调赠送:C#开源即时通讯系统(支持广域网)——GGTalk4.5 最新源码】

    在即时通讯系统(IM)中,加密重要的通信消息,是一个常见的需求.尤其在一些政府部门的即时通信软件中(如税务系统),对即时聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据.我在最新 ...

  10. importlib

    Python提供了importlib包作为标准库的一部分.目的就是提供Python中import语句的实现(以及__import__函数).另外,importlib允许程序员创建他们自定义的对象,可用 ...