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

Accessing mangled member of another instance

我使用这个逻辑来维护 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 而言,客户端 class.

如果是受保护的、未损坏的成员,那就没问题了:我不应该访问这样的成员,因为它们可能会被 Object subclass.

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

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

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

我也试过添加assert isinstance(parent, Object),但没有用。

编辑 :

我能够编写代码,使 PyLInt 不会引发 protected-access,而只会引发 bad-staticmethod-argument。我没有在这个特定的 class 中使用其他 staticmethod s,所以也许这可能是这个问题的一个可接受的答案:

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
        ))

为什么要使 ascendants 方法成为一个损坏的 属性?如果你真的想使用如此复杂的继承并为每个 superclasses 保留多个 parents 属性,则 mangling parents 将起作用。但是,似乎在 mangling ascendants 函数中没有用,因为它属于 class,而不属于对象本身:

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

I'm looking for a way to make PyLint accept accessing mangled attributes of a client subclass

有办法骗过 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')