3

Suppose that I have the following python base class:

class BaseClass(object):
    def a():
        """This method uses method b(), defined in the inheriting class"""

And also a class that inherites BaseClass:

class UsedByUser(BaseClass):
    def b():
        """b() is defined here, yet is used by the base class"""

My user would only create instances of class UsedByUser. Typical use would be:

if __name__ == '__main__':
    # initialize the class used by the user        
    usedByUser = UsedByUser()

    # invoke method a()
    usedByUser.a()

My questions is, is the above use problematic? is this a valid approach, or must I also define method b() in BaseClass and then override it in UsedByUser?

2
  • 2
    Stop thinking in Java... Almost everything you wrote is not pythonic Commented Aug 17, 2011 at 0:06
  • What Franklin said. Also, read the Python Style Guide. Commented Aug 17, 2011 at 0:17

4 Answers 4

7

I would define the b method in the BaseClass too:

class BaseClass(object):
    def b(self):
        raise NotImplementedError('b must be implemented by a subclass')

Remember: explicit is better than implicit and given that the method a needs the method b anyways, better raise a meaningful exception rather than a general AttributeError.

It is worth to point out that this is absolutely NOT needed from a syntactic point of view, but it adds clarity to the code and enforces the subclass to provide an implementation.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you for this detailed answer. Suppose that I implement B() also in the BaseClass() (meaning, provide a real implementation -- not an exception). Will the implementation of B() in the UsedByUser() class always override the definition of B() in the BaseClass()?
If you instantiate the UsedByUser class, yes!
0
  • The use is correct. Classes can define methods that can be overriden from subclasses, but those can also define new methods. Defining every method needed for subclasses in the superclass seems a bit senseless. (Since object then would also need to have every function defined ?)

    A subclass often has a different bahviour to another subclass.

    class Vehicle(object): def Refuel(self): # ...

    class Plane(Vehicle): def Fly(self): # ...

    class Car(Vehicle): def Drive(self): # ...

Edit: I misread the code.
If only you create a subclass of it and make sure subclasses have B(), then it's theoratically ok, but bad style. It makes more sense and is safer to give the superclass attributes and methods that are used by the superclass. -> Define B()

2 Comments

But in OP's example, BaseClass's method needs one of SubClass's method. In object, there is no need to define every method because object doesn't need them.
Lol, I'm sorry. You're right. I didn't read the comment in A() good enough.
0

Sounds like you want A to call a protected member function of UsedByUser that can't go in the abstract BaseClass). Try prefixing the protected function with an underscore (although note this is just a convention used by Python and not strictly checked, as mentioned here).

class BaseClass(object):
    def A(self):
        print "Grettings from A"
        self._B()
    def _B(self):
        raise NotImplementedError('b must be implemented by a subclass')

class UsedByUser(BaseClass):
    def _B(self):
        """ prefix with underscore is a python convention for a protected member function """
        print "B rocks!"

if ( __name__=='__main__' ):
    usedByUser = UsedByUser()
    usedByUser.A()

Find more on this convention in the PEP guidelines.

Edit:

As GaretJax suggested, I added a BaseClass _B method for clarity. Nice tip!

1 Comment

The OP did not mention that method b needs any protection.
-1

BaseClass can't assume that a UsedByUser object exists, so it can't use a B() method from it. You probably want to define a B() in BaseClass, that either does nothing (if it's sensible to attempt B() with something that doesn't support it) or raises an exception (if it's not sensible to attempt B()).

If you tell us what A and B are in your use case, we may be able to advise you better.

2 Comments

-1 Such a construction is legal and possible, and abc exists to facilitate such usage.
"BaseClass can't assume that a UsedByUser object exists". That is true. But it does not make that assumption (only the more general one that b will exist), so where is the problem? This is just the Template Method design pattern.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.