一、 特殊方法(魔术方法)
特殊方法都是以__开头__结尾的方法
特殊方法不需要自己调用
学习特殊方法:
1.特殊方法什么时候调用
2.特殊方法有什么作用
# 对于Person这个类name属性是必须,并且每一个实例对象的name属性是不一样的
# 我们现在是将name属性手动添加
# 特别容易出错
# 对象的创建流程
# p1 = Person()
# 1.创建了一个变量
# 2.在内存中创建了一个新的对象
# 3.执行类中的代码块中的代码(只在类中执行一次)
# 4.__init__方法执行了
class Person:
# print('Person类中代码')
# name = '葫芦娃'
# 特殊方法不需要我们自己调用
# 特殊方法会在特殊的时候自动调用
# init会在对象创建以后立即执行
# init会向新创建的对象初始化属性
def __init__(self,name):
# 通过self向新建的对象初始化属性
self.name = name
# Person中的self <__main__.Person object at 0x0000020A04819908> 葫芦娃
# 每次实例化Person时,self的值都是不同的
print('Person中的self',self,name)
def speak(self):
print('大家好,我是%s'%self.name)
p1 = Person('葫芦娃') #Person中的self <__main__.Person object at 0x000001E21476B9C8> 葫芦娃
print(p1.name) #葫芦娃
p2 = Person('钢铁侠') #Person中的self <__main__.Person object at 0x000001E21476BB08> 钢铁侠
print(p2.name) #钢铁侠
# p3 = Person()
# p4 = Person()
p1.speak() #大家好,我是葫芦娃
p2.speak() #大家好,我是钢铁侠
p1.__init__('劳拉') #Person中的self <__main__.Person object at 0x000002C81D1BB9C8> 劳拉
# 手动向实例对象添加属性
p1.name = '小金刚葫芦娃'
# p2 = Person() #Person()的括号中没有参数,会直接报错
# p2.name = '钢铁侠'
p1.speak() #大家好,我是小金刚葫芦娃
p3 = Person(1) #Person中的self <__main__.Person object at 0x000001E21476BB48> 1
p3.name = '黑猫警长'
p3.speak() #大家好,我是黑猫警长
类的基本结构
class 类名([父类]):
公共属性...
对象的初始化方法
def __init__(self,....)
其他的方法
def method(self,...)
二、 类的练习
尝试定义一个表示车的类
'''
属性: name color
方法: run() laba()
'''
class Car():
def __init__(self,name,color):
self.name = name
self.color = color
def run(self):
print('汽车开始跑了....')
def laba(self):
print('%s 嘀嘀嘀嘀'%self.name)
c = Car('大奔','白色')
c.name = '奥迪'
c.color = '黑不溜秋'
print(c.name,c.color) #奥迪 黑不溜秋
c.run() #汽车开始跑了....
c.laba() #奥迪 嘀嘀嘀嘀
注意:
我们要如何增加数据的安全性
1.属性不能随意修改(我让你改你才能改,不让你改你就别改)
2.属性不能改为任意的值
三、封装1
封装是面向对象的三大特性之一
封装指的是隐藏对象中一些不希望被外部访问到的属性或方法
1.如何隐藏对象中的一个属性
将对象的属性名,修改为一个外部不知道的名字
2.如何获取(修改)对象当中的属性
我们可以提供一个getter和setter
使用封装,确实增长了类定义复杂度,但是它确保了数据的安全性:
1.隐藏了属性名,使调用者无法随意修改对象当中的属性
2.增加了getter和setter方法,可以很好的控制属性是否是只读的
如果希望属性是只读的,则可以直接去掉setter方法
如果希望属性不能被外界访问,则可以 直接去掉getter方法
3.使用setter方法设置属性,可以增加数据的验证,确保数据的值是正确的
4.可以在读取属性和设
class Dog:
def __init__(self,name,age):
self.hidden_name = name
self.hidden_age = age
def speak(self):
print('大家好,我是%s'%self.hidden_name)
def get_age(self):
return self.hidden_age
def set_age(self,age):
if age > 0:
self.hidden_age = age
def get_name(self):
# get_name()用来获取对象的属性
return self.hidden_name
def set_name(self,name):
self.hidden_name = name
d = Dog('二哈',5)
# d.hidden_name = '凯撒'
# print(d.name) #'Dog' object has no attribute 'name'
d.set_name('凯撒')
print(d.get_name()) #凯撒
d.speak() #大家好,我是凯撒
d.set_age(-10)
print(d.get_age()) #5,因为-10<0,所以年龄还是初始值5
四、封装2
可以为对象的属性使用双下划线开头,__xxx
双下划线开头的属性是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过外部访问
隐藏属性是python自动为属性改了一个名字
实际改的名字是: _类名_属性名 __name -> _Person__name
class Person:
def __init__(self,name):
self._name = name
def get_name(self):
return self._name
def set_name(self,name):
self._name = name
p = Person('葫芦宝')
print(p.get_name()) #葫芦宝
p.set_name('浩克')
p.hidden_name = '猫女'
p.__name = '黑猫警长'
print(p.hidden_name) #猫女
print(p.__name) #黑猫警长
p._Person__name = '黑猫警长'
print(p._Person__name) #黑猫警长
print(p.get_name()) #浩克
一般情况,使用_开头的属性都是私有属性,没有特殊情况下不要修改私有属性
五、 @property
用来将一个get方法 转换为对象的属性
添加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):
self._name = name
#
# import requests
#
# import urllib
p = Person('小蝴蝶')
p.name = 'gangtiex'
print(p.name) #get方法执行了 #gangtiex