我是一个Python新手,试图理解继承方法背后的哲学/逻辑。问题最终涉及到为什么以及何时必须在子类中使用__init__
方法。示例:
从超类继承的子类似乎不需要有自己的构造函数(__init__
)方法。下面,狗继承哺乳动物的属性(名字、年龄)和方法(makenoise)。你甚至可以添加一个方法(do_a_trick
),看起来一切都是“应该”的。在
但是,如果我想像在Cats类中那样在子类中添加一个新的属性,我会得到一个错误消息“self”没有被定义。但我在定义dog类时使用了“self”。区别的本质是什么?
我想用__init__(self,name)
和{
class Mammals(object):
def __init__(self,name):
self.name = name
print("I am a new-born "+ self.name)
self.age = 0
def makenoise(self):
print(self.name + " says Hello")
class Dogs(Mammals):
def do_a_trick(self):
print(self.name + " can roll over")
class Cats(Mammals):
self.furry = "True" #results in error `self' is not defined
mymammal = Mammals("zebra") #output "I am a new-born zebra"
mymammal.makenoise() #output "zebra says hello"
print(mymmmal.age) #output 0
mydog = Dogs("family pet") #output "I am a new-born family pet"
mydog.makenoise() #output "family pet says hello"
print(mydog.age) # output 0
mydog.do_a_trick() #output "family pet can roll over"
Python类顶层的声明成为类属性。如果来自C++或java背景,这与声明静态成员变量类似。不能在该级别分配实例属性。在
变量
self
通常指的是类的一个特定实例,从中调用了方法。当使用语法inst.method()
进行方法调用时,函数的第一个参数是调用该方法的对象inst
。在您的例子中,通常按照约定,该参数在方法的函数体中命名为self
。您可以将self
看作是方法体中的一个有效标识符。您的赋值self.furry = True
不在方法中发生,因此self没有在那里定义。在你基本上有两个选择来实现你想要的。第一种方法是正确地将
furry
定义为cat类的属性:也可以在cat构造函数中设置实例变量
^{pr2}$furry
的值:如果您正在接触Python,我强烈建议您阅读Python文档的以下两部分:
Python classes
Python data model special methods(更高级)
但是,您可以执行以下操作:
或者
^{pr2}$在你的超类哺乳动物中,有一个
__init__
函数,它接受你选择的一个参数来调用self
。当您在__init__
函数体中时,此参数在作用域内-它是与任何局部变量一样的局部变量,并且在其包含函数终止后无法引用它。 在Dog类上定义的函数do_a_trick
,也接受一个名为self
的参数,并且它也是该函数的本地函数。 这些变量的特殊之处并不是它们的名称(您可以随意调用它们),而是事实上,作为python中实例方法的第一个参数,它们获得了对调用它们的对象的引用作为它们的值。(把最后一句话再读几遍,这是理解这一点的关键,你可能第一次就不会明白了。)现在,在
Cat
中,有一行代码根本不在函数中。此时,范围内没有任何内容,包括self
,这就是它失败的原因。如果要在Cat
中定义一个函数,该函数接受一个名为self
的参数,则可以引用该参数。如果该参数碰巧是Cat
上实例方法的第一个参数,那么它将具有调用它的Cat
实例的值。否则,它就会有任何被传给它的东西。在*你的选择很明智!在
相关问题 更多 >
编程相关推荐