Python 类的学习_2
创建用于的计算的属性
property
属性 与 类属性和实例属性不同,差异点在于:
- 类属性和实例属性,返回所存储的值,是静态的
property
属性,在访问时将计算它的值并返回,是动态的,更类似于方法
python 中,可以通过@property
来把方法转换为属性,从而实现可以计算的属性,也把@property
称作装饰器@property
方法创建的属性,其值不可以修改,为只读属性
这种方法的优点是可以直接通过方法名来访问方法,且不需要添加小括号,语法如下:
@property
def methodName(self):
block # 方法体通常需要用 return 语句返回计算结果
示例如下:
class Rect:
def __init__(self, width, height): # 构造方法
self.width = width # 矩形的宽度
self.height = height # 矩形的高度
@property # 装饰器,将方法变为属性
def area(self): # 定义一个面积计算方法
return self.width*self.height # 计算矩形面积,并通过 return 返回计算结果
rect = Rect(800,600) # 创建类的实例
print('面积为:',rect.area) #输出面积
# 输出结果为 “ 面积为: 480000 ”
rect.area = 100 # 为属性重新赋值
print('面积为:',rect.area) #输出面积
# 以上重新赋值的语句运行将会报错
# 故 @property 创建的属性不可以更改(可以理解为 只读属性)
为属性添加安全保护机制
创建私有类型属性 __foo
可以一定程度上对属性进行保护,但此方法存在缺陷:设置为私有后,在类体外不能访问属性(不可修改,也不可读取)
而利用装饰器 @property
可以创建可以读取但是不能修改值的属性(只读属性),以下示例进行介绍:
class TVshow: # 电视节目类
def __init__(self,show):
self.__show = show
@property
def show(self): # 创建 show 方法
return self.__show # 返回私有属性
tvshow = TVshow('正在播放《战狼2》') # 创建类的实例
print('默认',tvshow.show) # 获取属性值
# 以下代码测试 修改TVshow.show 属性,实际测试时报错,表面属性不可修改
tvshow.show = '正在播放《红海行动》'
print('默认',tvshow.show)
运行后,输出结果如下:
默认: 正在播放《战狼2》
Traceback (most recent call last): #以下为报错信息
File "C:\Users\风转砂\Desktop\00 Python 学习\为属性添加保护机制.py", line 19, in <module>
tvshow.show = '正在播放《红海行动》'
AttributeError: can't set attribute
案例学习:
一家电影院,只能点播节目单上的节目,点播其它节目时报错提醒。
class TVshow: # 电视节目类
list_film = ['战狼2','红海行动','西游记','熊出没']
def __init__(self,show):
self.__show = show
@property
def show(self): # 创建 show 方法
return self.__show # 返回私有属性
@show.setter # 设置 setter 方法,上属性课可修改
def show(self, value):
if value in TVshow.list_film: # 判断值是否在列表中
self.__show = "您选择了《" + value + "》,稍后将播放" # 修改返回的值
else:
self.__show = "您点播的电影不存在"
tvshow = TVshow('战狼2') # 创建类的实例
print('正在播放:《',tvshow.show,'》') # 获取属性值
print('您可以从',TVshow.list_film,'中选择您要点播的电影')
tvshow.show = '红海行动'
print(tvshow.show) # 获取属性值
运行后,输出结果如下:
正在播放:《 战狼2》
您可以从 ['战狼2', '红海行动', '西游记', '熊出没'] 中选择您要点播的电影
您选择了《红海行动》,稍后将播放
继承的基本语法
class ClassName(baseClassList):
''' 类的帮助信息 '''
statement
baseClassList
要继承的基类,多个基类之间可以用逗号 “,”
间隔;如果不指定则默认继承object
实例演示,创建一个水果类作为基类,以及其派生类
class Fruit:
color = '绿色' # 类属性,水果的默认颜色
def harvest(self, color):
print('水果是:', color, '的!') # 输出形式参数 color
print('水果已经收获……')
print('水果原来是:', Fruit.color, '的!')
class Apple(Fruit): #定义一个子类 苹果
color = '红色'
def __init__(self):
print('我是苹果')
class Orange(Fruit): #定义一个子类 橘子
color = '橙色'
def __init__(self):
print('我是橘子')
apple = Apple() # 创建苹果类的实例
apple.harvest(apple.color) # 调用基类的 harvest() 方法
orange = Orange() # 创建橘子类的实例
orange.harvest(orange.color) # 调用基类的 harvest() 方法
运行结果
我是苹果
水果是: 红色 的!
水果已经收获……
水果原来是: 绿色 的!
我是橘子
水果是: 橙色 的!
水果已经收获……
水果原来是: 绿色 的!
方法重写
基类(父类)的属性和方法可以被派生类(子类)继承,但是父类中的某些方法并不能完全适用于子类中,此时就需要在子类进行重写父类的方法。
class Fruit:
color = '绿色' # 类属性,水果的默认颜色
def harvest(self, color):
print('水果是:', color, '的!') # 输出形式参数 color
print('水果已经收获……')
print('水果原来是:', Fruit.color, '的!')
class Apple(Fruit): #定义一个子类 苹果
color = '红色'
def __init__(self):
print('我是苹果')
def harvest(self, color):
print('苹果是:', color, '的!') # 输出形式参数 color
print('苹果已经收获……')
print('苹果原来是:', Fruit.color, '的!')
class Orange(Fruit): #定义一个子类 橘子
color = '橙色'
def __init__(self):
print('我是橘子')
def harvest(self, color):
print('橘子是:', color, '的!') # 输出形式参数 color
print('橘子已经收获……')
print('橘子原来是:', Fruit.color, '的!')
apple = Apple() # 创建苹果类的实例
apple.harvest(apple.color) # 调用基类的 harvest() 方法
orange = Orange() # 创建橘子类的实例
orange.harvest(orange.color) # 调用基类的 harvest() 方法
运行输出:
我是苹果
苹果是: 红色 的!
苹果已经收获……
苹果原来是: 绿色 的!
我是橘子
橘子是: 橙色 的!
橘子已经收获……
橘子原来是: 绿色 的!
子类中调用父类的 __init__()
- 如果在子类中不定义构造方法,则执行父类的构造方法;反之,如果在子类中定义了构造方法,则不执行父类的构造方法
class Fruit:
def __init__(self, color='绿色'):
Fruit.color = color #类属性
def harvest(self, color):
print('水果是:', color, '的!') # 输出形式参数 color
print('水果已经收获……')
print('水果原来是:', Fruit.color, '的!')
class Apple(Fruit): #定义一个子类 苹果
color = '红色'
def __init__(self): # 尝试对比 将子类的构造方法注释掉的运行结果
print('我是苹果')
def harvest(self, color):
print('苹果是:', color, '的!') # 输出形式参数 color
print('苹果已经收获……')
print('苹果原来是:', Fruit.color, '的!')
class Orange(Fruit): #定义一个子类 橘子
color = '橙色'
def __init__(self):
print('我是橘子')
def harvest(self, color):
print('橘子是:', color, '的!') # 输出形式参数 color
print('橘子已经收获……')
print('橘子原来是:', Fruit.color, '的!')
- 如果在子类中定义了构造方法并且需要调用父类的构造方法,可以通过
super().__init__()
的方法来实现
class Fruit:
def __init__(self, color='绿色'):
Fruit.color = color #类属性
def harvest(self, color):
print('水果是:', color, '的!') # 输出形式参数 color
print('水果已经收获……')
print('水果原来是:', Fruit.color, '的!')
class Apple(Fruit): #定义一个子类 苹果
color = '红色'
def __init__(self):
print('我是苹果')
super().__init__() # 调用父类的 构造方法
def harvest(self, color):
print('苹果是:', color, '的!') # 输出形式参数 color
print('苹果已经收获……')
print('苹果原来是:', Fruit.color, '的!')
class Orange(Fruit): #定义一个子类 苹果
color = '橙色'
def __init__(self):
print('我是橘子')
super().__init__() # 调用父类的 构造方法
def harvest(self, color):
print('橘子是:', color, '的!') # 输出形式参数 color
print('橘子已经收获……')
print('橘子原来是:', Fruit.color, '的!')
apple = Apple() # 创建苹果类的实例
apple.harvest(apple.color) # 调用基类的 harvest() 方法
orange = Orange() # 创建橘子类的实例
orange.harvest(orange.color) # 调用基类的 harvest() 方法