我是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
为什么属性self.x_a
和self.y_b
不适用于课程RectPoint
但可用于CircPoint
?我怎么能让它们可用?
此外,为什么self.x
和self.y
可用于RectPoint
和CircPoint
这两个类?
进一步阅读的链接也将受到赞赏(代替解释)
答案 0 :(得分:4)
您的RectPoint.__init__
方法屏蔽 Point.__init__
方法。由于Point.__init__
个实例未执行RectPoint
,因此永远不会设置self.x_a
和self.y_b
属性。这是因为Python首先搜索实例,然后搜索类,然后搜索属性的基类。这里的方法确实是专门的属性。在创建类的实例时,Python会在类上查找__init__
方法,然后在基类上查找。
CircPoint
未实现自己的__init__
,因此找到并使用Point.__init__
,self.x_a
和self.y_b
集。
您为x
和y
提供了具体的 class 属性; Python使用相同的搜索顺序查找这些内容;它们没有在实例上设置,最终会在Point
基类上找到;要么是因为你有一个Point
实例,要么是Point
的子类,并且搜索了该子类的基类。
您可以显式从__init__
调用已覆盖的RectPoint.__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_a
和self.y_b
属性,之后它将返回,RectPoint.__init__
方法将设置更多属性。
Class chapter of the Python tutorial详细介绍了所有这些内容。
答案 1 :(得分:1)
RectPoint
个实例没有x_a
和y_b
个属性,因为您的RectPoint.__init__
方法从不定义它们,也从不调用Point.__init__
。
x
和y
是类属性,可在定义它们的类,任何子类和这些类的实例上使用(除非通过在子类或实例上设置属性来覆盖) 。 self.x
首先在实例上查找x
,然后在类及其父类中找不到它。
答案 2 :(得分:1)
当你在Python类中覆盖 init 时,你仍然需要调用你继承的类的 init 方法,否则这些属性将无法用于你的子类。您可以使用super方法执行此操作。在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)