Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python __初始化更改父类属性_Python - Fatal编程技术网

Python __初始化更改父类属性

Python __初始化更改父类属性,python,Python,我真的很困惑,这颠覆了我对Python中OOP的理解。 我不明白发生了什么事 问题。我为某些视图集创建父类: class BaseViewSet(object): bindings = {} def __init__(self): # Check that inherited class have updates for bindings if hasattr(self, 'bindings_update') \

我真的很困惑,这颠覆了我对Python中OOP的理解。 我不明白发生了什么事

问题。我为某些视图集创建父类:

class BaseViewSet(object):
    bindings = {}

    def __init__(self):
        # Check that inherited class have updates for bindings
        if hasattr(self, 'bindings_update') \
                and isinstance(self.bindings_update, dict):
            self.bindings.update(self.bindings_update)
继承该类后:

class ClientsViewSet(BaseviewSet):
    bindings_update = {
        'get': 'get_clients_list',
    }
好的,看起来还正常

import BaseViewSet

b = BaseViewSet()

>>> b.bindings
{}
但我不明白接下来会发生什么:

import BaseViewSet
import ClientsViewSet

>>> BaseViewSet.bindings
{}

c = ClientsViewSet()
>>> c.bindings
{'get': 'get_clients_list'}

>>> BaseViewSet.bindings
{'get': 'get_clients_list'}  # WTF O_O ???!!!

b = BaseViewSet()
b.bindings
{'get': 'get_clients_list'}  # I started cry here...
所以我不明白为什么继承类实例的创建会影响父类属性。 实际上,当一个带有
绑定的视图集\u update
影响另一个继承的视图集时,我遇到了一些有趣的错误

请帮帮我

使现代化 非常感谢大家的帮助。 当然我忘了,我的
绑定
是类属性,所以当我在子类的
\uuu init\uuuu
中更改它时,它在所有继承的实例中都发生了更改

所以,解决方案,我用来解决我的问题:

from copy import deepcopy

class BaseViewSet(object):
    bindings = {'get': 'get_instance'}

    def __new__(cls, *args, **kwargs)
        """ `__new__` called first and create instance of class """

        # It is new instance of my class
        obj = super().__new__(*args, **kwargs)

        # Deepcopy bindings dict from inherited class to avoid override
        obj.bindings = deepcopy(cls.bindings)

        # Now I have deal with instance's copied `bindings`,
        # not with BaseViewSet.bindings
        if hasattr(cls, 'binding_updates'):
            assert isinstance(cls.bindings_update, dict)
            obj.bindings.update(cls.bindings_update)

        return obj

class UserViewSet(BaseViewSet):
    bindings_update = {'post': 'create_user'}

b = BaseViewSet()
>>> b.bindings
{'get': 'get_instance'}

u = UserViewSet()
>>> u.bindings
{'get': 'get_instance', 'post': 'create_user'}

>>> BaseViewSet.bindings
{'get': 'get_instance'}  # Olala, my bindings rescued :D

绑定
是类的属性,而不是对象。 这就是为什么对
绑定
字典的更改会影响类的原因,因为它们会影响类

如果要将数据分配给单个对象,这就是
\uuuuu init\uuuu
方法的作用:

class BaseViewSet(object):

    def __init__(self):
        self.bindings = {}
        if hasattr(self, 'bindings_update') \
          and isinstance(self.bindings_update, dict):
            self.bindings.update(self.bindings_update)
        return


class ClientsViewSet(BaseViewSet):

    def __init__(self):
        self.bindings_update = {
          'get': 'get_clients_list',
        }
        super(ClientsViewSet, self).__init__()
        return
然后,假设您已经适当地导入了所有内容:

>>> b = BaseViewSet()
>>> b.bindings
{}
>>> BaseViewSet.bindings
AttributeError: type object 'BaseViewSet' has no attribute 'bindings'

>>> c = ClientsViewSet()
>>> c.bindings
{'get': 'get_clients_list'}
>>> BaseViewSet.bindings
AttributeError: type object 'BaseViewSet' has no attribute 'bindings'

>>> b = BaseViewSet()
>>> b.bindings
{}
请注意,您不能再访问
BaseViewSet.bindings
,因为它不再是类属性。
您必须确保没有其他代码尝试使用该属性。

绑定
是一个静态变量。这意味着,如果您在一个类中修改它,那么您就是在为所有类修改它


您应该将批次移动到
\uuuu init\uuuu
中,或者创建一个新的字典,从类1复制值,以便您修改类自己的绑定。这样,当您更新字典时,您将仅针对该实例进行更新。

绑定
是一个静态变量。这意味着如果您在一个类中修改它,那么您就是在为所有类修改它。您应该将该批代码移到
\uuuuu init\uuuuu
中,或者创建一个新的字典,从类1复制值,以便您修改类自己的绑定。是的,我很愚蠢。我将BaseVievSet中的
\uuuuu init\uuuuuuuu
更改为
\uuuu new\uuuuuuu
,并将deepcopy
绑定更改为创建的实例。现在它可以像我等待它一样工作了。另外,您应该能够在
\uuuu init\uuuu
中转到
self.bindings=deepcopy(self.bindings)
。没有真正的理由使用
\uuuuu new\uuuuu
。@shadow,当然,你是对的,但我这里的代码是简化的,我有一些更难的逻辑,所以这是一个原因,为什么我要将它移动到
\uuuuuuu new\uuuuuuu
,那就好了。只是确保你知道另一种方式。我根据评论创建了一个答案-如果它解决了您的问题,请随意标记我的答案为正确:)谢谢,凯文。您的建议很有效,但我需要一个解决方案,它允许在每个子视图集中没有
\uuuuu init\uuuu
,因为我将有数百个。您可以从更新的问题中查看我的解决方案,我对您的意见非常感兴趣。