博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象之组合、封装、多态、property装饰器
阅读量:5221 次
发布时间:2019-06-14

本文共 9865 字,大约阅读时间需要 32 分钟。

概要:

    

    

    

    

1 Python推崇鸭子类型:解耦合,统一标准(不用继承) 2 1. 组合 3     继承:会传递给子类强制属性 4     组合:解耦合,减少占用内存.如:正常继承,如果一个班级有100个学生,那么这个学生的重复的课程信息会存一百遍,浪费内存 5  6     一个对象有一个属性,该属性的值是来自于另外一个类的对象 7  8 2. 封装 9     装指的是将属性装进一个容器10     封指的是将容器内的属性隐藏起来11 12     如何做到"封":在属性名前加上__开头,特点如下:13         1. __开头的属性会在检测语法时发生变形,规则_类名__属性名14         2. 该隐藏是对外不对内的15         3. 该变形只在语法检测时发生一次,在类定义之后新增的__开头的属性不会发生变形16         4. 父类不想让子类覆盖自己的属性,可以在属性前加上__开头17 18     封装不是单纯意义的隐藏:19         1. 封装数据属性: 是为了开放接口让类外部的使用者间接地去操作属性,从而我们可以通过修改接口的逻辑来严格控制使用者对属性的操作20         2. 封装函数属性: 隔离复杂度21 3. property22     是一个装饰器,用来将类中定义的函数伪装成一个数据属性23     class Foo:24         @property25         def xxx(self): # 查看属性的功能26             pass27 28         @xxx.setter29         def xxx(self,val): # 修改属性的功能30             pass31 32         @xxx.deleter33         def xxx(self): # 删除属性的功能34             pass35    原始方式:    36         def c(self):37             pass38         def a(self):39             pass40         def b(self):41             pass42 43         xxx=property(a,b,c)44 4. 多态45     多态指的是同一种事物的多种形态46     多态性指的是可以在不用考虑对象具体类型的前提下而直接使用对象47     继承父类,肯定继承了父类里的功能

组合:

1. 什么是组合    一个对象的属性是来自于另外一个类的对象,称之为组合   此时,这个对象就获得了另一个对象的所有属性和功能2. 为何用组合    组合也是用来解决类与类代码冗余的问题    3. 如何用组合

 演示:

1 class Foo: 2     aaa=1111 3     def __init__(self,x,y): 4         self.x=x 5         self.y=y 6  7     def func1(self): 8         print('Foo内的功能') 9 10 class Bar:11     bbb=222212     def __init__(self, m, n):13         self.m = m14         self.n = n15 16     def func2(self):17         print('Bar内的功能')18 19 obj1=Foo(10,20)20 obj2=Bar(30,40)21 22 obj1.xxx=obj223 #此行代码就是组合的过程24 print(obj1.x,obj1.y,obj1.aaa,obj1.func1)25 print(obj1.xxx.m,obj1.xxx.n,obj1.xxx.bbb,obj1.xxx.func2)#组合之后就可以利用obj1.xxx来调用对象obj2所有的功能

组合的优点及其演化过程:

第一步:最顶级的类的数据属性会传递给依靠类生成的所有对象

1 class OldboyPeople: 2     school = 'Oldboy' 3     # 如果有一个管理员的话,也被迫添加了课程相关的属性 4     def __init__(self, name, age, gender, course_name, course_price, course_period): 5         self.name = name 6         self.age = age 7         self.gender = gender 8         self.course_name = course_name 9         self.course_price = course_price10         self.course_period = course_period11 12 class OldboyStudent(OldboyPeople):13     def choose_course(self):14         print('%s is choosing course' % self.name)15 16 class OldboyTeacher(OldboyPeople):17     def __init__(self, name, age, gender, level, salary, course_name, course_price, course_period):18         OldboyPeople.__init__(self, name, age, gender)19         self.level = level20         self.salary = salary21 22     def score(self, stu, num):23         stu.num = num24         print('老师%s给学生%s打分%s' % (self.name, stu.name, num))25 #对于课程名,价格,周期等不需要重复传入,会增加内存占用26 stu1 = OldboyStudent('egon', 18, 'male', 'Python开发', 3000, '5mons')27 stu2 = OldboyStudent('kevin', 38, 'male', 'Python开发', 3000, '5mons')28 #定义课程函数29 def tell_course(obj):30     print('课程名:<%s> 价钱:[%s] 周期:[%s]' % (obj.course_name, obj.course_price, obj.course_period))31 32 tell_course(stu1)33 tell_course(stu2)

 第二步

1 class OldboyPeople: 2     school = 'Oldboy' 3     def __init__(self, name, age, gender): 4         self.name = name 5         self.age = age 6         self.gender = gender 7  8 class OldboyStudent(OldboyPeople): 9     def choose_course(self):10         print('%s is choosing course' %self.name)11 12 class OldboyTeacher(OldboyPeople):13     def __init__(self, name, age, gender,level,salary):14         OldboyPeople.__init__(self, name, age, gender)15         self.level=level16         self.salary=salary17 18     def score(self,stu,num):19         stu.num=num20         print('老师%s给学生%s打分%s' %(self.name,stu.name,num))21 #定义课程类22 class Course:23     def __init__(self,course_name,course_price,course_period):24         self.course_name=course_name25         self.course_price=course_price26         self.course_period=course_period28     def tell_course(self):29         print('课程名:<%s> 价钱:[%s] 周期:[%s]' % (self.course_name, self.course_price, self.course_period))30 31 python_obj=Course('python开发',3000,'5mons')32 linux_obj=Course('linux运维',5000,'3mons')
stu1=OldboyStudent('egon',18,'male') stu1.courses=[]#给学生对象添加课程属性 stu1.courses.append(linux_obj)#组合(追加课程类对象),解决了代码冗余,浪费内存,解耦合(避免父类的所有属性传递给子类) stu1.courses.append(python_obj) stu1.courses[0].tell_course()#调用课程类中的查课方法

封装(__属性):

1. 什么是封装    装指的是把属性装进一个容器    封指的是隐藏的意思,但是这种隐藏式对外不对内的2. 为何要封装    封装不是单纯意义的隐藏    封装数据属性的目的:将数据属性封装起来,类外部的使用就无法直接操作该数据属性了    需要类内部开一个接口给使用者,类的设计者可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作    封装函数属性的目的:隔离复杂度3. 如何封装    在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)    只需要在属性前加上__开头,该属性就会被隐藏起来,该隐藏具备的特点:        1. 只是一种语法意义上的变形,即__开头的属性会在检测语法时发生变形_类名__属性名        2. 这种隐藏式对外不对内的,因为在类内部检测语法时所有的代码统一都发生的变形        3. 这种变形只在检测语法时发生一次,在类定义之后新增的__开头的属性并不会发生变形        4. 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

 示例:

1 class Foo: 2     __x=111 #_Foo__x = 111 3     def __init__(self,m,n): 4         self.__m=m # self._Foo__m=m 5         self.n=n 6  7     def __func(self): #_Foo__func 8         print('Foo.func') 9 10     def func1(self):11         print(self.__m) #self._Foo__m12         print(self.__x) #self._Foo__x13 14 print(Foo.__dict__)15 # Foo.__x  报错,属性被隐藏,找不带属性16 # Foo.__func17 # print(Foo._Foo__x)18 # print(Foo._Foo__func)
obj=Foo(10,20) print(obj.__dict__)#{'_Foo__m': 10, 'n': 20} print(obj.n)#20 # print(obj.__m)#报错,找不到 print(obj._Foo__m)#10 obj.func1()#10,111,通过调用内部的方法,内部方法可以访问被封装的数据

容易犯错:

#要区分没有被封装的类中的属性查找class Foo:    def __f1(self): #_Foo__f1        print('Foo.f1')    def f2(self):        print('Foo.f2')        self.__f1() #self._Foo__f1class Bar(Foo):    def __f1(self): #_Bar__f1        print('Bar.f1')obj=Bar()obj.f2()#Foo.f2  Foo.f1 #封装之后在检测语法的时候会进行语法变形。属性查找按照变形之后的名字

封装函数属性的真实意图:隔离复杂度

class ATM:    def __card(self):        print('插卡')    def __auth(self):        print('用户认证')    def __input(self):        print('输入取款金额')    def __print_bill(self):        print('打印账单')    def __take_money(self):        print('取款')    def withdraw(self):        self.__card()        self.__auth()        self.__input()        self.__print_bill()        self.__take_money()a=ATM()a.withdraw()#讲取款的复杂流程封装为一个简单的步骤

 -------

class People:    def __init__(self,name,age):        self.__name=name        self.__age=age    def tell_info(self):        print('
' %(self.__name,self.__age)) def set_info(self,new_name,new_age): if type(new_name) is not str: print('名字必须是str类型傻叉') return if type(new_age) is not int: print('年龄必须是int类型傻叉') return self.__name=new_name self.__age=new_age print('
' % (self.__name, self.__age)) def clear_info(self): del self.__name del self.__ageobj=People('egon',18)obj.tell_info()#通过一个功能直接完成要做的事obj.set_info('alex',78)

property装饰器:

 

将功能掩盖为一个属性

'''BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)成人的BMI数值:过轻:低于18.5正常:18.5-23.9过重:24-27肥胖:28-32非常肥胖, 高于32  体质指数(BMI)=体重(kg)÷身高^2(m)  EX:70kg÷(1.75×1.75)=22.86'''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 ** 2)obj=People('egon',70,1.82)obj.height=1.85print(obj.bmi)#bmi在类中属于一个功能,property将其装饰成一个属性

property的用法:查,改,删

1 class People: 2     def __init__(self,name): 3         self.__name=name 4  5     @property 6     def name(self):#查 7         return '
' %self.__name 8 9 @name.setter10 def name(self,new_name):#改11 if type(new_name) is not str:12 print('名字必须是str类型')13 return14 self.__name=new_name15 16 @name.deleter17 def name(self):#删18 del self.__name19 20 obj=People('egon')21 # 查22 print(obj.name)23 # 改24 obj.name='alex'25 print(obj.name)26 # 删27 del obj.name28 print(obj.__dict__)
View Code

 --------------

1 class People: 2     def __init__(self,name): 3         self.__name=name 4     # 查 5     def xxx_name(self): 6         return '
' %self.__name 7 # 改 8 def yyy_name(self,new_name): 9 if type(new_name) is not str:10 print('名字必须是str类型')11 return12 self.__name=new_name13 # 删14 def zzz_name(self):15 del self.__name16 # 必须按照查,改,删的顺序17 name=property(xxx_name,yyy_name,zzz_name)18 19 obj=People('egon')20 print(obj.name)#
21 22 obj.name=12323 print(obj.name)#名字必须是str类型24 25 del obj.name26 print(obj.__dict__)#{}
旧写法,不清晰,不采用

多态:

1. 什么是多态    同一种事物的多种形态2. 为何要用多态    多态性:指的是可以在不用考虑对象具体类型的前提下而直接使用对象下的方法3. 如何用多态

多态示例:

1 import abc 2 class Animal(metaclass=abc.ABCMeta): 3     # 抽象方法 4     @abc.abstractmethod 5     def speak(self): 6         pass 7 # Animal() # 这里父类不能实例化,因为父类本身就是用来制定标准的 8 class People(Animal): 9     def speak(self):10         print('say hello')11     # def jiao(self):12     #     print('say hello')13 class Dog(Animal):14     def speak(self):15         print('汪汪汪')16 class Pig(Animal):17     def speak(self):18         print('哼哼哼')19 20 peo=People()21 dog1=Dog()22 pig1=Pig()23 24 peo.speak()25 dog1.speak()26 pig1.speak()

代码转换:

''.__len__()[].__len__()len([1,2,3]) #[1,2,3].__len__()
1 #方式一 2 peo=People() 3 dog1=Dog() 4 pig1=Pig() 5  6 peo.speak() 7 dog1.speak() 8 pig1.speak() 9 #方式二10 def speak(animal):11     animal.speak()12 13 speak(peo)14 speak(dog1)15 speak(pig1)
转换

Linux系统任何操作都是基于文件(均是对文件的读写操作):

1 class Memory: 2     def read(self): 3         print('mem read') 5     def write(self): 6         print('mem write') 7  8 class Disk: 9     def read(self):10         print('disk read')12     def write(self):13         print('disk write')14 15 class Cpu:16     def read(self):17         print('cpu read')19     def write(self):20         print('cpu write')21 22 obj1=Memory()23 obj2=Disk()24 obj3=Cpu()25 26 obj1.read()27 obj2.read()28 obj3.read()

转载于:https://www.cnblogs.com/xuechengeng/p/9843159.html

你可能感兴趣的文章