概要:

    组合

    封装

    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. TableML-GUI篇(C# 编译/解析 Excel/CSV工具)

    项目情况 本文接上篇TableML Excel编译/解析工具,本文主要介绍GUI工具的使用,及配置项,如果你想了解此工具更加详细的说明,请阅读上篇文章. 项目地址:https://github.com ...

  2. Linux Mysql数据库安全配置

    Linux  Mysql数据库安全配置 目录: 1.修改mysql管理员账号root的密码(2种方法) 2.修改mysql管理员账号root 3.mysql管理员root账号密码遗忘解决办法(2种方法 ...

  3. 英语口语练习系列-C03-常用问句

    连接到英语口语系列总分类 连接到上一章抱怨 枫桥夜泊 How are you doing?你好吗? 美国人见面时候最常用的打招呼方式: "Hey! How are you doing?&qu ...

  4. FutureTask并发详解,通俗易懂

    最近做项目,使用到了FutureTask和主线程并发,应用到实际中还是挺实用的,特在此总结一下. 有不对之处,忘各位多多指出. package com.demo; import java.util.c ...

  5. Node+express实现后台服务接口

    一.准备工作 创建代码目录,依次执行以下操作 1.(若没有安装过)安装node 2.npm init(package.json) 3.安装express(请求)npm install express ...

  6. Docker(3):Dockerfile配置详解

    FROM  : 指定base镜像 MAINTAINER :设置镜像的作者,可以是任意的字符串 COPY :将文件从build context 复制到镜像   COPY 支持两种形式:COPY src ...

  7. 日志切割之Logrotate

    1.关于日志切割 日志文件包含了关于系统中发生的事件的有用信息,在排障过程中或者系统性能分析时经常被用到.对于忙碌的服务器,日志文件大小会增长极快,服务器会很快消耗磁盘空间,这成了个问题.除此之外,处 ...

  8. 一位月薪1.2w的北漂程序员真实生活!

    “ 每个人都有一条生活道路.千万人,千万条,各不相同,各有特点.但是并不是好人都有一条好路,坏人都有一坏路.有的时候却恰恰相反.这虽然不是历史的必然,但却是客观社会存在的.今天咱们说的这部书是发生在当 ...

  9. First ServiceStack Service

    博客1:ServiceStack Web Service 创建与调用简单示列 博客2:Hbuilder+vs2017 web api开发app 官方文档:servicestack docs 1.手动下 ...

  10. 双字节验证:vue输入框中英文字数长度验证

    export default { data() { let validcodeName=(rule,value,callback)=>{ //替换双字节汉字,为aa,限制输入框长度: if(va ...