2014-10-08 220 views
0

我是OOP和Python的新手。几乎所有我知道的是自学成才的,所以如果你能提供一些链接供我阅读,我将不胜感激,因为我不知道我应该寻求什么确切的术语来澄清我的疑惑。类,隐藏属性和继承

这是我到目前为止的代码:

class Point(object): 
    x = 2 
    y = 3 

    def __init__(self, x, y): 
     self.x_a = x 
     self.y_b = y 

class RectPoint(Point): 

    def __init__(self, x, y): 
     self.x_1 = x 
     self.y_1 = y 
     self.dist = (x*x + y*y)**0.5 


class CircPoint(Point): 
    pass 

a = Point(3,4) 
b = CircPoint(3,4) 
c = RectPoint(3,4) 

print a.x  # 2 
print a.y  # 3 
print a.x_a # 3 
print a.y_b # 4 
print b.x  # 2 
print b.y  # 3 
print b.x_a # 3 
print b.y_b # 4 
print c.x  # 2 
print c.y  # 3 
print c.x_1 # 3 
print c.y_1 # 4 
print c.dist # 5.0 
print c.x_a # AttributeError 
print c.y_b # AttributeError 

为什么是CircPoint属性self.x_aself.y_b不适用于类RectPoint但可用?我将如何使它们可用?

此外,为什么self.xself.y可用于两个类别RectPointCircPoint

进一步阅读的链接也将赞赏(到位的解释)

+1

我让更有经验的用户详细解释;但用几句话来说,'a'显然有它应有的一切; 'b'是一个'CircPoint',它继承了'Point'的所有内容,并且什么也没加,所以它拥有'Point'所有的东西。另一方面,'c'是一个'RectPoint',一个从'Point'继承'x'和'y'的类,但是你定义了一个不同的'__init__'方法 - 所以这覆盖了原始类的方法。 – Roberto 2014-10-08 16:50:19

回答

4

您的RectPoint.__init__方法面具Point.__init__方法。由于Point.__init__未针对RectPoint实例执行,因此self.x_aself.y_b属性从不设置。这是因为Python首先搜索实例,然后搜索类,然后搜索属性的基类。在这里,方法真的是专用属性。在创建类的实例时,Python会在类上查找__init__方法,然后在基类上查找。

CircPoint没有实现自己__init__所以Point.__init__是发现和使用,self.x_aself.y_b集。

对于xy,请做特定的类别属性; Python使用相同的搜索顺序来查找它们;它们没有设置在实例上,最终在基类上找到;要么是因为您有Point实例或Point的子类,并且搜索了该子类的基类。

您可以明确呼叫从RectPoint.__init__的覆盖__init__方法:

class RectPoint(Point): 
    def __init__(self, x, y): 
     super(RectPoint, self).__init__(x, y) 
     self.x_1 = x 
     self.y_1 = y 
     self.dist = (x*x + y*y)**0.5 

super() function,您可以访问原来Point.__init__方法在这里,首先调用它。然后该方法设置self.x_aself.y_b属性,之后它将返回并且RectPoint.__init__方法将设置更多属性。

​​涵盖了一切细节。

+0

+1我只是加了一个(我在我自己的 - 被遗弃的答案中),虽然在某些语言中'RectPoint'会隐式地调用'Point'的构造函数,但Python不是这些语言之一。 – chepner 2014-10-08 16:54:30

+0

非常感谢。我还有一个问题,我不确定是否应该在这里插入它或将它作为一个单独的。对'__init__'方法中没有初始化的变量有没有实际应用?即从我的代码属性'x'和'y'? – 2014-10-08 17:07:43

+0

@ M.Klugerford:是的,您可以将它们用作默认值,或者在所有实例之间共享信息。将这与建筑论文相比较;您可以将基类,类和实例分层叠加,并通过图层查看数据,但*设置*实例上的属性将隐藏类上的属性(掩码)。但是你总是可以用'ClassObject.attribute_name = new_value'在类上直接设置属性*。 – 2014-10-08 17:30:56

1

RectPoint实例没有x_ay_b属性,是因为你的RectPoint.__init__方法不会定义他们,永远不会调用Point.__init__这将。

xy是类属性,可在定义它们的类,任何子类和这些类的实例上使用(除非通过在子类或实例上设置属性来重写)。 self.x首先在实例上寻找x,然后在该类及其父类上找不到它。

1

当你重写初始化在Python类,你仍然需要给你打电话从继承的类的初始化方法或者那些属性将不会提供给你的子类。你用超级方法做到这一点。在RectPoint,昌你的init方法像这样:

def __init__(self, *args, **kwargs): 
    self.x_1 = x 
    self.y_1 = y 
    self.dist = (x*x + y*y)**0.5 
    super(RectPoint,self).__init__(*args,**kwargs)