Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell pylint that sub-classes of a composed class have access to the parent members?

Tags:

python

pylint

I have this test script:

class HugeGetterClass:

    def __init__(self):
        pass

    def getMe(self, key):
        return self._cache.get(key)

class HugeSetterClass:

    def __init__(self):
        pass

    def setMe(self, key, value):
        self._cache[key] = value

class ContainerClass(HugeGetterClass, HugeSetterClass):

    def __init__(self):
        HugeGetterClass.__init__(self)
        HugeSetterClass.__init__(self)
        self._cache = { }

a = ContainerClass()

a.setMe('a', 'Hello')
print a.getMe('a')

This is maybe not very good style, but works: HugeGetterClass and HugeSetterClass have access to self._cache indirectly, by being part of ContainerClass. But running pylint gives:

» pylint -E composing.py
No config file found, using default configuration
************* Module composing
E:  7,15:HugeGetterClass.getMe: Instance of 'HugeGetterClass' has no '_cache' member
E: 15,8:HugeSetterClass.setMe: Instance of 'HugeSetterClass' has no '_cache' member

Which is understandable, but it annoys me. The classes have no _cache member, but have anyway access to it. I have several questions:

  1. Is it possible to trick pylint on this, without disabling the error class completely, which is too heavy handed?
  2. Is this coding style pythonic?. If not, what would the alternative way to code a huge class? What I am doing is separating functionality in sub-classes (in order to avoid having huge source files which become unmanageable), even though those subclasses are meant to be always used together.
like image 385
blueFast Avatar asked Jan 07 '14 08:01

blueFast


1 Answers

The problem is that you cannot instantiate and use properly HugeGetterClass and HugeSetterClass on their own because of the missing _cache attribute. This is why I suggested you to replace your pass statements with self._cache = {}. It's not just about patching the pylint error, it is also about making your code more pythonic and modulable.

Anyway, if you don't want these classes to be instantiable, Python has a tool for that : ABC (Abstract Base Classes). This allows you to define base classes with abstract methods and properties.

Here's a simple example of what you're trying to achieve using an abc:

from abc import ABCMeta, abstractproperty

class HugeGetterClass:
    __metaclass__ = ABCMeta

    def get_me(self, key):
        return self.cache_access.get(key)

    @abstractproperty
    def cache_access(self):
        return {}

class ContainerClass(HugeGetterClass):

    def __init__(self):
        HugeGetterClass.__init__(self)
        self._cache = {"a":"Hello"}

    @property
    def cache_access(self):
        return self._cache

a = ContainerClass()
print a.get_me('a')
like image 131
Vincent Avatar answered Oct 31 '22 21:10

Vincent