我在和赛顿捣乱,深入到基维,我一直在尝试我自己的基维财产。在
我有定义DocProperty的以下文件: my.pyx:
from kivy.properties cimport Property, PropertyStorage
from kivy._event cimport EventDispatcher
cdef inline void observable_object_dispatch(object self, str name):
cdef Property prop = self.prop
prop.dispatch(self.obj, name)
class ObservableObject(object):
# Internal class to observe changes inside a native python object.
def __init__(self, *largs):
self.prop = largs[0]
self.obj = largs[1]
super(ObservableObject, self).__init__()
def __setattr__(self, name, value):
object.__setattr__(self, name, value)
observable_object_dispatch(self, name)
cdef class DocProperty(Property):
def __init__(self, defaultvalue=None, rebind=False, **kw):
self.baseclass = kw.get('baseclass', object)
super(DocProperty, self).__init__(defaultvalue, **kw)
self.rebind = rebind
cpdef link(self, EventDispatcher obj, str name):
Property.link(self, obj, name)
cdef PropertyStorage ps = obj.__storage[self._name]
ps.value = ObservableObject(self, obj, ps.value)
cdef check(self, EventDispatcher obj, value):
if Property.check(self, obj, value):
return True
if not isinstance(value, object):
raise ValueError('{}.{} accept only object based on {}'.format(
obj.__class__.__name__,
self.name,
self.baseclass.__name__))
cpdef dispatch(self, EventDispatcher obj, str name):
'''Dispatch the value change to all observers.
.. versionchanged:: 1.1.0
The method is now accessible from Python.
This can be used to force the dispatch of the property, even if the
value didn't change::
button = Button()
# get the Property class instance
prop = button.property('text')
# dispatch this property on the button instance
prop.dispatch(button)
'''
cdef PropertyStorage ps = obj.__storage[self._name]
ps.observers.dispatch(obj, ps.value, (name,), None, 0)
^{pr2}$
和一个快速的sript来尝试一下:my.py
# -*- coding: utf-8 -*-
from kivy.event import EventDispatcher
import pyximport
pyximport.install()
from properties import DocProperty
if __name__ == '__main__':
class ED(EventDispatcher):
doc = DocProperty()
def on_doc(self, obj, value):
print 'printing doc', self.doc
class DumbObj(object):
def __init__(self, num):
self._num = num
@property
def num(self):
return 5
@num.setter
def num(self, value):
self._num = value
ed = ED()
ed.doc = DumbObj(3)
ed.doc.num = 4
当我跑的时候我的.py,我在DocProperty的dispatch方法上得到一个“Signature not compatible with previous declaration”,因为我尝试重写at属性上的声明,以便它可以比原始代码声明多接受一个参数。有没有可能重载pxd上声明的cpdef方法?如果是,我做错了什么?在
编辑:
在@ead's suggestion之后,我尝试在dispatch
的声明中用普通的def
替换{
我不知道你为什么要做这样的事,我也不确定从长远来看这是明智之举。但这个问题并非没有兴趣(至少是理论上的)。在
有method overriding-相同的名称,相同的签名,不同的实现-这在Cython中是可能的,例如:
现在:
^{pr2}$这些代码行的内容远不止这些:分派不是在Python中进行的,而是在C级上进行的——比Python的分派快得多,但灵活性稍差。在
还有function overloading-相同的名称,不同的签名,两种方法都可以使用-这是not really possible in Python,因此在Cython中也不是这样。但是,与C语言不同,Python允许更改同名方法的签名,以便使用最后一个签名:
您可以使用Cython实现相同的行为,使用
def
而不是cpdef
函数(但是函数不应该再在pxd
中声明,尽管您可以在父类中将其保留为cpdef
):现在会导致错误:
这一次使用Python分派(here是关于它如何工作的更多信息)并且类层次结构中
get_number
的“最后一个”定义需要一个未提供的参数,因此出现错误。在还有一件事:为什么不能更改函数的签名并将其保留为
cpdef
?在cpdef
函数具有静态类型部分。类A
及其所有子类的函数表中都有一个指向get_number(self)
实现的指针,该指针的类型为:例如,在
A
的表中:与
get_number(self, int m)
相对应的类型是:签名中有一个附加的
int
,因此它是不同类型的,不能写入__pyx_vtabstruct_4test_A.get_number
-在这里,Cython表现为C另一方面,在同一个结构中不能有两个不同的成员,因此真正的重载(例如C++中的名称转换)是不可能的。在
相关问题 更多 >
编程相关推荐