面向对象之组合、封装、多态性、鸭子类型

一、组合

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)
conclusion:

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

二、封装

1. 什么是封装
装指的是把属性装进一个容器
封指的是隐藏的意思,但是这种隐藏式对外不对内的

2. 为何要封装
封装不是单纯意义的隐藏
封装数据属性的目的:将数据属性封装起来,类 外部的使用就无法直接操作该数据属性了
需要类 内部开一个接口给使用者,类的设计者可以在接口之上附加任意逻辑,从而严格
控制使用者对属性的操作
封装函数属性的目的:隔离复杂度

3. 如何封装?
只需要在属性前加上__开头,该属性就会被隐藏起来,该隐藏具备的特点:
1. 只是一种语法意义上的变形,即__开头的属性会在检测语法时发生变形_类名__属性名
2. 这种隐藏式对外不对内的,因为在类内部检测语法时所有的代码统一都发生的变形
3. 这种变形只在检测语法时发生一次,在类定义之后新增的__开头的属性并不会发生变形
4. 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

class Foo:
    __x=111 #_Foo__x
    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__)
# Foo.__x
# Foo.__func
# print(Foo._Foo__x)
# print(Foo._Foo__func)

封装数据属性的真实意图:

1、封装数据:

class Peoole:
    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

    def clear_info(self):
        del self.name

  people1 = Peoole(‘wwl‘,18)
  people2 = Peoole(‘wlw‘,20)
  #查
  people1.tell_info()
  people2.tell_info()
  #改
  people1.set_info(‘leilei‘,30)
  print(people1.tell_info())
  #删
  people2.clear_info()

2、封装方法:目的是隔离复杂度

# 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()
取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做隔离了复杂度,同时也提升了安全性。*了解装饰器property的用法1、什么是property?property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值2、为何用?将一个类的函数定义成特性以后,对象再去使用的时候obj.bim,根本无法察觉自己的bim执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则eg:
‘‘‘
例一: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)

3、怎么用

新写法:

# 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=123
# # 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)

# obj.name=123
# print(obj.name)

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()
 def speak(animal):
    animal.speak()

speak(peo)
speak(dog1)
speak(pig1)

四、鸭子类型

Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子

python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象

也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。

#二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
class TxtFile:
    def read(self):
        pass

    def write(self):
        pass

class DiskFile:
    def read(self):
        pass
    def write(self):
        pass
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()

其实我们一直在享受着多态性带来的好处,比如Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下

#str,list,tuple都是序列类型
s=str(‘hello‘)
l=list([1,2,3])
t=tuple((4,5,6))

#我们可以在不考虑三者类型的前提下使用s,l,t
s.__len__()
l.__len__()
t.__len__()

len(s)
len(l)
len(t)

原文地址:https://www.cnblogs.com/wanlei/p/9846041.html

时间: 2024-10-09 11:15:23

面向对象之组合、封装、多态性、鸭子类型的相关文章

组合||抽象类||多态||鸭子类型

组合 软件重用的重要方式除了继承之外还有另外一种方式,即:组合 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 class People: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class Renwen(People): def __init__(self,name,age,sex,weapon): super().__init__(name,age,se

面向对象:多态(多态性)、封装(隐藏属性)、绑定方法与非绑定方法

多态: 多态指的是一类事物有多种形态:比如 动物有多种形态:人.狗.猪 如下代码: import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): #动物的形态之二:狗 def talk(se

16 Apr 18 封装的property 多态 鸭子类型 classmethod和staticmethod

16 Apr 18 一.      封装的property BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) 首先需要明确.bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能都会立即计算一个值,但很明显人的bmi值听起来更像一个名词而非

面向对象的三大特性 鸭子类型 类的约束 super的深度剖析

1.三大特性 封装 ? 把很多数据封装到?个对象中. 把固定功能的代码封装到?个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了?个很?B的函数. 那这个也可以被称为封装. 在?向对象思想中. 是把?些看似?关紧要的内容组合到?起统?进?存储和使?. 这就是封装. 继承 ? ?类可以?动拥有?类中除了私有属性外的其他所有内容. 说?了, ??可以随便?爹的东?. 但是朋友们, ?定要认清楚?个事情. 必须先有爹, 后有??. 顺序不能乱, 在py

封装之property,多态,鸭子类型,classmethod与staticmethod

一.封装之Property prooerty是一种特殊的属性,访问时他会执行一段功能(函数)然后返回 '''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__(se

023_接口类,抽象类,多态,鸭子类型,封装

1,接口类 1 class Wechat(): 2 def pay(self,money): 3 print('已经用微信支付了%s元'%money) 4 class Alipay(): 5 def pay(self,money): 6 print('已经用支付宝支付了%s元' % money) 7 wechat = Wechat() 8 ali = Alipay() 9 # wechat.pay(100) 10 # ali.pay(200) 11 #将上面两句用下面的替换, 12 def pa

Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)

Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装: ? ? ? ? ? ?将一些东西封装到一个地方,你还可以取出来 ? ? ? ? ? ?类设置静态属性, 设置一些方法 或者 对象, 对象可以在其对象封装一些属性 多态: ? ? ? ? ? ?python默认支持多态, 多态指的是一种事务具有多种形态 ? ? ? ? ? ?1.多态可以增加代码的灵活度: ? ? ? ? ? ?2.以继承和重写父类方法为前提: ?

Python:面向对象的“开闭原则”和“鸭子类型”

开闭原则 开闭原则(OCP)是面向对象设计中"可复用设计"的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段. 1988年,勃兰特·梅耶(Bertrand Meyer)在他的著作<面向对象软件构造(Object Oriented Software Construction)>中提出了开闭原则,它的原文是这样:"Software entities should be open for extension,but closed fo

封装- --接口,抽象, 鸭子类型 #22

知识点1.封装 1.封装.py 1 '''''' 2 """ 3 封装: 4 """ 5 6 """ 7 1.什么是封装? 8 就是将复杂的丑陋的,隐私的细节,隐藏到内部,对外提供简单的使用接口 9 10 即:对外隐藏内部实现细节,并提供访问接口 11 """ 12 """ 13 2.为什么需要封装? 14 两个目的: 15 1.为了保证 关键数据的安全性