zoukankan      html  css  js  c++  java
  • 面向对象之多态

    1.property装饰器

      property装饰器是用来将类内的函数属性伪装成数据属性。当一些属性的值,不是固定的而是通过计算得来的时候,我们必须为这个属性添加方法才能完成计算,但是一旦使用方法后,该属性的的访问方式就变成了方法的调用,很明显与其他属性的访问方式不同,这样会给使用者带来困惑,所以需要将这个方法伪装成普通的属性,此时就用到了property装饰器。

    #BMI案例
    #不使用property装饰器时
    class Body:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    
        def bmi(self):
            return self.weight/(self.height**2)
    
    b1=Body("杨过",75,1.83)
    print(b1.bmi())
    
    #bmi看起来更像是一个属性而不是一个方法,因此我们需要用property装饰器进行伪装
    
    #使用property装饰器时
    class Body:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
        @property
        def bmi(self):
            return self.weight/(self.height**2)
    
    b1=Body("杨过",75,1.83)
    print(b1.bmi)

      利用property装饰器可以将方法伪装成属性这一特点,我们也可以将其使用到封装中,之前没有property装饰器时,访问类中的私有属性时,需要类中定义方法,来间接访问和修改私有属性,现在便可以使用property装饰器进行伪装,使得访问私有属性与访问普通属性的方式一致。

    class Student:
        def __init__(self,name,age):
            self.__name=name
            self.__age=age
        @property
        def name(self):
            return self.__name
        @name.setter     #property装饰器的另一个用法,setter,修改属性,用法看代码
        def name(self,name):
            if isinstance(name,str):
                self.__name=name
            else:
                print("名字必须为str类型")
        @name.deleter      #property装饰器的另一个用法,deleter,删除属性,用法看代码
        def name(self):
            del self.__name
    
    stu=Student("egon",18)
    stu.name=1212
    print(stu.name)
    del stu.name
    print(stu.__dict__)
    
    >>>:
    egon
    {'_Student__age': 18}
    porperty装饰器对封装的操作

    2.面向对象的三大特征之一:多态

      2.1什么是多态?

        在生活中多态指的是多种形态,生活中有许多具备多种形态的食物,水等,即一种事物具备多种形态或状态就称之为多态。

        在程序中,官方解释是:不同的对象,可以相应同一方法,并作出不同的行为,产生不同的结果,那么便是多态。

      2.2如果实现多态?

        让几个不同类拥有相同的父类(又称基类),这样一来他们就具备了相同的方法,每个子类要覆盖父类的方法,从而每个类的对象行为都不同。

    class Animal:
        def eat(self):
            print("动物在吃东西...")
    
    class Person(Animal):
        def eat(self):
            print("人吃粮食...")
    
    class Pig(Animal):
        def eat(self):
            print("猪吃饲料...")
    
    class Dog(Animal):
        def eat(self):
            print("狗吃骨头...")
    
    
    person = Person()
    pig = Pig()
    dog = Dog()
    
    person.eat()
    pig.eat()
    dog.eat()
    >>>:
    人吃粮食...
    猪吃饲料...
    狗吃骨头...
    
    #人类,猪类,狗类都继承与一个父类动物类,是动物就需要吃东西,所以人,狗,猪都有#吃这一个方法,但是他们又有所不同,吃的方式不同,最终的结果也不同,这便是多态。
    以动物为例的多态

      2.3多态使程序扩展性提高

        使用多态后,对象的使用者不需要关心该对象具体的实现,只需要知道该对象属于哪个基类,就能直接使用它。

      2.4多态之abc模块

        多态是多个类的对象拥有相同的方法,但是我们没有从严格要求说必须提供这些方法,子类可以完全不提供这些方法,如此做的话,可能会达不到多态的要求。abc模块便是严格要求子类必须实现父类声明的方法的模块。

        2.4.1使用abc模块来限制子类的步骤:

            1.为类中指定元类为abc.ABCMeta

            2.在相应的方法上加上abc.abstractmethod装饰器

    import abc
    class Animal(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
    
    class Cat(Animal):
        def eat(self):
            print("猫爱吃鱼肉...")
    
        def drink(self):
            print("用舌头舔..")
    
    class Dog(Animal):
        def eat(self):
            print("狗爱吃骨头...")
        def drink(self):
            print("用舌头舔..")
    
    class Pig(Animal):
        def eat(self):
            print("猪 爱吃草...")
    
        def drink(self):
            print("用嘴吸的..")
    p = Pig()
    c = Cat()
    
    #如果在任意一个子类中缺少了基类中的任意一个被abc装饰器装饰的方法,那么便会报
    #错。错误如下:
    #TypeError: Can't instantiate abstract class Pig with abstract methods drink
    abc模块用法

      多态好处的体现:完全不需要考虑得到的对象时声明的类型,只需要知道基类中的内容就能使用。

    def feeding(animal):
        animal.eat()
        animal.drink()
    
    feeding(c)
    feeding(p)
    
    #代码接上段代码,当我想要饲养动物时,我只需要知道继承基类动物类的且会吃会喝水的便是动物,只是吃喝可能会有不同,但这两个方法缺一不可。
    多态好处的扩展性和好处的体现
    print(len("abc"))
    print(len([1,2,3,4,]))
    print(len({"name":"123","sex":"man"}))
    
    print("abc".__len__())
    print([1,2,3,4,].__len__())
    print({"name":"123","sex":"man"}.__len__())
    
    print(len({1,23,4,5}))
    系统内置的方法有很多都体现了多态

      2.5鸭子类型

        Python推崇简单的编程方式,也就是说Python推崇鸭子类型。

        定义:鸭子类型,如果一个对象叫声像鸭子,走路像鸭子,那就把它当成鸭子。

           对应到代码中就是:只要你的行为一样,那就会把你当成同一个类型来看待。

        作用:如果程序员足够自觉,可以不使用abc模块,也不需要基类,自觉的将方法名字都写成一样,同样可以实现多态。

    class Duck:
    
        def bark(self):
            print("鸭子嘎嘎叫...")
    
        def run(self):
            print("摇摇晃晃走....")
    
    class Chicken:
        def bark(self):
            print("鸡咯咯叫...")
    
        def run(self):
            print("摇摇晃晃走....")
    
    def test(obj):
        obj.bark()
        obj.run()
    duck = Duck()
    c = Chicken()
    
    test(duck)
    test(c)
    
    >>>"
    鸭子嘎嘎叫...
    摇摇晃晃走....
    鸡咯咯叫...
    摇摇晃晃走....
    
    #如上,没有使用abc模块与子类,但是我们书写规范,最终还是达到了多态的效果
    鸭子类型多态的体现
  • 相关阅读:
    CF 980D Perfect Groups(数论)
    CF 983B XOR-pyramid(区间dp,异或)
    CF 984C Finite or not? (数论)
    CF 979D Kuro and GCD and XOR and SUM(异或 Trie)
    (可能)常用打比赛网站
    排序工作量之新任务(SHOI2001)
    【图楼】长期图楼~~不定期更新
    【题解】SHOI2014概率充电器
    【题解】NOIP2015推销员
    [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]
  • 原文地址:https://www.cnblogs.com/846617819qq/p/10136724.html
Copyright © 2011-2022 走看看