Instance error in OOP design: Instance of Card has No points member

Question:

I’m reading this book called Master Object Oriented programming Python by Steven Lott.

I came across this code:

class Card:
    def  __init__( self, rank, suit ):
        self.suit= suit
        self.rank= rank
        self.hard, self.soft = self._points()
class NumberCard( Card ):
    def _points( self ):
        return int(self.rank), int(self.rank)
class AceCard( Card ):
    def _points( self ):
        return 1, 11
class FaceCard( Card ):
    def _points( self ):
        return 10, 10

I’m not able to understand how can self._points() in Card be legal expression.

I run the code in compiler too it stats the following error
Instance of Card has No points member

Error Image
Full Code I have kept it as gist here

Asked By: vidit02100

||

Answers:

From your error: it is just a pylint issue, if you do not do something like c = Card(1, 2), it will be ok.

The code in fact is correct.

It intends you will call it like n = NumberCard(1, 2), then __init__ will be used by its subclass, and subclass has the function _points.

In fact, for other language, usually we need to define a _points function in parent class. Then, subclass could override the function in parent class. But python is not so strict, so you could do without define _points function in parent class, but then you will just able to new a object for its subclass not parent class.

To sum all, what you need to google is function override of OOP.

Answered By: atline

The __init__() function of the base class, Card, tries to access the member function _points(), when it has none. That its subclasses all have such a member function doesn’t help the base class from getting this member function. You simply can’t instantiate Card directly because it really is an abstract class.

You should use the abc module to declare Card as an abstract class, and Card._points as an abstract method, and instantiate child classes instead:

from abc import ABC, abstractmethod

class Card(ABC):
    def  __init__( self, rank, suit ):
        self.suit= suit
        self.rank= rank
        self.hard, self.soft = self._points()
    @abstractmethod
    def _points(self):
        return None, None
class NumberCard( Card ):
    def _points( self ):
        return int(self.rank), int(self.rank)
class AceCard( Card ):
    def _points( self ):
        return 1, 11
class FaceCard( Card ):
    def _points( self ):
        return 10, 10

a=AceCard(1,2)
print(a.hard, a.soft)
Answered By: blhsing
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.