python __new__()和__init__()哪个更早?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python __new__()和__init__()哪个更早?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3758字,纯文字阅读大概需要6分钟。
内容图文
通过代码验证是最靠谱的:
class Foo(object): def __init__(self): print 'foo init' def __new__(cls,*args,**kwargs): print 'foo new' return object.__new__(cls,*args,**kwargs) foo = Foo() print type(foo)
结果:
>>> foo new foo init <class '__main__.Foo'> >>>
可以看出来__new__()执行顺序比较早,实际上,新式类的__new__()才是真正的初始化函数。
Ps:cls表示一个类,一个当前要被实例化的类,参数由py解释器自动提供。
上述代码只能论证__new__比__init__更早被调用。但是why?
查了下官方文档:https://docs.python.org/2.7/reference/datamodel.html#object.__new__
object.__new__(cls[, ...]):
创建一个实例:Called to create a new instance of class cls.
静态方法:__new__() is a static method that takes the class of which an instance was requested as its first argument.
通过调用父辈的__new__:super(currentclass, cls).__new__(cls[, ...])
创建好实例才__init__:If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...])
object.__init__(cls[,...]):
有一句话:__new__() to create it, and __init__() to customise it
通过官方文档就能了解__new__()和__init__()的先后顺序了。但是why?
__init__()对应的实现代码:
static int object_init(PyObject *self, PyObject *args, PyObject *kwds) { int err = 0; if (excess_args(args, kwds)) { PyTypeObject *type = Py_TYPE(self); if (type->tp_init != object_init && type->tp_new != object_new) { err = PyErr_WarnEx(PyExc_DeprecationWarning, "object.__init__() takes no parameters", 1); } else if (type->tp_init != object_init || type->tp_new == object_new) { PyErr_SetString(PyExc_TypeError, "object.__init__() takes no parameters"); err = -1; } } return err; }
__new__()对应的实现代码:
static PyObject * object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int err = 0; if (excess_args(args, kwds)) { if (type->tp_new != object_new && type->tp_init != object_init) { err = PyErr_WarnEx(PyExc_DeprecationWarning, "object() takes no parameters", 1); } else if (type->tp_new != object_new || type->tp_init == object_init) { PyErr_SetString(PyExc_TypeError, "object() takes no parameters"); err = -1; } } if (err < 0) return NULL; if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { static PyObject *comma = NULL; PyObject *abstract_methods = NULL; PyObject *builtins; PyObject *sorted; PyObject *sorted_methods = NULL; PyObject *joined = NULL; const char *joined_str; /* Compute ", ".join(sorted(type.__abstractmethods__)) into joined. */ abstract_methods = type_abstractmethods(type, NULL); if (abstract_methods == NULL) goto error; builtins = PyEval_GetBuiltins(); if (builtins == NULL) goto error; sorted = PyDict_GetItemString(builtins, "sorted"); if (sorted == NULL) goto error; sorted_methods = PyObject_CallFunctionObjArgs(sorted, abstract_methods, NULL); if (sorted_methods == NULL) goto error; if (comma == NULL) { comma = PyString_InternFromString(", "); if (comma == NULL) goto error; } joined = PyObject_CallMethod(comma, "join", "O", sorted_methods); if (joined == NULL) goto error; joined_str = PyString_AsString(joined); if (joined_str == NULL) goto error; PyErr_Format(PyExc_TypeError, "Can't instantiate abstract class %s " "with abstract methods %s", type->tp_name, joined_str); error: Py_XDECREF(joined); Py_XDECREF(sorted_methods); Py_XDECREF(abstract_methods); return NULL; } return type->tp_alloc(type, 0); }
我们就关注问题本身,why __new__比__init__更早,看到python源代码(C语言实现):
可以看到object_init()实际上并没有什么代码,只是两个if判断,而object_new()才是各种属性搞起:
static PyObject *comma = NULL;所以问题得到解决:__new__()的确是创建一个新的实例,__init__()在实例上面进行customize(定制)。
PyObject *abstract_methods = NULL;
PyObject *builtins;
PyObject *sorted;
PyObject *sorted_methods = NULL;
PyObject *joined = NULL;
貌似__new__()是新式类(继承自object)内置有的。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/emaste_r/article/details/47322827
内容总结
以上是互联网集市为您收集整理的python __new__()和__init__()哪个更早?全部内容,希望文章能够帮你解决python __new__()和__init__()哪个更早?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。