Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python naming conventions for attributes and methods meant to be overwritten

I have some object oriented code in Python, where some classes are meant to be extended to provide the missing custom bits of code (a la Template Method pattern, but also with variables), that will only be used by the super class, not by the client code using them.

Are there any style conventions for such abstract (or dull, because their implementation in the super class would be either pass or raise a NonImplemented exception) methods and attributes?

I've been browsing the PEP-0008 and it only mentions about prepending an underscore to private members not intended to be used by subclasses.

like image 252
fortran Avatar asked Oct 18 '11 14:10

fortran


3 Answers

I usually use single underscore e.g. _myvar for protected (as in C++) methods/attributes, which can be used by derived classes and use double underscore e.g. __var when it should not be used by anybody else, and as double-underscore names at class definition level are mangled, so they can't be overridden in derived class e.g.

class A(object):
    def result1(self): # public method
        return self._calc1()

    def result2(self): # public method
        return self.__calc2()

    def _calc1(self): # protected method, can be overridden in derived class
        return 'a1'

    def __calc2(self): # private can't be overridden
        return 'a2'


class B(A):
    def _calc1(self):
        return 'b1'

    def __calc2(self):
        return 'b2'

a = A()
print a.result1(),a.result2()
b = B()
print b.result1(),b.result2()

Here it seems derived class B is overriding both _calc1 and __calc2 but __calc2 isn't overridden because its name is already mangled with class name and hence output is

a1 a2
b1 a2

instead of

a1 a2
b1 b2

but ultimately choose any convention and document it, also in above case it is not that base class can't override private, here is a way :)

class B(A):
    def _calc1(self):
        return 'b1'

    def _A__calc2(self):
        return 'b2'
like image 154
Anurag Uniyal Avatar answered Oct 23 '22 03:10

Anurag Uniyal


First of all i think that you are mistaken when you say that:

about prepending underscore to private members not intended to be used by subclasses.

Actually prepending a method/attribute by underscore is a python convention that mean that this method/attribute shouldn't be accessed outside the class (and its subclass) and I think you forgot to read about the double underscore that is used to make a method/attribute not possible to override.

class Foo(object):
    def __foo(self):
        print "foo"
    def main(self):
        self.__foo()


class Bar(Foo):
    def __foo(self):
        print "bar"


bar = Bar()
bar.main()
# This will print "foo" and not "bar".

There is another way of declaring stub method by the way which is using abc.ABCMeta and abc.abstractmethod.

like image 37
mouad Avatar answered Oct 23 '22 03:10

mouad


There isn't really a naming convention for these methods because they'll have the same name when they're overridden. Otherwise they wouldn't be overridden! I think having the method to be overridden do something trivial, and documenting it accordingly, is good enough:

class MyClass:

  def aMethod():
    '''Will be overridden in MyDerivedClass'''
    pass

Name mangling, which you mention in your question, is useful if you have a non-trivial method that will be overridden, but you still want to be able to access the base version. See the documentation for more info and an example.

like image 2
andronikus Avatar answered Oct 23 '22 03:10

andronikus