概要:

    组合

    封装

    property装饰器

    多态

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

组合:

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

演示:

 class Foo:
aaa=1111
def __init__(self,x,y):
self.x=x
self.y=y def func1(self):
print('Foo内的功能') class Bar:
bbb=2222
def __init__(self, m, n):
self.m = m
self.n = n def func2(self):
print('Bar内的功能') obj1=Foo(10,20)
obj2=Bar(30,40) obj1.xxx=obj2
#此行代码就是组合的过程
print(obj1.x,obj1.y,obj1.aaa,obj1.func1)
print(obj1.xxx.m,obj1.xxx.n,obj1.xxx.bbb,obj1.xxx.func2)#组合之后就可以利用obj1.xxx来调用对象obj2所有的功能

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

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

 class OldboyPeople:
school = 'Oldboy'
# 如果有一个管理员的话,也被迫添加了课程相关的属性
def __init__(self, name, age, gender, course_name, course_price, course_period):
self.name = name
self.age = age
self.gender = gender
self.course_name = course_name
self.course_price = course_price
self.course_period = course_period class OldboyStudent(OldboyPeople):
def choose_course(self):
print('%s is choosing course' % self.name) class OldboyTeacher(OldboyPeople):
def __init__(self, name, age, gender, level, salary, course_name, course_price, course_period):
OldboyPeople.__init__(self, name, age, gender)
self.level = level
self.salary = salary def score(self, stu, num):
stu.num = num
print('老师%s给学生%s打分%s' % (self.name, stu.name, num))
#对于课程名,价格,周期等不需要重复传入,会增加内存占用
stu1 = OldboyStudent('egon', 18, 'male', 'Python开发', 3000, '5mons')
stu2 = OldboyStudent('kevin', 38, 'male', 'Python开发', 3000, '5mons')
#定义课程函数
def tell_course(obj):
print('课程名:<%s> 价钱:[%s] 周期:[%s]' % (obj.course_name, obj.course_price, obj.course_period)) tell_course(stu1)
tell_course(stu2)

第二步

 class OldboyPeople:
school = 'Oldboy'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender class OldboyStudent(OldboyPeople):
def choose_course(self):
print('%s is choosing course' %self.name) class OldboyTeacher(OldboyPeople):
def __init__(self, name, age, gender,level,salary):
OldboyPeople.__init__(self, name, age, gender)
self.level=level
self.salary=salary def score(self,stu,num):
stu.num=num
print('老师%s给学生%s打分%s' %(self.name,stu.name,num))
#定义课程类
class Course:
def __init__(self,course_name,course_price,course_period):
self.course_name=course_name
self.course_price=course_price
self.course_period=course_period
def tell_course(self):
print('课程名:<%s> 价钱:[%s] 周期:[%s]' % (self.course_name, self.course_price, self.course_period)) python_obj=Course('python开发',3000,'5mons')
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. 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

示例:

 class Foo:
__x=111 #_Foo__x = 111
def __init__(self,m,n):
self.__m=m # self._Foo__m=m
self.n=n def __func(self): #_Foo__func
print('Foo.func') def func1(self):
print(self.__m) #self._Foo__m
print(self.__x) #self._Foo__x print(Foo.__dict__)
15 # Foo.__x  报错,属性被隐藏,找不带属性
16 # Foo.__func
17 # 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__f1 class 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('<name:%s age:%s>' %(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('<name:%s age:%s>' % (self.__name, self.__age))
def clear_info(self):
del self.__name
del self.__age obj=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.85 print(obj.bmi)#bmi在类中属于一个功能,property将其装饰成一个属性

property的用法:查,改,删

 class People:
def __init__(self,name):
self.__name=name @property
def name(self):#查
return '<name:%s>' %self.__name @name.setter
def name(self,new_name):#改
if type(new_name) is not str:
print('名字必须是str类型')
return
self.__name=new_name @name.deleter
def name(self):#删
del self.__name obj=People('egon')
# 查
print(obj.name)
# 改
obj.name='alex'
print(obj.name)
# 删
del obj.name
print(obj.__dict__)

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

 class People:
def __init__(self,name):
self.__name=name
# 查
def xxx_name(self):
return '<name:%s>' %self.__name
# 改
def yyy_name(self,new_name):
if type(new_name) is not str:
print('名字必须是str类型')
return
self.__name=new_name
# 删
def zzz_name(self):
del self.__name
# 必须按照查,改,删的顺序
name=property(xxx_name,yyy_name,zzz_name) obj=People('egon')
print(obj.name)#<name:egon> obj.name=123
print(obj.name)#名字必须是str类型 del obj.name
print(obj.__dict__)#{}

旧写法,不清晰,不采用

多态:

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

多态示例:

 import abc
class Animal(metaclass=abc.ABCMeta):
# 抽象方法
@abc.abstractmethod
def speak(self):
pass
# Animal() # 这里父类不能实例化,因为父类本身就是用来制定标准的
class People(Animal):
def speak(self):
print('say hello')
# def jiao(self):
# print('say hello')
class Dog(Animal):
def speak(self):
print('汪汪汪')
class Pig(Animal):
def speak(self):
print('哼哼哼') peo=People()
dog1=Dog()
pig1=Pig() peo.speak()
dog1.speak()
pig1.speak()

代码转换:

''.__len__()
[].__len__()
len([1,2,3]) #[1,2,3].__len__()
 #方式一
peo=People()
dog1=Dog()
pig1=Pig() peo.speak()
dog1.speak()
pig1.speak()
#方式二
def speak(animal):
animal.speak() speak(peo)
speak(dog1)
speak(pig1)

转换

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

 class Memory:
def read(self):
print('mem read')
def write(self):
print('mem write') class Disk:
def read(self):
print('disk read')
def write(self):
print('disk write') class Cpu:
def read(self):
print('cpu read')
def write(self):
print('cpu write') obj1=Memory()
obj2=Disk()
obj3=Cpu() obj1.read()
obj2.read()
obj3.read()

面向对象之组合、封装、多态、property装饰器的更多相关文章

  1. 面向对象之 组合 封装 多态 property 装饰器

    1.组合 什么是组合? 一个对象的属性是来自另一个类的对象,称之为组合 为什么要用组合 组合也是用来解决类与类代码冗余的问题 3.如何用组合 # obj1.xxx=obj2''''''# class ...

  2. PYTHON-组合 封装 多态 property装饰器

    # 组合'''软件重用的重要方式除了继承之外还有另外一种方式,即:组合组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之 ...

  3. 面向对象(三)——组合、多态、封装、property装饰器

    组合.多态.封装.property装饰器 一.组合 1.什么是组合 组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象 class Foo(): pass class Bar(): pas ...

  4. python面向对象:组合、封装、property装饰器、多态

    一.组合二.封装三.property装饰器四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 3. ...

  5. 组合,多态与多态性,封装以及property装饰器介绍

    一:组合: 什么是组合:组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象. 为何要用组合:通过为某一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合 ...

  6. python面向编程:类的组合、封装、property装饰器、多态

    一.组合 二.封装 三.propert装饰器 四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 ...

  7. 面向对象(三)--多态、封装、property装饰器

    一.多态与多态性 1.什么是多态 多态指的是同一种类/事物的不同形态 class Animal: def speak(self): pass class People(Animal): def spe ...

  8. 面向对象之封装 及@property装饰器使用

    目录 封装 1.封装的定义 2.封装的目的: 3.封装的三种方式 4.封装的优点 5.访问限制(封装) @property 装饰器 属性property底层实现 封装 1.封装的定义 将复杂的丑陋的, ...

  9. 初识面向对象-封装、property装饰器、staticmathod(静态的方法)、classmethod(类方法) (五)

    封装 # class Room:# def __init__(self,name,length,width):# self.__name = name# self.__length = length# ...

随机推荐

  1. 进程命令(tasklist)

    TaskList命令: // 描述: 显示本地或远程计算机上正在运行的进程列表信息. // 语法: tasklist [/s <computer> [ /u [<domain> ...

  2. Django contenttypes 组件

    contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...

  3. JavaScript-创建日志调试对象(面向对象实例)

    参考自http://www.2cto.com/kf/201312/261990.html IC.js文件 自己封装的js类库 /** * * @authors Your Name (you@examp ...

  4. 重写override

    不可重写私有方法. 不可重写非静态的方法,虽然编译器不会报错,但是得不到预期的结果. 可以通过重写的形式对父类的功能进行重新定义,比如:对功能进行修改或者进行升级时. class BaseAction ...

  5. c++11の死锁

    一.死锁的产生 两个mutex的时候,mutex1,mutex2 如果两把锁两个线程的顺序不一致,会造成相互等待释放资源,造成死锁 二.死锁的避免 1.是否需要两把以上的锁,如果不用两把锁,自然不会存 ...

  6. python基础-小练习

    三级菜单 要求: 打印省.市.县三级菜单 可返回上一级 可随时退出程序 购物车程序 要求: 用户名和密码存放于文件中,格式为:egon|egon123 启动程序后,先登录,登录成功则让用户输入工资,然 ...

  7. 正益工作能担起PaaS+SaaS的未来探索吗?

    没有竞争,行业没有未来.不参与竞争,企业没有未来.中国企业的类型纷繁复杂,也决定了企业的多样化需求.云计算和移动化的双重叠加,企业管理需要重新梳理,企业业务创新日益频繁,个性化需求日益突出,软件服务商 ...

  8. 理论篇-Java中一些零碎的知识点

    1. Java中length,length方法,size方法区别 length属性:用于获取数组长度. length方法:用于获取字符串长度. size方法:用于获取泛型集合有多少个元素. 2. is ...

  9. 深入理解Fabric环境搭建的详细过程

    博主之前的文章都是教大家怎么快速的搭建一个Fabric的环境,但是其中大量的工作都隐藏到了官方的脚本中,并不方便大家深入理解其中的过程,所以博主这里就将其中的过程一步步分解,方便大家! 前面的准备工作 ...

  10. Python第二天: 变量详解及变量赋值

    目录 什么是变量? 怎么写一个好的变量? 下划线命名法及驼峰命名法 结语 目录 此文章针对刚学Python的小白,若觉得对变量有很好的掌握,可以观看其他的文章 在这里, 我说一下我对变量的简单总结: ...