要覆盖的属性和方法的Python命名约定

时间:2011-10-18 14:53:56

标签: python naming-conventions template-method-pattern

我在Python中有一些面向对象的代码,其中一些类要扩展以提供缺少的自定义代码位(la Template Method pattern,但也包含变量),这些只会由超类,而不是使用它们的客户端代码。

这样的抽象是否存在任何样式约定(或者是沉闷的,因为它们在超类中的实现可能是pass或引发NonImplemented异常)方法和属性?

我一直在浏览PEP-0008,并且只提到将下划线添加到不打算由子类使用的私有成员。

3 个答案:

答案 0 :(得分:12)

我通常使用单下划线,例如_myvar用于受保护(如在C ++中)的方法/属性,可由派生类使用并使用双下划线,例如__var当它不应被其他人使用时,并且在类定义级别的双下划线名称为mangled,因此它们不能在派生类中被覆盖,例如。

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()

这里似乎派生类B覆盖了_calc1__calc2__calc2没有被覆盖,因为它的名称已经被类名破坏了,因此输出是

a1 a2
b1 a2

而不是

a1 a2
b1 b2

但最终选择任何约定并记录它,在上面的情况下它不是基类不能覆盖私有,这里是一种方式:)

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

    def _A__calc2(self):
        return 'b2'

答案 1 :(得分:9)

首先,我认为当你这么说时你错了:

  

关于将下划线添加到不打算由子类使用的私有成员。

实际上通过下划线预先设置方法/属性是一个python约定,意味着不应该在类(及其子类)之外访问此方法/属性,我想你忘了阅读用于的双下划线使方法/属性无法覆盖。

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".

通过使用abc.ABCMetaabc.abstractmethod的方式,还有另一种声明存根方法的方法。

答案 2 :(得分:2)

这些方法实际上没有命名约定,因为它们在被覆盖时具有相同的名称。否则他们不会被覆盖!我认为让覆盖的方法做一些微不足道的事情,并相应地记录它,就足够了:

class MyClass:

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

您在问题中提到的名称修改,如果您有一个非重要的方法将被覆盖,但您仍希望能够访问基本版本,那么它很有用。有关详情和示例,请参阅the documentation