我的博客第十二篇
面向对象(中)
1.特殊方法
。init 魔法方法
。初始化属性
。创建实例的时候就会调用这个方法
。特殊方法不需要我们调用,它会在特定时候自动调用
举例:
class Person:
def speak(self):
print('大家好,我是%s' % self.name)
p1 = Person()
p1.name = '葫芦娃'
p2 = Person()
p2.name = '钢铁侠'
p3 = Person()
p1.speak()
p2.speak()
p3.speak()
#结果会报错 因为p3没有添加属性,每个都需要添加会很发麻,所以需要用到特殊方法。
#目前,name对于我们的程序是必须的
#并且name又是不同的
#手动添加name属性容易忘记
#__名称__ 这种方式的方法就是特殊方法,魔法方法
#没创建一个实例对象,那么解释器就会调用一次init魔法方法
class Person:
def __init__(self):
print('hello!!!')
def speak(self):
print('大家好,我是%s' % self.name)
p1 = Person()
# p1.name = '葫芦娃'
p2 = Person()
#p2.name = '钢铁侠'
p3 = Person()
# p1.speak()
# p2.speak()
# p3.speak()
#解决一下三个问题:
#1.目前,name对于我们的程序是必须的
#2.并且name又是不同的
#3.手动添加name属性容易忘记
class Person:
#类属性
#name = '葫芦娃'
def __init__(self,name):
#实例属性
self.name = name
def speak(self):
print('大家好,我是%s' % self.name)
p1 = Person('刘亦菲')
#p1.name = '葫芦娃'
p2 = Person('林青霞')
#p2.name = '钢铁侠'
p3 = Person('周慧敏')
p1.speak()
p2.speak()
p3.speak()
class LogicStudent:
def __init__(self, stu_name, stu_age): # __init__方法 形参传递
self.name = stu_name
self.age = stu_age
# 1.__init__方法是否可以有返回值:可以,但是必须为None
# return '111' # __init__() should return None, not 'str'
def stu_infor(self):
# print(self.name, self.age)
self.gender = "female"
self.addr = "ChangSha"
N_stu = LogicStudent("N", 18) # __init__方法 实参传递
# 2.在__init__()方法中声明的属性,可否在类的外部通过对象访问?可以
# print(N_stu.name)
# print(N_stu.age)
# 3.在自定义的方法当中定义对象的属性,注意需要先调用指定该方法,才会将gender属性以及addr属性封装到该对象中。才可以访问
N_stu.stu_infor()
print(N_stu.gender)
print(N_stu.addr)
2.封装
• 出现封装的原因:我们需要一种方式来增强数据的安全性
• 1. 属性不能随意修改
• 2. 属性不能改为任意的值
• 封装是面向对象的三大特性之一
• 封装是指隐藏对象中一些不希望被外部所访问到的属性或方法
• 我们也可以提供给一个getter()和setter()方法是外部可以访问到属性
• getter() 获取对象中指定的属性
• setter() 用来设置对象指定的属性
• 使用封装,确实增加了类的定义的复杂程度,但是它也确保了数据的安全
• 1. 隐藏属性名,使调用者无法随意的修改对象中的属性
• 2. 增加了getter()和setter()方法,很好控制属性是否是只读的
• 3. 使用setter()设置属性,可以在做一个数据的验证
• 4. 使用getter()方法获取属性,使用setter()方法设置属性可以在读取属性和修改属性的同时做一些其他的处理
• 可以为对象的属性使用双下划线开头 __xxx。双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象访问
• 其实隐藏属性只不过是Python自动为属性改了一个名字 --> _类名__属性名 例如 __name -> _Person__name
• 这种方式实际上依然可以在外部访问,所以这种方式我们一般不用。一般我们会将一些私有属性以_开头
• 一般情况下,使用_开头的属性都是私有属性,没有特殊情况下不要修改私有属性
class Person:
def __init__(self, name):
self._name = name
# getter查看属性
def get_name(self):
print('用户调用了此读取方法')
return self._name
def set_name(self, name):
print('用户调用了此修改方法')
self._name = name
p1 = Person('周慧敏')
p1.set_name('林青霞')
# p1.name = '张柏芝'
# print(p1._name)
# # print(p1._Person__name)
print(p1.get_name())
#结果
用户调用了此修改方法
用户调用了此读取方法
林青霞
3.装饰器
。可以使实例调用get和set方法的时候,就像查看属性一样,例如:
response = requests.get(‘xxxx’)
content = response.text #text就使用了@property这个装饰器
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
print('get方法执行了')
return self._name
@name.setter
def name(self, name):
print('set方法执行了')
self._name = name
# def __call__(self, *args, **kwargs):
p1 = Person('周慧敏')
#查看属性
p1.name
#修改属性
p1.name = '林青霞'
print(p1.name)
#结果
set方法执行了
get方法执行了
林青霞