Python修改__获取属性__

w41d8nur  于 2023-01-06  发布在  Python
关注(0)|答案(1)|浏览(101)

我想修改"父类"中_* getattribute 的行为(原因是许多属性都在XML元素中,并且由于其他原因,我不想将XML元素中的所有信息作为属性转储到类中)我尝试过的方法是在类中定义一个属性,该属性收集必须在XML元素中搜索的属性的名称(仅在这些情况下, getattribute *_的行为发生了变化)。

    • 重要信息!*我将编写一个简单的示例,因为问题仅出现在_ getattribute *_方法中,而不是XML管理部分。
class Parent:

    def __init__(self):

        self.parentAttr = "some string"

    @property
    def specialAttrs(self):
        return {"parentAttr"}

    def __getattribute__(self, attr: str):

        if attr in self.specialAttrs:
            return "SPECIAL! " + self.__dict__[attr]

        else:
            return super().__getattribute__(attr)

foo = Parent()
print(foo.parentAttr)

将引发此错误

RecursionError                            Traceback (most recent call last)
Cell In[12], line 20
     17             return super().__getattribute__(attr)
     19 foo = Parent()
---> 20 print(foo.parentAttr)

Cell In[12], line 13, in Parent.__getattribute__(self, attr)
     11 def __getattribute__(self, attr: str):
---> 13     if attr in self.specialAttrs:
     14         return "SPECIAL! " + self.__dict__[attr]
     16     else:

Cell In[12], line 13, in Parent.__getattribute__(self, attr)
     11 def __getattribute__(self, attr: str):
---> 13     if attr in self.specialAttrs:
     14         return "SPECIAL! " + self.__dict__[attr]
     16     else:

    [... skipping similar frames: Parent.__getattribute__ at line 13 (2970 times)]

Cell In[12], line 13, in Parent.__getattribute__(self, attr)
     11 def __getattribute__(self, attr: str):
---> 13     if attr in self.specialAttrs:
     14         return "SPECIAL! " + self.__dict__[attr]
     16     else:

RecursionError: maximum recursion depth exceeded

显然,类试图查找specialAttrs属性,这导致了对specialAttrs的递归搜索。
解决方案可以是通过{" parentAttr "}更改自定义特殊属性

class Parent:

    def __init__(self):

        self.parentAttr = "some string"

    def __getattribute__(self, attr: str):

        if attr in {"parentAttr"}:
            return "SPECIAL! " + self.__dict__[attr]

        else:
            return super().__getattribute__(attr)

foo = Parent()
print(foo.parentAttr)

图纸:

SPECIAL! some string

但是我需要修改specialAttrs的能力,因为其他类继承specialAttrs并扩展它。

class Son(Parent):

    def __init__(self):

        self.sonAttr = "other string"

        super().__init__()

    @property
    def specialAttrs(self):
        return super().specialAttrs.union({"sonAttr"})

我有点累了。有什么建议吗?谢谢!

编辑1(Pranav Hosangadi建议)

这是我之前提出的解决方案,稍微扩展了一下。

class Parent:

    def __init__(self):

        self.parentAttr = "some string"

    def __getattribute__(self, attr: str):

        if attr in {"parentAttr"}:
            return "SPECIAL! " + self.__dict__[attr]

        else:
            return super().__getattribute__(attr)

class Son(Parent):

    def __init__(self):

        self.sonAttr = "other string"

        super().__init__()

    def __getattribute__(self, attr: str):

        if attr in {"sonAttr"}:
            return "SPECIAL! " + self.__dict__[attr]

        else:
            return super().__getattribute__(attr)

foo = Son()
print(foo.parentAttr)

图纸:

SPECIAL! some string

它工作..但是!我必须在每个继承自父类的类中重新定义_* getattribute *_方法。我想避免这种方法。

11dmarpk

11dmarpk1#

我们的想法是,不希望在Parent.__getattribute__定义 * 中调用Parent.__getattribute__ *。self.specialAttrs调用self.__getattribute__('specialAttrs')
要解决此问题,请将该调用更改为super().__getattribute__('specialAttrs'),如下所示:

class Parent:
    def __init__(self):
        self.parentAttr = "some string"
        self.regAttr = 3.14

    @property
    def specialAttrs(self):
        return {"parentAttr"}

    def __getattribute__(self, attr: str):
        if attr in super().__getattribute__('specialAttrs'):
            return "SPECIAL! " + super().__getattribute__(attr)
        else:
            return super().__getattribute__(attr)

现在,它按预期工作:

foo = Parent()
print(foo.regAttr) # 3.14 
print(foo.parentAttr) # SPECIAL! some string

而且,您可以扩展Parent,而不必重新定义__getattribute__

class Son(Parent):
    def __init__(self):
        super().__init__()
        self.sonAttr = "other string"
        self.regAttr = 6.28

    @property
    def specialAttrs(self):
        return super().specialAttrs.union({"sonAttr"})
    
bar = Son()
print(bar.regAttr) # 6.28
print(bar.parentAttr) # SPECIAL! some string
print(bar.sonAttr) # SPECIAL! other string

相关问题