接着上面讲的,我们之前提过,类里面不光有数据还有方法。这种将数据通过方法直接在类内部操作的形式叫做封装。这里的封装是把数据封装在类内部。这样对类形成了一种“黑盒”状态,我们不需要知道类内部是什么样的。只要对对象进行操作就可以。
再回到上篇讲的数据访问限制,我们讲到既想将数据保护起来,又想在一定程度上对数据进行操作。这里就可以用到这个特性,我们可以在类中,设定一个方法,get_eyes()来得到数据,modify_eyes()来修改数据。示例如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Animal(object):
def __init__(self,legs,eyes):
self.__legs=legs
self.__eyes=eyes
def get_eyes(self):
return self.__eyes
def modify_eyes(self,eyes):
self.__eyes=eyes
wolf=Animal(4,2)
print (wolf.get_eyes())
这样我们就又可以访问,得到数据了。我们这里再想一下,我们还可以对数据进行筛选操作,防止错误数据传入对朝鲜造成破坏。示例代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Animal(object):
def __init__(self,legs,eyes):
self.__legs=legs
self.__eyes=eyes
def get_eyes(self):
return self.__eyes
def modify_eyes(self,eyes):
if 0<=eyes<=4:
self.__eyes=eyes
else:
raise ValueError('Bad Data')
wolf=Animal(4,2)
wolf.modify_eyes(5)
print(wolf.get_eyes())
输出结果如下:
raise ValueError('Bad Data')
ValueError: Bad Data
这里起到了保护程序的作用,你可能已经注意到。
0<=eyes<=4:
这是允许的。python大法好。/撒花
最后要注意一点。可能有人想这么修改:
wolf=Animal(4,2)
wolf.__eyes=3
print(wolf.get_eyes())
但实际上,是修改不了的。
输出结果:
2
继承这个概念是用来描述类与类之间的关系的。顾名思义,子类可以从父类继承内容。比如我们已经定义了一个Animal类,代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Animal(object):
def eat(self):
print ("animal can eat")
def sleep(self):
print ("animal can sleep")
def birth(self):
print ("animal can birth")
class Dog(Animal):
pass
black_dog=Dog()
black_dog.eat()
black_dog.sleep()
black_dog.birth()
输出结果:
animal can eat
animal can sleep
animal can birth
这就是继承,什么都不用干,实例black_dog()就有了animal的所有方法。这就是继承的好处,我们也可以对子类增加一些方法:
class Dog(Animal):
def bark(self):
print("Wow Wow")
但是美中不足的是,我们可以从上面看到,输出依然是:animal can....。这是很不舒服的,我们是否可以对子类进行改进呢?答案是可以的。示例代码如下:
class Dog(Animal):
def bark(self):
print("Wow Wow")
def eat(self):
print("Dog can eat")
def sleep(self):
print("Dog can sleep")
def birth(self):
print("Dog can birth")
输出结果是:
Dog can eat
Dog can sleep
Dog can birth
Wow Wow
很高兴,我们成功了。这就是面向对象的第三个特性——多态。
要了解多态,我们先再定义一个函数:
def eat_twice(Animal):
Animal.eat()
Animal.eat()
eat_twice(Dog())
输出结果:
Dog can eat
Dog can eat
我们可能感觉没什么?但是在继承一个新的类,cat。
class Cat(Animal):
def eat(self):
print("Cat can eat")
def eat_twice(Animal):
Animal.eat()
Animal.eat()
eat_twice(Dog())
eat_twice(Cat())
Dog can eat
Dog can eat
Cat can eat
Cat can eat
我们发现不必对eat_twice做修改就可以用,所定义的语句,直接变成了;
Dog.eat()
Dog.eat()
Cat.eat()
Cat.eat()
注意:
这就是多态的好处。我们不必再在意所调用的子类型具体是什么,也不用在意子类型的方法有什么修改。只要子类型与父类型有同样的方法,就可以调用该子类型变量。具体方法由当时使用的情况(即,这个实例是什么子类)决定。这就是多态的强大之处,以及精华之处。
同理:
如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行。
子可以看成父,但父不可以看成子
希望有志同道合的小伙伴关注我的公众平台,欢迎您的批评指正。