访问另一个实例的受损成员

时间:2016-08-15 16:38:33

标签: python oop code-analysis pylint private-members

我使用此逻辑来维护Object实例的有向树:

class Object:
    def __init__(self, *parents: 'Object'):
        self.__parents = list(parents)

    @property
    def __ascendants(self):
        for parent in self.__parents:
            yield from parent.__ascendants
            yield parent

这段代码运行正常,但是PyLint抱怨__ascendantsparent的受保护成员,对于PyLint来说,这是一个客户端类。

对于受保护的,非受损的成员,这没关系:我不应该访问这些成员,因为它们可以被Object子类覆盖。

但是在这种情况下,由于属性被破坏,子类无法覆盖它们,这就是为什么我允许自己甚至在外部对象上使用它们(提供给构造函数)。

TLDR ;我正在寻找一种方法让PyLint接受访问客户端子类的受损属性,而不必每次都使用#pylint: disable=protected-access,或者全局禁用警告。

看起来我可以使用astng回调来注册MANAGER,并转换模块以便PyLint可以使用其他信息。但是,我只能添加存根成员(这样可以在没有警告的情况下使用动态添加的成员),而且我不能确定我能以这种方式解决我的问题。

我还尝试添加assert isinstance(parent, Object),但它没有帮助。

编辑

我能够编写代码,以便PyLInt不会引发protected-access,而只会引发bad-staticmethod-argument。我不会在这个特定的课程中使用其他静态方法,所以这可能是这个问题的可接受的答案:

class Object:
    def __init__(self, *parents: 'Object'):
        self.__parents = list(parents)

    @staticmethod
    def __get_ascendants(self: 'Object'):
        for parent in self.__parents:
            yield from self.__get_ascendants(parent)
            yield parent

编辑2 :(受@ shx2启发)

使用具有正确参数名称的lambda也会欺骗Pylint:

class Object:
    def __init__(self, *parents: 'Object'):
        self.__parents = list(parents)

    @property
    def __ascendants(self):
        get_ascendants = lambda self: self.__ascendants

        for parent in self.__parents:
            yield from get_ascendants(parent)
            yield parent

编辑3 :因为名称不会从生成器表达式(或列表omprehensions)中泄漏,所以它也可以这样写:

from itertools import chain

class Object:
    def __init__(self, *parents: 'Object'):
        self.__parents = list(parents)

    @property
    def __ascendants(self):
        return chain(*(
           chain(self.__ascendants, (self, ))
           for self in self.__parents
        ))

2 个答案:

答案 0 :(得分:1)

为什么要将ascendants方法设为受损属性?如果您真的想要使用这样一个复杂的继承并为每个超类保留多个parents属性,那么修改parents将起作用。但是,似乎没有用于修改ascendants函数,因为它属于类,而不属于对象本身:

class Object(object):
    def __init__(self, parents):
        self.__parents = list(parents)

    def ascendants(self):
        for parent in self.__parents:
            yield from parent.ascendants()
            yield parent

答案 1 :(得分:1)

  

我正在寻找一种让PyLint接受访问客户端子类的受损属性的方法

有愚弄pylint的方法。

一种方法是将parent伪装成self

@property
def __ascendants(self):
    for parent in self.__parents:
        self = parent
        yield from self.__ascendants
        yield self

另一个是使用getattr间接访问该属性。而不是:

yield from parent.__ascendants

做的:

yield from getattr(parent, '__ascendants')