object的实例是 python_Python的实例对象是如何一步一步被创建出来的?

一切皆对象!!!

题主已经知道new能创建对象,那么想必应该也知道 () 这个操作符代表什么意思,他是去调用call方法,那么如何去判断一个对象有没有call方法

答案是

callable

下面看下Python代码

def test1():

pass

class Test2():

pass

print(callable(int))

print(callable(dict))

print(callable(test1))

print(callable(Test2))

上面的例子都是返回True,证明他们都是支持()这个操作的,也就是都有callable方法

再来看下元类type

callable(type)

毋庸置疑,这个也是True

所以正常的逻辑是

在解释器初始化的时候,调用type的call方法生成了class, 在程序实例化的时候,调用type的call方法生成了实例

!!!

很奇怪是不是,怎么都是type的call方法

这里就要说明下,type的type是什么?是type!!!

注意,这里不是调用自己的call方法,是调用上一级的call方法, 只不过上一级还是type

是不是打破了你的认识,这里跟new和init方法没有一点点关系,全是call方法再起作用

下面给出验证例子

class MyType(type):

def __init__(self, *args, **kwargs):

print('MyType __init__方法执行了', args, kwargs)

super(MyType, self).__init__(*args, **kwargs)

def __new__(cls, *args, **kwargs):

print('MyType __new__方法执行了', args, kwargs)

return type.__new__(cls, *args, **kwargs)

def __call__(self, *args, **kwargs):

print('MyType __call__方法执行了', args, kwargs)

return super(MyType, self).__call__(*args, **kwargs)

class MyClass(metaclass=MyType):

def __init__(self, *args, **kwargs):

print('MyClass __init__方法执行了', args, kwargs)

super(MyClass, self).__init__(*args, **kwargs)

def __new__(cls, *args, **kwargs):

print('MyClass __new__方法执行了', args, kwargs)

return object.__new__(cls, *args, **kwargs)

def __call__(self, *args, **kwargs):

print('MyClass __call__方法执行了', args, kwargs)

print('=======运行前输出=======')

MyClass()

输出结果如下

MyType __new__方法执行了 ('MyClass', (), {'__module__': '__main__', '__qualname__': 'MyClass', '__init__': , '__new__': , '__call__': , '__classcell__': }) {}

MyType __init__方法执行了 ('MyClass', (), {'__module__': '__main__', '__qualname__': 'MyClass', '__init__': , '__new__': , '__call__': , '__classcell__': }) {}

=======运行前输出=======

MyType __call__方法执行了 () {}

MyClass __new__方法执行了 () {}

MyClass __init__方法执行了 () {}

是不是,在MyClass实例化的时候调用了上一级MyType的call方法

如果你想调用MyClass的call方法,得这样MyClass()()

为什么第一行少了type呢,因为第一次调用的是type的call方法,这里没办法重写,所以没有任何输出,而后续的就是调用的MyType的call方法,就有输出了

可是上面明明跟new init有关系啊,他们明确的执行了,跟上面说的不一样,其实这里可以大胆一点,猜测new和init方法都是在call方法里面执行的!!!

接下来到了查看type的call方法了。

一下代码摘自Python3.7.0源码 typeobject.c

static PyObject *

type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)

{

PyObject *obj;

if (type->tp_new == NULL) {

PyErr_Format(PyExc_TypeError,

"cannot create '%.100s' instances",

type->tp_name);

return NULL;

}

obj = type->tp_new(type, args, kwds);

obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);

if (obj == NULL)

return NULL;

/* Ugly exception: when the call was type(something),

don't call tp_init on the result. */

if (type == &PyType_Type &&

PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&

(kwds == NULL ||

(PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0)))

return obj;

/* If the returned object is not an instance of type,

it won't be initialized. */

if (!PyType_IsSubtype(Py_TYPE(obj), type))

return obj;

type = Py_TYPE(obj);

if (type->tp_init != NULL) {

int res = type->tp_init(obj, args, kwds);

}

return obj;

}

果然,里面有tpnew 和 tp_init方法,验证了我们的猜测。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值