[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Style Q: Instance variables defined outside of __init__

On 3/19/18 1:04 PM, Irv Kalb wrote:
> I am building some classes for use in future curriculum.  I am using PyCharm for my development.  On the right hand edge of the PyCharm editor window, you get some little bars indicating warnings or errors in your code.  I like this feature and try to clean up as many of those as I can.  However, there is one warning that I am seeing often, and I'm not sure about how to handle it.  The warning I see is:
> "Instance attribute <instance variable name> defined outside of __init__ ..."
> The following is a simple example.  I am creating a card class that I am using to build card games with PyGame.
> class Card():
>      BACK_OF_CARD_IMAGE = pygame.image.load('images/backOfCard.png')
>      def __init__(self, window, name, suit, value):
>          self.window = window
>          self.suit = suit
>          self.cardName = name + ' of ' + suit
>          self.value = value
>          fileName = 'images/' + self.cardName + '.png'
>          self.image = pygame.image.load(fileName)
>          self.backOfCardImage = Card.BACK_OF_CARD_IMAGE
>          self.conceal()
>      def conceal(self):
>          self.faceUp = False
>      def reveal(self):
>          self.faceUp = True
>      <more code snipped>
> In this class, I get warnings on the single lines of the conceal and reveal methods.  Yes, the warnings are correct, the variable "self.faceUp" is not defined inside the __init__ method.  My __init__ method calls self.conceal which is a more logical place to initialize this variable.
> My question is, what is the Pythonic way to handle this?  In the research that I have done, I see split results.  Some people say that this type of thing is fine and these warnings should just be ignored.  While others say that all instance variables should be defined in the __init__ method.  I like that idea (and have done so in other languages), but if I define this variable there, what value should I give it?  Do I redundantly set it to the proper starting value (in case False), or do as others have suggested, set it to None (which seems a little odd for something that I will use as a Boolean).

I understand this tension: it's nice to assign only meaningful values, 
and to do it in as few places as possible.? But it's also nice to have 
all of your attributes in one place.? This is a by-product of Python 
having no declarations, only definitions (assignments).? So to mention 
the attributes initially, you have to choose a value for them.? If I 
were to add faceUp to __init__, I would assign False to it.
> I have many more similar cases.  For example, in many small game programs, at the end of my __init__ method, I call a "reset" method in the same class which initializes a bunch of instance variables for playing a game.  When the game is over, if the user wants to play again, I call the same reset method.  Very clean, and works very well, but all the instance variables defined in that reset method gets the same warning messages.

You didn't ask about this, so perhaps you already know it, but you can 
disable this particular Pylint warning, either line-by-line, 
file-by-file, or for the entire project.