Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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_Oop_Properties - Fatal编程技术网

属性设置器在Python类中不起作用

属性设置器在Python类中不起作用,python,oop,properties,Python,Oop,Properties,我正在使用一个我无法控制的类(MainClass)。我想将我的类建立在MainClass的基础上,但要添加额外的功能。我在类(超类)中添加了一个属性(索引),但当我尝试将索引转换为属性时,@.setter似乎被忽略。这里怎么了 class MainClass(object): def __init__(self): self.name = 'abc' class SuperClass(object): def __init__(self, main, *args

我正在使用一个我无法控制的类(MainClass)。我想将我的类建立在MainClass的基础上,但要添加额外的功能。我在类(超类)中添加了一个属性(索引),但当我尝试将索引转换为属性时,@.setter似乎被忽略。这里怎么了

class MainClass(object):
    def __init__(self):
        self.name = 'abc'

class SuperClass(object):
    def __init__(self, main, *args, **kwargs):
        super(SuperClass, self).__init__(*args, **kwargs)
        self.__main = main
        self._index = 0

    def __getattr__(self, attr):
        return getattr(self.__main, attr)

    def __setattr__(self, attr, val):
        if attr == '_SuperClass__main':
            object.__setattr__(self, attr, val)
        return setattr(self.__main, attr, val)

    @property
    def index(self):
        return self._index

    @index.setter
    def index(self, value):
        self._index = value

main_object = MainClass()
super_object = SuperClass(main_object)
print('x', super_object.index, super_object.name)

super_object.index = 3
print('y', super_object.index)

super_object.index += 2
print('z', super_object.index)

您定义的
\uuuu setattr\uuuu
方法优先于
@index.setter
简化代码,它应该可以工作:

class MainClass(object):
    def __init__(self):
        self.name = 'abc'

class SuperClass(object):
    def __init__(self, main, *args, **kwargs):
        super(SuperClass, self).__init__(*args, **kwargs)
        self.__main = main
        self._index = 0

    @property
    def name(self):
        return self.__main.name

    @name.setter
    def name(self):
        return self.__main.name

    @property
    def index(self):
        return self._index

    @index.setter
    def index(self, value):
        self._index = value

main_object = MainClass()
super_object = SuperClass(main_object)
print('x', super_object.index, super_object.name)

super_object.index = 3
print('y', super_object.index)

super_object.index += 2
print('z', super_object.index)
输出:

x 0 abc
y 3
z 5

\uuuu getattr\uuuu
仅在正常查找机制失败时使用

但是,所有设置属性的尝试都会调用
\uuuuuu setattr\uuuuu
。这意味着您当前的定义将在
MainClass
实例,而不是访问属性的setter

>>> super_object._SuperClass__main.index
2
由于
\uuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

\uuuu setattr\uuuu
必须处理三种情况:

  • 属性
    \u SuperClass\uuuuu main
    本身,用于在
    \uuuu init\uuuu
    中指定给
    self.\uuuuu main
  • 分配给
    self.\uu main
  • 指定给特定于
    超类的属性
  • 记住这一点,试试看

    def __setattr__(self, attr, val):
        if attr == '_SuperClass__main':
            super().__setattr__(attr, val)
        elif hasattr(self.__main, attr):
            setattr(self.__main, attr, val)
        else:
            super().__setattr__(attr, val)
    

    我还建议使用更简单的选项,即仅从
    MainClass
    继承,而不是使用组合和委派:

    class SuperClass(MainClass):
        def __init__(self):
            super().__init__()
            self._index = 0
    
        @property
        def index(self):
            return self._index
    
        @index.setter
        def index(self, value):
            self._index = value
    

    谢谢我可以看出这是可行的,但这意味着我必须为MainClass中的所有属性设置属性和setter。这不是小事。没有办法吗?我喜欢setattr和getattr,因为它可以解决这个问题。这不是我能想到的。我还没有设法使
    属性.setter
    \uuuu setattr\uuuu
    很好地协同工作。不管怎样,只使用属性是更干净的。你有没有理由不从
    Main
    继承
    SuperClass
    ?谢谢,但这对我不起作用(我想)。我看到了MainClass对象,要创建超类对象,我必须分配所有属性(不是吗?)。那会破坏目标的