Python有默认的类构造函数吗?

4
我在思考Python3.6是否有类的默认构造函数。所以我写了一些代码来测试这个问题。但是,当我开始测试时,我留下了比之前更多的疑问。
我试图理解为什么我的程序第11行上的myCat被成功构建,然而我无法解释为什么程序的第27行需要知道它本身。
如果您可以帮忙,请查看此Python代码和输出...它有意义吗? 我创建了两个文件animal.py和an_test_program.py。
#!/usr/bin/env python3
#animal.py file  ==============================
class animal:
    name = ""
    height = 0
    weight = 0

    def __init__( self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight

    def printvars(self):
        print(self.name)
        print(self.height)
        print(self.weight)


#!/usr/bin/env python3
#an_animal_program.py ==============================
import animal as an

#Instantiate a variable of type animal using the special constructor of the class
myDog = an.animal('Capitan', 30, 70)
print('myDog\'s name is ' + myDog.name)
myDog.printvars()

#now play around with Python and discover some things...
#Instantiate a variable of type animal without using the special constructor
myCat = an.animal
print('myCat\'s name is ' + myCat.name)
print('myCat\'s height is ' + "%d" % (myCat.height))
print('myCat\'s weight is ' + "%d" % (myCat.weight))

#notice everything in myCat is empty or zero
#thats because myCat is not initialized with data
#none-the-less myCat is a viable object, otherwise Python would puke out myCat

myCat.name = 'Backstreet'
print('myCat\'s name is ' + myCat.name) # now myCat.name has data in it
    #Ouch... this next line produces an error:
    #myCat.printvars()
    #"an_test_program.py", line 21, in <module>
    #    myCat.printvars()
    #TypeError: printvars() missing 1 required positional argument: 'self'
myCat.printvars(myCat)   #ok, I'm rolling with it, but this is wierd !!!

#oh well, enough of the wierdness, see if the myCat var can be
#reinstantiated with an animal class that is correctly constructed
myCat = an.animal('Backstreet', 7, 5)
myCat.printvars()

#I'm trying to understand why myCat constructed ok on line 11
#But I can't explain why line 27 demanded to know itself
#the output is:
# RESTART: an_test_program.py 
#myDog's name is Capitan
#Capitan
#30
#70
#myCat's name is 
#myCat's height is 0
#myCat's weight is 0
#myCat's name is Backstreet
#Backstreet
#0
#0
#Backstreet
#7
#5

严谨地说,.__init__ 是实例的初始化器。实例构造函数被称为 .__new__。类从 object 继承 .__new__ 方法,通常无需覆盖它,但这是可以做到的。 - PM 2Ring
谢谢,我懂了。 - MrEmanLOL
1
你可能会发现这篇文章很有帮助:《有关Python名称和值的事实与神话》(http://nedbatchelder.com/text/names.html),它是由SO老手Ned Batchelder撰写的。另外还可以看一下《其他语言有“变量”,Python有“名称”》(http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables),其中附有可爱的图示,对此进行了简短的总结。 - PM 2Ring
1个回答

3

你没有构造任何东西。你只是创建了对animal类的另一个引用。

那个类已经有了nameheightweight属性,所以print()语句可以访问这些属性并打印出值。你也可以给这些类属性赋予不同的值,所以myCat.name = 'Backstreet'也可以工作。但是这个更改也会通过animal.name可见。

myCat.printvars是你定义的方法的引用,但它是未绑定的;这里没有实例,只有一个类对象,所以没有什么可以设置self的。在这种情况下,你可以显式地传递一个值给self,这就是为什么myCat.printvars(myCat)可以工作;你明确地将self设置为myCat,并且再次,这个类对象具有此操作所需的属性。

你仍然可以从myCat引用中创建实际的实例:

an_actual_cat = myCat('Felix', 10, 15)

请记住,Python 中的所有名称都是引用;您可以通过赋值创建更多对象引用:

foo = an.animal
bar = an.animal

现在,foobar也指向animal类。

太好了!谢谢。我没有意识到我引用了类对象并引用了它的内部函数。现在代码真正的作用非常清晰了。 - MrEmanLOL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接