【Python】类的封装、继承 & 多态

tech2025-01-08  6

类的封装、继承 & 多态

类的基本使用类的封装封装的操作装饰器的使用装饰器 @property装饰器 @函数名 . setter装饰器@函数名 . deleter 类的继承继承的操作issubclass(class1, class2)className . __ bases __super ( Class, self ) 函数单继承多继承 类的多态对象之间没有继承关系的情况对象之间有继承关系的情况

类的基本使用

【Python】类的基本使用

类的封装

封装的操作

用于设置对象的私有数据 ( 属性 ) / 行为 ( 方法 ) ,使其不能被修改。

在定义类时,在 数据 ( 属性 ) / 行为 ( 方法 ) 前面加两个下划线,表示对该 属性 / 方法 进行隐藏,只有类的内部成员可以直接调用,一般情况下外部无法访问在定义类时,这种 __ 数据名 会被转化为 _ 类名 __ 数据名,所以在类的外面,我们还是可以通过 对象名 . _ 类名 __ 数据名 的形式强行访问私有数据,但是一般不推荐这样使用 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
最新回复(0)