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}
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
多态好处的体现:完全不需要考虑得到的对象时声明的类型,只需要知道基类中的内容就能使用。
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模块与子类,但是我们书写规范,最终还是达到了多态的效果