day21

组合

什么是组合

组合就是一个类的对象具备某一个属性,该属性的值指向另外一个类的对象

为什么用组合

组合是用来解决类与类之间代码冗余的问题

如何用组合

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)

多态性的好处

  1. 增加了程序的灵活性
  2. 增加了程序的可扩展性

抽象类

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()方法,就可以正确的被调用。
'''
上一篇:day21总结


下一篇:1011课堂小结 day21