组合
什么是组合
组合就是一个类的对象具备某一个属性,该属性的值指向另外一个类的对象
为什么用组合
组合是用来解决类与类之间代码冗余的问题
如何用组合
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class Teacher(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
class Student(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
# 日期类
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tell_birth(self):
print(f'''
=== 出生年月日 ===
年: {self.year}
月: {self.month}
日: {self.day}
''')
tea1 = Teacher('tank', 17, 'male')
date_obj = Date(2002, 1, 1)
# date_obj.tell_birth()
# 将date对象赋值到tea1对象的date属性中
tea1.date = date_obj
tea1.date.tell_birth()
访问限制机制
#当我们在类的内部定义一些不想被外部访问的属性时,可以使用__变量名、__函数名的方式来定义
class Foo:
# 数据属性
__name = 'tank'
# 方法属性
def __run(self):
print('running..')
#但是这种方式也仅仅是限制,可以通过接口的方式来访问
class Foo:
# 数据属性
__name = 'tank'
# 方法属性
def __run(self):
print('running..')
# 接口: 获取数据接口
def get_name(self):
return self.__name
def set_name(self):
self.__name = 'jason_sb'
foo = Foo()
#print(foo.__name) #找不到这个属性
res = foo.get_name()
print(res)
print(foo._Foo__name) # --> _Foo__name
foo.set_name()
print(foo.get_name())
property
property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不加括号直接使用
class People:
def __init__(self, name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight / (self.height * self.height)
'''
property装饰器的三种形式
@property
@get_name.setter
@get_name.deleter
'''
# 了解
@property
def get_name(self):
return self.name
# 改
@get_name.setter
def set_name(self, val):
self.name = val
# 删除
@get_name.deleter
def del_name(self):
del self.name
#实例化对象
p = People('jason', 200, 1.6)
#调用对象的get_name方法,不需要加括号
print(p.get_name)
#调用对象的set_name方法,并将'tank'作为参数传入方法
p.set_name = 'tank'
print(p.get_name)
#调用对象的del_name方法
del p.del_name
print(p.get_name)
多态和多态性
多态
多态指的是一类事物由多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)
class Animal:
def run(self): # 子类约定俗称的必须实现这个方法
raise AttributeError('子类必须实现这个方法')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
peo1 = People()
pig1 = Pig()
d1 = Dog()
peo1.run()
pig1.run()
d1.run()
多态性
注意:多态和多态性是两种概念
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数
def func(obj):
obj.run()
func(peo1)
func(pig1)
func(d1)
多态性的好处
- 增加了程序的灵活性
- 增加了程序的可扩展性
抽象类
import abc
class Animal(metaclass=abc.ABCMeta):
# 吃
# 加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法
@abc.abstractmethod
def eat(self):
pass
# 喝
@abc.abstractmethod
def drink(self):
pass
# 叫
@abc.abstractmethod
def speak(self):
pass
# 猪
class Pig(Animal):
# 吃
def eat(self):
print('猪在吃饭')
pass
# 喝
def drink(self):
pass
def speak(self):
print('哼哼哼~~~')
# 派生
def run(self):
pass
pig = Pig()
鸭子类型
class Duck():
def walk(self):
print('I walk like a duck')
def swim(self):
print('i swim like a duck')
class Person():
def walk(self):
print('this one walk like a duck')
def swim(self):
print('this man swim like a duck')
'''
可以很明显的看出,Person类拥有跟Duck类一样的方法,当有一个函数调用Duck类,并利用到了两个方法walk()和swim()。我们传入Person类也一样可以运行,函数并不会检查对象的类型是不是Duck,只要他拥有walk()和swim()方法,就可以正确的被调用。
'''