避免Pylint警告E1101:具有动态属性

时间:2016-03-14 14:31:39

标签: python dynamic pylint

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

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

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

我可以禁用警告,但这样会很糟糕(因为我仍然希望在因错误拼写等原因而不存在该属性的情况下获得警告)。

是否有一种通用且合法的(Pylint-proof)方式可以动态地将成员添加到不会导致警告的对象中?

或者:我可以只为一个对象而不是行/块/文件禁用Pylint吗?

解释

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

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

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

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'背后的结构可能是任意的,非常复杂,我不想在类结构中重现它。

摆脱此警告的一种方法是创建/访问基于dict的树:

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

但这写起来比较难写,而且阅读起来也不好 - 我只会这样做才能让Pylint安静下来。

6 个答案:

答案 0 :(得分:4)

我可以通过向类添加__getattr__方法来避免此警告,当在对象上未找到属性时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

答案 1 :(得分:3)

对我来说,只需安装pylint-django即可解决问题:

pip install pylint-django

答案 2 :(得分:2)

This page描述了该错误,并提供了一种直接在代码中直接解决该错误的简便方法。 tl; dr

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

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

评论者提到可以使用# pylint: disable=no-member在文件顶部的一行上将其禁用。我还发现您可以基于this reddit entry使用# pylint: disable=E1101

答案 3 :(得分:1)

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

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

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

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

# pylint: disable=E1101

答案 4 :(得分:0)

试试看!我的问题解决了!

Pylint无法理解Django的动态字段。因此,我们需要教Django对Pylint来说是什么

*对于Windows 10中的vscode *

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

vscode中的Python,Django代码段,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"
   ],
}

答案 5 :(得分:0)

犹豫要不要添加到这个答案中,因为我更喜欢是否有一种明确的方法可以用 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