类的封装、继承 & 多态
类的基本使用
类的封装
封装的操作
用于设置对象的私有数据 ( 属性 ) / 行为 ( 方法 ) ,使其不能被修改。
- 在定义类时,在 数据 ( 属性 ) / 行为 ( 方法 ) 前面加两个下划线,表示对该 属性 / 方法 进行隐藏,只有类的内部成员可以直接调用,一般情况下外部无法访问
- 在定义类时,这种 __ 数据名 会被转化为 _ 类名 __ 数据名,所以在类的外面,我们还是可以通过 对象名 . _ 类名 __ 数据名 的形式强行访问私有数据,但是一般不推荐这样使用
class Dog():
def __init__(self, DogName):
self.__name = DogName # 定义私有数据
def set_name(self, name):
self.__name = name
def __get_name(self): # 定义私有函数
return self.__name
def get_fun(self):
return self.__get_name()
dog1 = Dog('中华田园犬')
print(dog1.get_fun())
dog1.set_name('二哈')
print(dog1.get_fun())
print(f'强行调用私有函数输出{dog1._Dog__get_name()}') # 不推荐强行调用
print(f'强行调用私有数据输出{dog1._Dog__name}')
# ---------- 输出 ----------
# 中华田园犬
# 二哈
# 强行调用私有函数输出二哈
# 强行调用私有数据输出二哈
- 一般我们会在数据名前加一个下划线,来表示这是一个私有数据。就是说它其实还是一般的数据,只是我们以这种方式来告诉别人这是私有数据,不希望被修改。
装饰器的使用
让我们能以调用数据的方式调用行为函数。方便我们后续的操作。
装饰器 @property
一般用于查询私有数据。我们可以在类的函数前使用 @property ,property装饰器会将行为 ( 方法 ) 转换为同名的数据 ( 属性 ) 。这样我们就可以用访问数据 ( 属性 ) 的形式调用行为 ( 方法 ) 。
class Dog():
def __init__(self, dogName):
self.__name = dogName
@property
def name(self):
print('执行property后面的函数', end=' ')
return self.__name
dog1 = Dog('little_black')
print(dog1.name)
# ---------- 输出 ----------
# 执行property后面的函数 little_black
装饰器 @函数名 . setter
一般用于修改 @property 修饰的函数的值。在进行修改操作的函数前面添加 @函数名 . setter 装饰器,该函数就会转化为同名属性,对该属性进行赋值,就是修改 @property 后面的函数的值。
- 装饰器修饰的函数名建议保持一致
class Dog():
def __init__(self, dogName):
self.__name = dogName
@property
def name(self):
print('执行property后面的函数', end=' ')
return self.__name
@name.setter
def name(self, newName):
print('执行setter后面的函数')
self.__name = newName
dog1 = Dog('little_black')
print(dog1.name)
dog1.name = 'big_dog'
print(dog1.name)
# ---------- 输出 ----------
# 执行property后面的函数 little_black
# 执行setter后面的函数
# 执行property后面的函数 big_dog
装饰器@函数名 . deleter
一般用于删除 @property 后面的函数的值。在进行删除操作的函数前面添加 @函数名 . deleter 装饰器,该函数就会转化为同名属性,对该属性进行删除操作,就是删除 @property 后面的函数的值。
- 装饰器修饰的函数名建议保持一致
class Dog():
def __init__(self, dogName):
self.__name = dogName
@property
def name(self):
print('执行property后面的函数', end=' ')
return self.__name
@name.deleter
def name(self):
print('执行deleter后面的函数')
del self.__name
dog1 = Dog('little_black')
print(dog1.name)
del dog1.name
# ---------- 输出 ----------
# 执行property后面的函数 little_black
# 执行deleter后面的函数
类的继承
- 特点:可以提高代码的重复利用率;符合 OCP 原则 (在不修改原代码的情况下,增加功能)。
- 通过继承,我们可以获取到其他类的属性和方法
继承的操作
- 在定义类的时候,在类名后面的括号里,填写当前类的父类 ( 超类、基类 )。这样当前类就可以调用父类里面的属性和行为了。
class Animals():
name = 'animals'
def run(self):
print('Animals can run')
class Dog(Animals):
pass
dog1 = Dog()
print(dog1.name, end=':')
dog1.run()
# ---------- 输出 ----------
# animals:Animals can run
- 如果当前类与父类都有一样的行为 / 数据,当前类的值会覆盖父类的值
class Animals():
name = 'animals'
def run(self):
print('Animals can run')
class Dog(Animals):
name = 'dog'
def run(self):
print('Dog can run')
dog1 = Dog()
print(dog1.name, end=':')
dog1.run()
# ---------- 输出 ----------
# dog:Dog can run
- 多重继承,一般不推荐用;因为开发中要求解耦合,即不希望不同的代码之间产生太多的牵连。
- 子类对象调用的函数,会先在子类里面找;如果没有,就到第一个继承的父类里面找;如果再没有就到下一个继承的父类里面找…
class Father():
def dancing(self):
print('dadadada', end=' ')
class Mother():
def singing(self):
print('lalalala')
class Son(Father, Mother):
pass
boy = Son()
boy.dancing()
boy.singing()
# ---------- 输出 ----------
# dadadada lalalala
issubclass(class1, class2)
用于判断 class1 是否是 class2 的子类;若是则返回 True,否则返回 False
- 所有类的父类都是 object
class Animals(object):
pass
class Dog(Animals):
pass
print(issubclass(Dog, Animals), end=' ')
print(issubclass(Animals, object))
print(issubclass(type, object), end=' ')
print(issubclass(int, object))
# ---------- 输出 ----------
# True True
# True True
className . __ bases __
会返回该类的所有父类
class Father(object):
pass
class Son(Father):
pass
print(Son.__bases__)
# ---------- 输出 ----------
# (<class '__main__.Father'>,)
super ( Class, self ) 函数
- Python 3 可以直-接使用 super().xxx 代替 super ( Class, self ) . xxx
单继承
- 用于在当前类的函数中调用父类中的同名函数
- super ( ) :找到该类的父类,把该类的对象转换为父类的对象
- super ( ) 调用的函数不用写 self 形参
class Animals(object):
def __init__(self, AnimalName):
print('enter Animals-init')
self.name = AnimalName
print('leave Animals-init')
def run(self, object1):
print('enter Animals-run')
print('%s can run' %object1)
print('leave Animals-run')
class Dog(Animals):
def __init__(self, DogName, DogAge):
print('enter Dog-init')
self.age = DogAge
super(Dog, self).__init__(DogName)
# 等价于Animals.__init__(self, DogName)
print('leave Dog-init')
def run(self, object1):
print('enter Dog-run')
super(Dog, self).run(object1)
# 等价于Animals.run(self, object1)
print('leave Dog-run')
dog1 = Dog('哈士奇', 5)
print(dog1.name, dog1.age)
dog1.run('二哈')
# ---------- 输出 ----------
# enter Dog-init
# enter Animals-init
# leave Animals-init
# leave Dog-init
# 哈士奇 5
# enter Dog-run
# enter Animals-run
# 二哈 can run
# leave Animals-run
# leave Dog-run
多继承
- 先继承的父级,先执行;后继承的父级,后执行。
class Grandfather(object):
def __init__(self):
print('enter Grandfather')
print('leave Grandfather')
class Father(Grandfather):
def __init__(self):
print('enter Father')
super(Father, self).__init__()
print('leave Father')
class Mother(Grandfather):
def __init__(self):
print('enter Mother')
super(Mother, self).__init__()
print('leave Mother')
class Son(Father, Mother):
def __init__(self):
print('enter Son')
super(Son, self).__init__()
print('leave Son')
boy = Son()
# ---------- 输出 ----------
# enter Son
# enter Father
# enter Mother
# enter Grandfather
# leave Grandfather
# leave Mother
# leave Father
# leave Son
等价于以下写法,但是这种写法会导致父类被调用多次,而 super ( ) 可以减少这样的开销。
class Grandfather(object):
def __init__(self):
print('enter Grandfather')
print('leave Grandfather')
class Father(Grandfather):
def __init__(self):
print('enter Father')
# 等价于super(Father, self).__init__()
Grandfather.__init__(self)
print('leave Father')
class Mother(Grandfather):
def __init__(self):
print('enter Mother')
# 等价于super(Mother, self).__init__()
Grandfather.__init__(self)
print('leave Mother')
class Son(Father, Mother):
def __init__(self):
print('enter Son')
Father.__init__(self)
Mother.__init__(self)
# 等价于super(Son, self).__init__()
print('leave Son')
boy = Son()
# ---------- 输出 ----------
# enter Son
# enter Father
# enter Grandfather
# leave Grandfather
# leave Father
# enter Mother
# enter Grandfather
# leave Grandfather
# leave Mother
# leave Son
类的多态
具有不同功能的函数,可以使用相同的函数名;这样就可以用一个函数名,调用不同功能的函数。
对象之间没有继承关系的情况
class Dog(object):
def run(self):
print('Dog is running')
class Cat(object):
def run(self):
print('Cat is running')
class Lion(object):
def run(self):
print('Lion is running')
def run(obj):
obj.run()
dog1 = Dog()
cat1 = Cat()
lion1 = Lion()
run(dog1)
run(cat1)
run(lion1)
# ---------- 输出 ----------
# Dog is running
# Cat is running
# Lion is running
对象之间有继承关系的情况
class Grandfather(object):
def __init__(self, money):
self.money = money
class Father(Grandfather):
def __init__(self, money, job):
self.job = job
super(Father, self).__init__(money)
class Mother(Grandfather):
def __init__(self, money, job):
self.job = job
super(Mother, self).__init__(money)
def job(obj):
print(obj.job, end=' ')
def money(obj):
print(obj.money, end=' ')
person1 = Grandfather(3000)
person2 = Father(10000, 'programmer')
person3 = Mother(8000, 'teacher')
job(person2)
job(person3)
money(person1)
money(person2)
money(person3)
# ---------- 输出 ----------
# programmer teacher 3000 10000 8000