面向对象之多态

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模块与子类,但是我们书写规范,最终还是达到了多态的效果
鸭子类型多态的体现
原文地址:https://www.cnblogs.com/846617819qq/p/10136724.html