避免 Pylint 警告 E1101: 'Instance of .. has no .. member' for class with dynamic attributes

Avoid Pylint warning E1101: 'Instance of .. has no .. member' for class with dynamic attributes

想象一个函数,它 动态地 使用 setattr 向对象添加属性。这样做的原因是我想将一些外部结构(例如给定的参数树)映射到一个对象:

my_object = SomeClass()
apply_structure(my_object, some_descriptor)
my_object.device1.enabled = True

从技术上讲这是可行的,但当然 Pylint 正确地抱怨 'device1' 不是 SomeClass 的成员。

我可以禁用警告,但那会很糟糕(因为我仍然希望在属性因拼写错误等原因不存在的所有情况下都收到警告)。

是否有一种通用且合法(Pylint 证明)的方式来动态地将成员添加到对象而不导致警告?

或者:我可以只为一个 对象 而不是 line/block/file 禁用 Pylint 吗?

解释:

您可能想知道,当我计划以后以硬编码的方式访问这些属性时,为什么要动态地为对象配备成员属性。

原因是:我有一个程序的动态部分(装饰发生的地方)和一个静态部分专门用于某个场景。所以我 可以 也为这种情况创建一个静态 class 但在很多情况下这会过大。

以下专用代码可能允许访问可能连接到某些总线的设备的某些参数:

class MyDeviceHandler:
   on_get_some_subtree_element(self):
      return _some_internal_value
   on_set_some_subtree_element(self, value):
      _some_internal_value = value

dev = MyDeviceHandler()

decorate_object_with_device_structure(dev, 'some/attached/device')

dev.some.subtree.element = 5       <--- will call the set-callback
x = dev.some.subtree.element       <--- will call the get-callback

所以 'some/attached/device' 背后的结构可能是任意的并且非常复杂,我不想在 class 结构中重现它。

消除此警告的一种方法是 create/access 基于 dict 的树:

dev['some']['subtree']['element'] = 5

但这更难写而且读起来也不好 - 我这样做只是为了让 Pylint 安静下来。

只是提供现在对我有用的答案 - 正如 The Compiler 建议您可以为项目中有问题的 class 添加规则 .pylintrc:

[TYPECHECK]
ignored-classes=Fysom,MyClass

This page 描述了错误并提供了一种直接在代码中解决错误的简单方法。 tl;博士

当为不存在的成员访问对象(变量、函数等)时使用。

误报:此消息可能会报告动态创建但在访问时存在的对象成员。

一位评论者提到可以在文件顶部的一行中用 # pylint: disable=no-member 禁用它。我还发现您可以根据 this reddit entry.

使用 # pylint: disable=E1101

试试这个!我的问题解决了!

Pylint 不理解 Django 的动态字段。因此,我们需要向 Pylint 教授 Django 是什么

*对于 vscode 在 Windows 10 *

$ pip install pylint-django
$ cd your_project_folder
$ code . // run vscode  

安装 Python 的扩展、Django 片段、vscode

中的 Django 模板

在vscode中打开.vscode/settings.json并添加:

{
   "python.linting.pylintEnabled": true,
   "python.linting.enabled": true,
   "python.pythonPath": "venv\Scripts\python.exe",
   "python.linting.pylintArgs": [
       "--load-plugins",
       "pylint_django"
   ],
}

PyLint 在两种情况下给出此类错误 Link:

  • 当一个对象(变量,函数,...)被访问时使用 不存在的成员。

  • 误报:此消息可能报告对象成员是 动态创建,但在访问时存在。

因为这个错误被识别为E1101错误。您可以通过在代码中添加以下行来解决问题。

# pylint: disable=E1101

对我来说,安装 pylint-django 就解决了这个问题:

pip install pylint-django

我可以通过将 __getattr__ 方法添加到我的 class 来避免此警告,当在对象上找不到属性时 python 调用该方法。虽然绝对不是最干净的解决方案,但它适用于我的特定用例,因为 pylint 认为对象有效。

import warnings
class AppConfiguration(object):     
    ... 
    def __getattr__(self, name):
        ''' will only get called for undefined attributes '''
        warnings.warn('No member "%s" contained in settings config.' % name)
        return ''

有关 __getattr__ 方法的更多信息可以是 found here

犹豫要不要添加到这个答案中,因为如果有明确的方法可以用 pylint 做到这一点,我更愿意。但是有一个绕过解决方案的黑客正在工作(至少从 pylint 2.7.4 开始)。在此示例代码中,我使用“getattr”空操作来防止 pylint 认为它知道有关该对象的任何信息。显然,这种简单的事情可能不会继续向前发展,但我喜欢这样一个事实,即您可以控制您希望 pylint 忽略哪些确切的事情,而无需触摸源文件以外的任何东西,也不必在整个源文件中全局禁用检查.

class MyClass():
    """an empty class"""

myc = MyClass()
print(myc.hello_world)  # pylint no-member
myc = globals()['myc']
print(myc.hello_world)  # no error flagged

class MyDeviceHolder1():
    """a device holder class"""
    def __init__(self):
        self.devices = MyClass()

mdh1 = MyDeviceHolder1()
print(mdh1.devices.hello_world)  # pylint no-member

class MyDeviceHolder2():
    """a device holder class"""
    def __init__(self):
        self.devices = MyClass()
        self.devices = getattr(self, 'devices')

mdh2 = MyDeviceHolder2()
print(mdh2.devices.hello_world)  # no error flagged
print(mdh2.devixes.hello_world)  # pylint no-member

获得 no-member 的另一个可能原因是,缺少此 class 的 __init_() 方法的 self 参数:

错误:

class foo:
    def __init__(bar):
        self.bar = bar

右:

class foo:
    def __init__(self, bar):
        self.bar = bar

获取 no-member 警告的应用程序代码:

x = foo('bar')
print(x.bar) # <-- this line will be the reported error line