8.4 构造函数

对于一个新定义的类,我们之所以能够用类似于这样的语句:  stu=Student() 来声明一个新的对象,其实是调用了一个函数,这个函数叫做构造函数。 什么是构造函数呢,有什么作用呢?
构造函数的作用是给新创建的对象分配内存,初始化属性的值。对于分配内存,我们不用做什么,编译器已经做好了,我们要自己写的是后面的那个:初始化属性。事实上,你就算是一个这样的类,里面什么都没有:
class Chapter:pass
即使这个类貌似什么“内容”都没有 ,编译器也自动给你添加了一个没有参数的构造函数,这个自动添加的构造函数,使得你可以创建对象,例如这样:
c = Chapter()
虽然编译器会提供一个缺省构造函数,但我们通常需要手动写,__init__就是构造函数首先自动调用的函数(注意是"两个下划线+init+两个下划线"),我们在此章节把init和构造函数当做同义词:
class Chapter:
    def __init__(self):
        print("构造函数被调用")
        self.id = 1000
        self.code = ""
        self.name = ""
        self.content = ""
        self.parentCode = ""
c = Chapter()
c2 = Chapter()
c1 = Chapter()
c4 = Chapter()
print(c.id)
1. init函数没有返回值,但是构造函数把生成的对象返回
2. 如果没有写构造函数,编译器会提供一个无参数构造函数
3. init函数只能有一个
4. 通常把属性的定义直接写在构造函数里

这里也展示了python类通常的写法:在构造函数里定义属性。
代码执行的时候,“构造函数被调用”会打出4次,因为声明了4个Chapter对象,最终打印的1000是因为c的id值在构造函数中初始化为1000。

python类的构造函数只能有一个。构造函数的参数可以自己定义。
假设id值是任何对象都必须要有的值,它很重要。那么我们可以写一个这样的构造函数:
class Chapter:
    def __init__(self,id):
        print("构造函数被调用")
        self.id = id
        self.code = ""
        self.name = ""
        self.content = ""
        self.parentCode = ""
c = Chapter(8898)
print(c.id)
c2 = Chapter() #这行语法错误,因为没有无参数的构造函数
如果类里面没有任何构造函数,编译器会自动生成一个无参数的构造函数;如果类里面已经有构造函数,那么编译器不会生成无参数的构造函数。(你无我生成,你有我不管)。所以上面最后一行的代码错误了,因为已经没有无参数的构造函数,系统也不再提供。

这个构造函数需要一个参数,用来设置id值。那么新生成一个对象的时候,就可以这样调用了,Chapter对象c被创建,同时c的id属性赋值为8898,同时还可以生成一个新的对象c2,但什么属性都不设置,但这里会出语法错误,因为c2的构造函数参数数量不对。如果需要c2对象也生效,那么可以把id设置成缺省参数(函数参数默认值):
class Chapter:
    def __init__(self,id=1000):
        print("构造函数被调用")
        self.id = id
        self.code = ""
        self.name = ""
        self.content = ""
        self.parentCode = ""
c = Chapter(8898)
print(c.id)
c2 = Chapter() 
print(c2.id)

如果有两个以上的参数,并且有缺省值,那么看下面的例子:
class Chapter:
    def __init__(self,id=1000,code=124587):
        print("构造函数被调用")
        self.id = id
        self.code = code
        self.name = ""
        self.content = ""
        self.parentCode = ""
# 不指定任何参数,那么所有参数使用默认
c = Chapter()
print(c.id,c.code)
# 指定参数为code,那么id值使用默认的1000
c1=Chapter(code=1123)
print(c1.id,c1.code)
#不指定参数名,那么就从最左边参数开始匹配,1123就是参数id
c2=Chapter(1123)
print(c2.id,c2.code)
#不指定参数名,那么就从最左边参数开始匹配,1123就是参数id,886就是code
c3=Chapter(1123,886)
print(c3.id,c3.code)


练习题

  • 练习题
    1.Chapter类里面有一个构造函数,它打印了一句话"正在调用构造函数"。那么关于下面的代码,正确的是 (2分) [选择]
    A.
    B. 会有语法错误
    C. 打印"正在调用构造函数",但是chapter对象是None
    D. 打印"正在调用构造函数",同时chapter对象正确创建
    E. 以上说法都错误
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self):</div><div class='codeNewLine'>        <span class='pyFunction'>print</span>(<span class='string'>"正在调用构造函数"</span>)</div><div class='codeNewLine'></div><div class='codeNewLine'>chapter=Chapter()    </div></code>
    
    2. (2分) [判断]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    <span class='keyword'>def</span> __init__(self, id2):</div><div class='codeNewLine'>        self.id = id2</div><div class='codeNewLine'>        self.code = <span class='string'>""</span></div><div class='codeNewLine'>        self.name = <span class='string'>""</span></div><div class='codeNewLine'>        self.content = <span class='string'>""</span></div><div class='codeNewLine'>        self.parentCode = <span class='string'>""</span></div><div class='codeNewLine'>        <span class='keyword'>return</span> self</div><div class='codeNewLine'></div><div class='codeNewLine'></div></code>
    
    3. (2分) [判断]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    <span class='keyword'>def</span> init(self, id2):</div><div class='codeNewLine'>        self.id = id2</div><div class='codeNewLine'>        self.code = <span class='string'>""</span></div><div class='codeNewLine'>        self.name = <span class='string'>""</span></div><div class='codeNewLine'>        self.content = <span class='string'>""</span></div><div class='codeNewLine'>        self.parentCode = <span class='string'>""</span></div><div class='codeNewLine'>        </div><div class='codeNewLine'></div><div class='codeNewLine'></div></code>
    
    4.为Chapter类编写一个构造函数 (10分) [编程]
    接收一个参数的构造函数,用来设置code的值
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    id=<span class='string'>''</span></div><div class='codeNewLine'>    code=<span class='string'>''</span></div><div class='codeNewLine'>    name=<span class='string'>''</span></div><div class='codeNewLine'>    content=<span class='string'>''</span></div><div class='codeNewLine'>    parentCode=<span class='string'>''</span></div><div class='codeNewLine'></div></code>
    
    5.为Chapter类编写一个无参数的构造函数,把id值设置为1000 (10分) [编程]
    已知Chapter类的属性如代码所示
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    id=<span class='string'>''</span></div><div class='codeNewLine'>    code=<span class='string'>''</span></div><div class='codeNewLine'>    name=<span class='string'>''</span></div><div class='codeNewLine'>    content=<span class='string'>''</span></div><div class='codeNewLine'>    parentCode=<span class='string'>''</span></div></code>
    
    6.为Chapter类编写构造函数,这个构造函数接受五个参数,分别设置Chapter的五个属性 (10分) [编程]
    五个参数的顺序是id、code、name、content、parentCode,具体调用的时候是这样的:
    c=Chapter(2,"123","456","789","012")
    <code><div class='codeNewLine'><span class='keyword'>class</span> Chapter:</div><div class='codeNewLine'>    id=<span class='string'>''</span></div><div class='codeNewLine'>    code=<span class='string'>''</span></div><div class='codeNewLine'>    name=<span class='string'>''</span></div><div class='codeNewLine'>    content=<span class='string'>''</span></div><div class='codeNewLine'>    parentCode=<span class='string'>''</span></div></code>
    
  • 按要求调用构造函数
    1. (3分) [编程填空]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Student:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self,id,name=<span class='string'>""</span>,clazz=<span class='string'>"通用班级"</span>):</div><div class='codeNewLine'>        self.name=name</div><div class='codeNewLine'>        self.id=id</div><div class='codeNewLine'>        self.clazz=clazz</div><div class='codeNewLine'></div><div class='codeNewLine'><span class="comments"># 创建一个id值为2010的Student对象</span></div><div class='codeNewLine'>stu =         </div></code>
    
    2. (3分) [编程填空]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Student:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self,id,name=<span class='string'>""</span>,clazz=<span class='string'>"通用班级"</span>):</div><div class='codeNewLine'>        self.name=name</div><div class='codeNewLine'>        self.id=id</div><div class='codeNewLine'>        self.clazz=clazz</div><div class='codeNewLine'></div><div class='codeNewLine'><span class="comments"># 创建一个name为曹孟德,clazz为魏国,id为003的Student对象</span></div><div class='codeNewLine'>cc =         </div></code>
    
    3. (3分) [编程填空]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Student:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self,id,name=<span class='string'>""</span>,clazz=<span class='string'>"通用班级"</span>):</div><div class='codeNewLine'>        self.name=name</div><div class='codeNewLine'>        self.id=id</div><div class='codeNewLine'>        self.clazz=clazz</div><div class='codeNewLine'></div><div class='codeNewLine'><span class="comments"># 创建一个name为吕布,id为009的Student对象</span></div><div class='codeNewLine'>lb =         </div></code>
    
    4. (3分) [编程填空]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Student:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self,id,name=<span class='string'>""</span>,clazz=<span class='string'>"通用班级"</span>):</div><div class='codeNewLine'>        self.name=name</div><div class='codeNewLine'>        self.id=id</div><div class='codeNewLine'>        self.clazz=clazz</div><div class='codeNewLine'></div><div class='codeNewLine'><span class="comments"># 创建一个id为10007的Student对象</span></div><div class='codeNewLine'>soldier =         </div></code>
    
    5. (3分) [编程填空]
    <code><div class='codeNewLine'><span class='keyword'>class</span> Student:</div><div class='codeNewLine'>    <span class='keyword'>def</span> <span class='pyFunction'>__init__</span>(self,id,name=<span class='string'>""</span>,clazz=<span class='string'>"通用班级"</span>):</div><div class='codeNewLine'>        self.name=name</div><div class='codeNewLine'>        self.id=id</div><div class='codeNewLine'>        self.clazz=clazz</div><div class='codeNewLine'></div><div class='codeNewLine'><span class="comments"># 创建一个id为101,clazz为蜀国的Student对象</span></div><div class='codeNewLine'></div><div class='codeNewLine'>light =         </div><div class='codeNewLine'></div></code>