填充tp_dict 在Python虚拟机类机制之对象模型(一)这一章中,我们介绍了Python的内置类型type如果要完成到class对象的转变,有一个重要的步骤就是填充tp_dict对象,这是一个极其繁杂的过程 typeobject.c int PyType_Ready(PyTypeObject *type) { PyObject *dict, *bases; PyTypeObject *base; Py_ssize_t i, n; …… //设定tp_dict dict = type->tp…
instance对象中的__dict__ 在Python虚拟机类机制之从class对象到instance对象(五)这一章中最后的属性访问算法中,我们看到“a.__dict__”这样的形式. # 首先寻找'f'对应的descriptor(descriptor在之后会细致剖析) # 注意:hasattr会在<class A>的mro列表中寻找符号'f' if hasattr(A, 'f'): descriptor = A.f type = descriptor.__class__ if hasat…
从slot到descriptor 在Python虚拟机类机制之填充tp_dict(二)这一章的末尾,我们介绍了slot,slot包含了很多关于一个操作的信息,但是很可惜,在tp_dict中,与__getitem__关联在一起的,一定不会是一个slot,原因很简单,slot不是一个PyObject,它不能存放在dict对象中.当然,我们再深入思考一下,会发现slot也不会被“调用”.既然slot不是一个PyObject,那么它就没有type,也就无从谈起什么tp_call了,所以slot是无论如何…
Bound Method和Unbound Method 在Python中,当对作为属性的函数进行引用时,会有两种形式,一种称为Bound Method,这种形式是通过类的实例对象进行属性引用,而另一种则是通过类进行属性引用,称为Unbound Method.当然,对Bound Method和Unbound Method的调用形式是不同的,其原因可以追溯到LOAD_ATTR中 demo2.py class A(object): def g(self, value): self.value = va…
从class对象到instance对象 现在,我们来看看如何通过class对象,创建instance对象 demo1.py class A(object): name = "Python" def __init__(self): print("A::__init__") def f(self): print("A::f") def g(self, aValue): self.value = aValue print(self.value) a =…
Python对象模型 在Python2.2之前,Python中存在着一个巨大的裂缝,就是Python的内置类type,比如:int和dict,这些内置类与程序员在Python中自定义的类并不是同一级别的类.比如说,程序员定义了class A,又定义了class B,B可以继承于A,这是理所当然的.但是,Python的内置类却不能被继承.程序员不能创建一个类继承于int或者dict.于是,Python的开发者在Python2.2中花费了巨大的精力填补了内置类和用户自定义class之间的鸿沟,使得两…
用户自定义class 在本章中,我们将研究对用户自定义class的剖析,在demo1.py中,我们将研究单个class的实现,所以在这里并没有关于继承及多态的讨论.然而在demo1.py中,我们看到了许多类的内容,其中包括类的定义.类的构造函数.对象的实例化.类成员函数的调用等 demo1.py class A(object): name = "Python" def __init__(self): print("A::__init__") def f(self):…
函数执行时的名字空间 在Python虚拟机函数机制之无参调用(一)这一章中,我们对Python中的函数调用机制有个大概的了解,在此基础上,我们再来看一些细节上的问题.在执行MAKE_FUNCTION指令时,调用了PyFunction_New方法,这个方法有一个参数是globals,这个globals最终将称为与函数f对应的PyFrameObject中的global名字空间——f_globals ceval.c case MAKE_FUNCTION: v = POP(); /* code obje…
位置参数的默认值 在Python中,允许函数的参数有默认值.假如函数f的参数value的默认值是1,在我们调用函数时,如果传递了value参数,那么f调用时value的值即为我们传递的值,如果调用时没有传递value的值,那么f将使用value的默认值,即为1.那么,带有默认值的位置参数,其实现机制与一般的位置参数有何不同呢? 我们先来看一下demo3.py # cat demo3.py def f(a=1, b=2): print(a + b) f() f(b=5) 然后我们用dis模块编译下…
扩展位置参数和扩展键参数 在Python虚拟机函数机制之参数类别(三)的例3和例4中,我们看到了使用扩展位置参数和扩展键参数时指示参数个数的变量的值.在那里,我们发现在函数内部没有使用局部变量时,co_nlocals和co_argcount的值已经不再相同了.从它们的差异我们猜测,当使用扩展位置参数*args或者扩展键参数**kwargs时,实际是作为一个局部变量来实现的.同时,我们还猜测,在Python内部,*args是由PyTuppleObject实现的,而**kwargs是由PyDictO…