1. 特殊方法__init__
1.1 为何使用特殊方法
- 我们在定义类的时候,往往需要定义一些公共属性和方法,也就是必填项,但是这些公共属性和方法又需要传入不同的值或者参数。这时候可以用到特殊方法来定义这一些属性或者方法,能够达到的效果就是,创建对象的时候必须填入参数,否则会报错,并且创建的时候填入什么参数,示例对象就是什么参数
请看下方示例:
class Player_profile():
def __init__(self,nick_name,job):
self.nick_name = nick_name
self.job = job
def illustrate(self):
print(f'该玩家昵称{self.nick_name},职业为{self.job}')
Player1 = Player_profile('大西瓜','战士')
Player1.illustrate()
Player2 = Player_profile('小绵羊','魔法师')
Player2.illustrate()
Plyaer3 = Player_profile()
Player3.illustrate()
该代码执行结果如下:
该玩家昵称大西瓜,职业为战士
该玩家昵称小绵羊,职业为魔法师
Traceback (most recent call last):
File “C:/Users/Robin Ding/PycharmProjects/pythonProject1/temp.py”, line 13, in
Plyaer3 = Player_profile()
TypeError: init() missing 2 required positional arguments: ‘nick_name’ and ‘job’
Process finished with exit code 1
由此可见,在玩家档案这个类中,我们通过__init__的特殊方法,将nick_name 和 job这两个变量设置为了必填属性,如果向Player3这样创建了对象,却没有传入必要的实参,就会报错,这样我们就知道有必填项没有填入。
1.2 特殊方法使用注意事项
- 特殊方法不需要我们自己调用,自己调用会造成方法多执行一次,所以不要尝试调用特殊方法
- 特殊方法在对象创建后立即执行,而类代码中的代码块只执行一次
2. 封装
2.1 封装的简介
- 封装是⾯向对象的三⼤特性之⼀
- 封装是指隐藏对象中⼀些不希望被外部所访问到的属性或⽅法
2.2 为什么要使用封装
- 如果不使用封装,我们可以直接用对象.属性的方法修改属性的值,这种方法非常不安全
- 封装可以增强数据安全性,需要修改的时候允许修改,不需要修改的时候就不允许修改。
2.3 封装的使用
- 封装的原理是在初始化属性的时候,将属性赋值给另外一个变量。
比如以下面示例:
class Player_profile():
def __init__(self,nick_name,job):
self.nick_name = nick_name
self.hidden_job = job
def illustrate(self):
print(f'该玩家昵称{self.nick_name},职业为{self.job}')
Player1 = Player_profile('大西瓜','战士')
print(Player1.nick_name)
Player2 = Player_profile('小绵羊','魔法师')
print(Player2.job)
代码执行结果如下:
大西瓜
Traceback (most recent call last):
File “C:/Users/Robin Ding/PycharmProjects/pythonProject1/temp.py”, line 12, in
print(Player2.job)
AttributeError: ‘Player_profile’ object has no attribute ‘job’
Process finished with exit code 1
由此可见,我们将job赋值给了hidden_job这个变量,这样job这个属性就没有办法通过外部访问,相对应的是,nick_name没有进行封装操作,就可以仍然访问到结果“大西瓜”。
注意事项:
- 一般情况下,可以为对象的属性使⽤双下划线开头 __xxx。双下划线开头的属性,是对象 的隐藏属性,隐藏属性只能在类的,
- 其实隐藏属性只不过是Python⾃动为属性改了⼀个名字 --> _类名__属性 名 例如 __name -> _Person__name内部访问,⽆法通过对象访问
- 这种⽅式实际上依然可以在外部访问,所以这种⽅式我们⼀般不⽤。⼀般我 们会将⼀些私有属性以_开头
- ⼀般情况下,使⽤_开头的属性都是私有属性,没有特殊情况下不要修改私有属性
2.4 封装中的getter()和 setter()
- 虽然对属性进行了封装,但是我们希望使用者能够通过我们指定的方法对对象进行访问或者修改,这个时候我们就可以定义getter() 和 setter()的方法
下面请看示例:
class Player_profile():
def __init__(self,nick_name,job):
self._nick_name = nick_name
self._job = job
def illustrate(self):
print(f'该玩家昵称{self.nick_name},职业为{self.job}')
def set_nick_name(self,nick_name):
self._nick_name = nick_name
def get_nick_name(self):
print(self._nick_name)
return
Player1 = Player_profile('大西瓜','战士')
Player1.set_nick_name('我是MT')
Player1.get_nick_name()
代码执行结果如下:
我是MT
由此可见我们通过setter()的方法可以已经封装的对象进行修改,getter()的方法对封装的对象进行了访问。 虽然这样修改和访问数据更复杂,但是更安全。 getter()和setter()⽅法可以很好控制属性是否是只读的
3. property装饰器和setter装饰器
- 我们可以使⽤@property装饰器来创建只读属性,@property装饰器会将⽅ 法转换为相同名称的只读属性,可以与所定义的属性配合使⽤,这样可以防⽌ 属性被修改
- 属性名.setter的装饰器可以用来创建和属性名相同的修改方法,省略()
请看以下示例:
class Player_profile():
def __init__(self,nick_name,job):
self._nick_name = nick_name
self._job = job
@property
def nick_name(self):
return self._nick_name
@nick_name.setter
def nick_name(self,nick_name):
self._nick_name = nick_name
Player1 = Player_profile('大西瓜','战士')
print(Player1.nick_name)
Player1.nick_name = '我是MT'
print(Player1.nick_name)
运行结果如下:
大西瓜
我是MT
可以看到 property和setter装饰器,都是方法,但是都不需要在方法名后加括号。property装饰器就创建了只读属性,setter装饰器就将方法转变为了可修改的属性。