零基础 学 python开发 (Genius套餐A) 二十九
夜光序言:
恋人分手之际,还能把话说得平和得体的,肯定是已然变心的那一个。
正文:
5.3 对象初始化
5.3.1 目标
面向对象的程序设计中在对象实例化时往往要对实例做一些初始化工作,例如设置实例的属性的初始值,而这些工作时自动完成的,因此有默认的方法被调用,这个默认的方法就是构造函数,与之匹配的是析构函数。教学目标就是要掌握构造函数与析构函数的使用方法,为个人信息类进行初始化。
5.3.2 构造与析构方法
在 Python 中有一些内置的方法,这些方法命名都有比较特殊的地方(其方法名以 2 个下划线开始然后以 2 个下划线结束)。类中最常用的就是构造方法和析构方法。
构造方法__init__(self,....)在生成对象时调用,可以用来进行一些初始化操作,不需要显示去调用,系统会默认去执行。如果用户自己没有重新定义构造方法,系统就自动执行默认的构造方法。
析构方法__del__(self)在释放对象时调用,可以在里面进行一些释放资源的操作,不需要显示调用。
例 5-3-1: 构造方法函数与析构方法函数
class Person:
def __init__(self,n):
print("__init__",self,n)
self.name=n
def __del__(self):
print("__del__",self)
def show(self):
print(self,self.name)
p=Person("james")
p.show()
print(p)
结果:
__init__ <__main__.Person object at 0x00000015C4DA72E8> james
james <__main__.Person object at 0x00000015C4DA72E8>
<__main__.Person object at 0x00000015C4DA72E8>
__del__ <__main__.Person object at 0x00000015C4DA72E8>
在执行 p=Person()语句是建立一个 Person 类对象实例 p,于是自动调用__init__函数,并向这个函数传递两两个参数,一个是对象实例p传递给self,另外是"james"传递给n参数,于是在__init__中我们看到:
__init__ <__main__.Person object at 0x00000015C4DA72E8> james
其中看到 p 对象的内存地址是 0x00000015C4DA72E8。
接下来执行 p.show(),它是通过实例调用的,于是会把 p 实例传递给函数 show 的 self参数,于是在 show 中看到:
<__main__.Person object at 0x00000015C4DA72E8> james
这个 self 地址与 p 是一样的,是同一个对象。在执行 print(p)时也看到:
<__main__.Person object at 0x00000015C4DA72E8>
主程序中的 p 对象也时这个地址。
程序结束时自动销毁 p 对象,于是看到__del__函数执行:
__del__ <__main__.Person object at 0x00000015C4DA72E8>
5.3.3 对象的初始化
构造函数__init__是建立对象实例的自动调用函数,我们可以在这个函数中为实例对象初始化属性值。
例 5-3-2:对象初始化
class Person:
def __init__(self,n,g,a):
self.name=n
self.gender=g
self.age=a
def show(self):
print(self.name,self.gender,self.age)
p=Person("james","male",21)
p.show()
结果:
james male 21
这个程序在执行语句:
p=Person("james","male",21)
时就调用__init__函数,并传递 4 个参数给它,通过:
self.name=n
self.gender=g
self.age=a
语句这个实例就生成了 name,gender,age 属性,而且值由参数 n,g,a 确定。注意这几个属性是实例对象自己的属性,不是类 Person 的类属性。
在 Python 中只允许有一个__init__函数,我们通过对__init__函数参数的默认值方法可以实现重载,例如:
p=Person("james")
是错误的,因为__init__需要 4 个参数,而这里只提供 2 个参数。但是修改__init__的定义,使得它带默认参数就可以。
例 5-3-3:设置__init__中有默认参数
class Person:
def __init__(self,n="",g="male",a=0):
self.name=n
self.gender=g
self.age=a
def show(self):
print(self.name,self.gender,self.age)
a=Person("james")
b=Person("james","female")
c=Person("james","male",20)
a.show()
b.show()
c.show()
那么都是正确的,结果:
james male 0
james female 0
james male 20
5.3.4 理解实例方法
类的实例方法都至少带有一个参数,而且第一个参数通常命名为 self,在实例调用这个方法时会把实例自己传递给这个 self 参数。
例 5-3-4:实例方法的 self 参数
class Person:
def __init__(self,n="",g="male",a=0):
self.name=n
self.gender=g
self.age=a
def show(self):
print(self)
print(self.name,self.gender,self.age)
p=Person("james","male",20)
Person.show(p)
p.show()
结果:
<__main__.Person object at 0x000000C395A47710>
james male 20
<__main__.Person object at 0x000000C395A47710>
james male 20
其中 Person.show(p)的效果与 p.show()是一样的,只是 Person.show(p)时我们直接把实例 p 传递给 self 参数,而 p.show()调用时 p 自动递给 show 的 self,因此在 show 中都可以使用 self.name,self.gender,self.age 访问到 p 的属性。
5.3.5【案例】我的日期类
1、案例描述
编写一个日期类 MyDate,拥有年月日的数据。
2、案例分析
定义 MyDate__init__函数实现对象的初始化,在数据不合理时抛出异常。
3、案例代码
class MyDate:
__months=[0,31,28,31,30,31,30,31,31,30,31,30,31]
def __init__(self,y,m,d):
if y<0:
raise Exception("无效年份")
if m<1 or m>12:
raise Exception("无效月份")
if y%400==0 or y%4==0 and y%100!=0:
MyDate.__months[2]=29
else:
MyDate.__months[2]=28
if d<1 or d>MyDate.__months[m]:
raise Exception("无效日期")
self.year=y
self.month=m
self.day=d
def show(self,end='\n'):
print("%04d-%02d-%02d" %(self.year,self.month,self.day),end=end)
try:
d=MyDate(2019,5,13)
d.show()
except Exception as e:
print(e)
结果:
2019-05-13