初始化时引发TypeError的子类化属性__

2024-04-24 10:47:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经对属性进行了子类化,试图向它添加一个锁,以便对它的访问是原子的(一次只能有一个线程对它进行读写)。但我在初始化时遇到了错误,也不知道为什么。你知道吗

要清楚的是:我不想做描述符,我希望能够使用@atomic\u property decorator而不是@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)

这是伊普顿的回溯。你知道吗

    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

Tags: nameselfnonelockobjdocreturninit
2条回答

似乎使用property.setter再次调用__init__,这看起来很奇怪(再次初始化同一个对象?)你知道吗

不管怎样,你需要让property做它的工作,如果你根本不使用property.__init__,你怎么能期望它正常工作呢?你可以这样做,例如:

class atomic_property(property):

    def __init__(self, *args, **kwargs):
        #print(args,kwargs) #uncomment to see this be called again when using .setter !
        super(atomic_property,self).__init__(*args,**kwargs)       
        self.lock = threading.Lock()

    def __get__(self, obj, objtype=None):
        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)

你还远远没有用你的代码正确地将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)

相关问题 更多 >