2013-12-22 36 views
2

我有以下两类:功能没有被覆盖的子类

class Shape(object): 
    def __init__(self, start_point, *args): 
     self.vertices = [] 
     self.__make_vertices(start_point, *args) 

    def __make_vertices(self, start_point, *args): 
     print "Not Implemented: __make_vertices" 

    def __getitem__(self, *args): 
     return self.vertices.__getitem__(*args) 

class Cube(Shape): 
    def __init__(self, start_point, side_length): 
     Shape.__init__(self, start_point, side_length) 

    def __make_vertices(self, start_point, side_length): 
     append = self.vertices.append 
     start_point = Vector(*(start_point)) 
     i, j, k = side_length*I, side_length*J, side_length*K 
     append(start_point) 
     append(self.vertices[-1] - k) 
     append(self.vertices[-1] - j) 
     append(self.vertices[-1] + k) 
     append(self.vertices[-1] - i) 
     append(self.vertices[-1] - k) 
     append(self.vertices[-1] + j) 
     append(self.vertices[-1] + k) 
     print self.vertices 

当我提出一个新的Cube,我期望我在多维数据集类中定义的__make_vertices函数将被调用,而是我一直获取Shape__make_vertices函数打印出的消息。我误解了什么?

+0

http://php.net/manual/en/language.oop5.overloading.php – 2013-12-22 18:00:25

+0

@Allendar:这是Python,而不是PHP。 – BrenBarn

+0

对不起,我在笔记本电脑后面睡着了,嘿嘿,我的坏:) – 2013-12-22 18:04:49

回答

7

你缺少name mangling

形式__spam的任何标识符(至少两个前导下划线,至多一个结尾下划线)的文本上与_classname__spam,classname即当前的类名前导下划线替​​换(s)剥离。只要它在类的定义内发生,就不会考虑标识符的语法位置。

换句话说,你应该只使用属性/方法的名称以两个下划线开始的时候你特别希望子类覆盖它们,而是为他们提供自己的私人版本。这很少见,所以通常你不需要使用双下划线名称。

+1

通常,人们将两个主要下划线与* private *成员关联,并且一个带有* protected *(或其他内部成员)的主要下划线关联。所以如果你想允许重写,最多只能使用一个下划线。 – poke

+0

@poke:这是真的,但人们认为他们想要私有/受保护属性的很多原因在Python中并不真正有效。使用单个下划线不是访问控制机制,它是关于哪些方法可以作为面向外API的一部分的文档约定。即使使用双下划线方法也不会阻止访问,它只是更改名称。所以我避开使用这些术语,因为他们可能会混淆人们尝试使用语法来获取在Python中并不存在的访问隐藏功能。 – BrenBarn

+0

做私有方法的一种更好的方法是不要在类中定义方法!相反,在同一个包中传递一个函数来执行该操作,即'def _private_foo(obj,arg1,arg2,...)'。 – wheaties