子类化属性在__init__上引发TypeError

时间:2016-06-20 16:37:08

标签: python concurrency properties

我已经将子属性设置为尝试向其添加锁定,因此对它的访问是原子的(一次只有一个线程可以读取和写入)。但我在初始化程序中遇到错误,无法找出原因。

要明确:我不想创建描述符,我希望能够使用@atomic_property装饰器而不是@property

class atomic_property(property):

    def __init__(self, func, name=None, doc=None):
        self.__name__ = name or func.__name__
        self.__module__ = func.__module__
        self.__doc__ = doc or func.__doc__
        self.func = func
        self.lock = threading.Lock()

    def __get__(self, obj, objtype=None):
        with self.lock:
            return self.func(obj)

    def __set__(self, obj, value):
        with self.lock:
            return self.func(obj, value)

这是来自ipython的追溯。

    In [12]: class a(object):
    def __init__(self):
        self._b = 1
    @utils.atomic_property
    def b(self):
        return self._b
    @b.setter
    def b(self, val):
        self._b = val
   ....:         
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-daec89385bc3> in <module>()
----> 1 class a(object):
      2     def __init__(self):
      3         self._b = 1
      4     @utils.atomic_property
      5     def b(self):

<ipython-input-12-daec89385bc3> in a()
      5     def b(self):
      6         return self._b
----> 7     @b.setter
      8     def b(self, val):
      9         self._b = val

TypeError: __init__() takes from 2 to 4 positional arguments but 5 were given

2 个答案:

答案 0 :(得分:2)

你远没有用你的代码正确地继承property:一次 你重写了一些方法,但从不关心调用上游方法,以便它可以开展业务。

不是说不能这样做,如果你真的在你的子类中重现超类上的方法将执行的所有行为 - 但即使不查看超类的代码(在cPython的情况下是在本机代码中) ) - 可以看出self.func是getter函数,或者它是setter函数 - 它不能同时存在。

如果你只是想注释你将使用的属性并执行你想要的动作,并将余数委托给原始代码,它将非常 可能只是工作:

class atomic_property(property):

    def __init__(self,*args, **kw):
        super(atomic_property, self).__init__(*args, **kw)
        self.lock = threading.Lock()

    def __get__(self, obj, obj_type):
        with self.lock:
            return super(atomic_property, self).__get__(obj, objtype)

    def __set__(self, obj, value):
        with self.lock:
            return super(atomic_property, self).__set__(obj, value)

答案 1 :(得分:1)

似乎使用x = linspace(0, 1, 20); y = x; i_cell = {1:6, 7:11, 12:20}; for i = 1:length(i_cell) figure indices = i_cell{i} plot(x(indices), y(indices)) end 再次调用property.setter,这似乎很奇怪(多次初始化同一个对象?)

无论如何,您需要让__init__完成它的工作,如果您根本不使用property,您认为它如何正常工作?你可以做这样的事情,例如:

property.__init__