Search code examples
pythonattributesclass-methodpylint

Protected attributes in classmethod


Python conventions suggest to proceed the names of protected attributes with an underscore. As far as I understand protected attributes should only be used within a given class and its subclasses. Could you then provide me with some intuition on why pylint returns protected-access warnings when I try to use protected attributes inside alternative initializers, e.g.

class Test(object):

    def __init__(self, name):
        self.name = name
        self._count = 0
        self._bound = 1  # max value

    @classmethod
    def specific_state(cls, name, bound):
        test = cls(name)
        test._bound = bound

I do understand that in this specific case (presented in the example above) I work on an instance of an object but it is still inside the class definition thus it seems ok from my point of view. Is pylint a bit too rigorous in this matter or do I misunderstand sth?


Solution

  • From pylint.checkers.classes.ClassChecker in the _check_protected_attribute_access method:

    '''Given an attribute access node (set or get), check if attribute
    access is legitimate. Call _check_first_attr with node before calling
    this method. Valid cases are:
    * self._attr in a method or cls._attr in a classmethod. Checked by
    _check_first_attr.
    * Klass._attr inside "Klass" class.
    * Klass2._attr inside "Klass" class when Klass2 is a base class of
        Klass.
    '''
    

    You can see that your case in not among the mentioned cases. So one could assume that the protected-access warning is legit.

    But:

    1. from pylints code itself the exact same case occurred. (e.g. exceptions.py:338):

      # pylint: disable=protected-access
      exc = exc._proxied
      

      So basically they disabled their on checker in that case.

    2. in c++ the following code is valid:

              class X
      {
      private:
          int a;
      protected:
          int b;
      public:
          static void staticMethod(X& x)
          {
              x.a = 1;
              x.b = 1;
          }
      };
      

      So accessing protected/private members in static methods is valid.

    I would say that pylint is overly sensitiv in this case. You could use a comment to disable the checker there. The reason that the warning is produced is probably that it is kind of hard for a static checker to implement a more complex behavior.