保护对象的属性
如果有一个对象,当需要对其进行修改属性时,有2钟方法:
- 对象名.属性名 = 数据 ---->直接修改
- 对象名.方法名() ---->间接修改
为了更好的保存属性的安全,即不能随意修改,一般的处理方式为:
- 将属性定义为私有属性
- 添加一个可以调用的方法,供调用
11 class Person(object): 12 def __init__(self,name): 13 self.__name = name 14 def getName(self): 15 return self.__name 16 def setName(self,newName): 17 if len(newName)>=5: 18 self.__name = newName 19 else: 20 print('error:名字的长度要大于或者等于5') 21 22 xiaoming = Person('XIAOYAFEI') 23 print(xiaoming.__name)
运行结果为:
Traceback (most recent call last): File "test.py", line 23, in <module> print(xiaoming.__name) AttributeError: 'Person' object has no attribute '__name'
修改代码:
11 class Person(object): 12 def __init__(self,name): 13 self.__name = name 14 def getName(self): 15 return self.__name 16 def setName(self,newName): 17 if len(newName)>=5: 18 self.__name = newName 19 else: 20 print('error:名字的长度要大于或者等于5') 21 22 xiaoming = Person('XIAOYAFEI') 23 24 xiaoming.setName("wang") 25 print(xiaoming.getName()) 26 27 xiaoming.setName('lisisi') 28 print(xiaoming.getName())
运行结果:
error:名字的长度要大于或者等于5
XIAOYAFEI
lisisi
总结:
- python中没有像C++中public和private这些关键字来区别公有属性和私有属性
- 它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表示该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)
__del__()方法
创建对象后,python解释器默认调用__init__()方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 15:28:14 6 7 # File Name: test2.py 8 # Description: 9 10 """ 11 import time 12 class Animal(): 13 #初始化方法 14 #创建为对象后会自动被调用 15 def __init__(self,name): 16 print('???????__init__方法被调用???????') 17 self.__name = name 18 19 #析构方法 20 #当对象被删除时,会自动被调用 21 def __del__(self): 22 print('__del__方法被调用') 23 print('%s对象马上被干掉了......'%self.__name) 24 25 #创建对象 26 dog = Animal('嗨皮') 27 #删除对象 28 del dog 29 30 cat = Animal('波斯猫') 31 cat2 = cat 32 cat3 = cat 33 34 print('马上删除cat对象') 35 del cat 36 print('马上删除cat1对象') 37 del cat2 38 print('马上删除cat2对象') 39 del cat3 40 41 print('程序在2秒钟后结束') 42 time.sleep(2)
运行结果如下:
———————__init__方法被调用——————— __del__方法被调用 嗨皮对象马上被干掉了...... ———————__init__方法被调用——————— 马上删除cat对象 马上删除cat1对象 马上删除cat2对象 __del__方法被调用 波斯猫对象马上被干掉了...... 程序在2秒钟后结束
总结:
- 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
- 当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
继承
在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为狗和猫继承自动物;同理,波斯猫和巴厘猫都继承自猫,而沙皮狗和斑点狗都继承自狗
继承示例
#!/usr/bin/python #coding=utf8 """ # Author: xiaoyafei # Created Time : 2018-04-04 11:35:02 # File Name: 03-单继承.py # Description: """ #定义一个父类 class Cat(): def __init__(self,name,color="白色"): self.name = name self.color = color def run(self): print('%s------在跑'%self.name) #定义一个子类,来继承Cat类 class Bosi(Cat): def __str__(self): return self.name def setNewName(self,newName): self.name = newName def eat(self): print("%s------在吃"%self.name) bs = Bosi("lipeng") bs.run() bs.setNewName("小明") print(bs)
运行结果为:
lipeng------在跑
小明
说明:
- 虽然子类没有定义__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi对象,就默认执行了那个继承过来的父类的__init__方法
总结:
- 子类在继承的时候,在定义类时,小括号()中为父类的名字
- 父类的属性、方法,会被继承给子类
注意点
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 15:45:07 6 7 # File Name: 04-单继承-注意点.py 8 # Description: 9 10 """ 11 class Animal(): 12 def __init__(self,name='动物',color='白色'): 13 self.__name = name 14 self.color = color 15 def __test(self): 16 print(self.__name) 17 print(self.color) 18 def test(self): 19 print(self.__name) 20 print(self.color) 21 22 class Dog(Animal): 23 def dogTest1(self): 24 #print(self.__name) 25 print(self.color) 26 def dogTest2(self): 27 #self.__test() 28 self.test() 29 30 A = Animal() 31 #print(A.__name) #程序出现异常,不能直接访问私有属性 32 print(A.color) 33 #A.__test() #程序出现异常,不能直接访问私有方法 34 A.test() 35 36 print('----------------------------华丽的分割线----------------------------------') 37 D = Dog(name = '小花狗',color = '黄色') 38 D.dogTest1() 39 D.dogTest2()
- 私有的属性,不能通过对象直接访问,但是可以通过方法访问
- 私有的方法,不能通过对象直接访问
- 私有的属性、方法,不会被子类继承,也不能给访问
- 一般情况下,私有的属性、方法都是不对外公布的,往往来做内部的事情,起到安全的作用
多继承
所谓多继承,即子类有多个父类,并且具有它们的特征
python中多继承的格式如下:
14 class a(): 15 def printA(self): 16 print('-aaaaaaaaaaaaa') 17 18 class b(): 19 def printB(self): 20 print('------------b') 21 22 23 class c(a,b): 24 def printC(self): 25 print('-cccccccccccccccccc') 26 27 c = c() 28 c.printA() 29 c.printB() 30 c.printC()
运行结果如下:
-aaaaaaaaaaaaa ------------b -cccccccccccccccccc
说明:
- python中是可以多继承的
- 父类中的方法、属性,子类会继承
多继承-注意点
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-04 14:29:20 6 7 # File Name: 06-多继承注意点.py 8 # Description: 9 在多个父类中拥有相同的方法应该调用哪一个??? 10 11 可以使用__mro__方法去查看调用顺序 12 """ 13 14 class A(): 15 def printA(self): 16 print('aaaaaaaaaaaaaaaaaa') 17 class B(): 18 def printA(self): 19 print('bbbbbbbbbbbbbbbbb') 20 21 class S(A,B): 22 def printS(self): 23 print('SSSSSSSSSSSSSSSSSS') 24 25 zi = S() 26 zi.printS() 27 zi. printA() 28 print(S.__mro__) #可以查看C类的对象搜索方法时的先后顺序
运行结果:
SSSSSSSSSSSSSSSSSS aaaaaaaaaaaaaaaaaa (<class '__main__.S'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
重写父类方法和调用父类方法
重写父类方法
所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
13 class Cat(): 14 def sayHello(self): 15 print('Hello----1') 16 17 class Bosi(Cat): 18 def sayHello(self): 19 print('Hello----4') 20 bosi = Bosi() 21 bosi.sayHello()
运行结果如下:
Hello----4
调用父类方法
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 17:28:14 6 7 # File Name: 08-调用父类的方法-1.py 8 # Description: 9 10 """ 11 class Cat(): 12 def __init__(self,name): 13 self.name = name 14 self.color = 'yellow' 15 16 class Bosi(Cat): 17 def __init__(self,name): 18 super().__init__(name) 19 20 def getName(self): 21 return self.name 22 23 bosi = Bosi('波斯猫') 24 print(bosi.name) 25 print(bosi.color)
运行结果如下:
波斯猫
yellow
super()不是父类,而是继承顺序的下一个类
在多重继承是会涉及到继承顺序,super()相当于返回继承顺序的下一个类,而不是父类
多态
多态的概念是应用于Java和c#这一类强语言中,而python崇尚"鸭子类型"
所谓多态:定义时的类型和运行时的类型不一样,此时就形成了多态
python鸭子类型代码:
12 class F1(object): 13 def show(self): 14 print('F1.show') 15 class S1(F1): 16 def show(self): 17 print('S1.show') 18 class S2(F1): 19 def show(self): 20 print('S2.show') 21 22 def Func(obj): 23 print(obj.show()) 24 25 s1_obj = S1() 26 Func(s1_obj) 27 28 s2_obj = S2() 29 Func(s2_obj)