《Python》 面向对象三大特性之多态、封装

一、多态

  1、什么是多态?

    一个类表现出的多种状态:通过继承来实现的

    在Java中的表现:在一个函数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,那么这些类型应该有一个父类,这个父类是所有子类对象的类型。

    在Python中:函数的参数不需要指定数据类型,所以我们也不需要通过继承的形式来统一一组类的类型,换句话说:所有的对象其实都是object类型,所有在Python当中处处是多态。

# 多态指的是一类事物有多种形态

# 动物有多种形态:人,狗,猪

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(self):
        print(‘say wangwang‘)

class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print(‘say aoao‘)

  2、多态性

    什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)

    多态性是指在不考虑实例类型的情况下使用实例

# 在面向对象方法中一般是这样表述多态性:
# 向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
# 也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

# 比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同

  3、鸭子类型

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

    len()   # str  list  tuple  dict  set  range  对于len函数来说,这些都是鸭子类型

    index()  # str  list  tuple  对于index函数来说,这些都是鸭子类型

    print()   # 对于print来说所有的对象都是鸭子类型

    不是明确的通过继承实现的多态,而是通过一个模糊的概念来判断这个函数能不能接受这个类型的参数

二、封装

  概念:隐藏对象的属性和实现细节,仅对外提供公共访问方式。

  好处

    1、将变化隔离;

    2、便于使用;

    3、提高复用性;

    4、提高安全性;

  原则

    1、将不需要对外提供的内容都隐藏起来;

    2、把属性都隐藏,提供公共方法对其访问。

  广义上的封装:(把属性函数都放到类里)

    class  类名:

      def 方法1(self):pass

      def 方法2(self):pass

    是为了只有这个类的对象才能使用定义在类中的方法

  狭义上的封装:(定义私有成员)

    把一个属性或方法藏在类中

    class Goods:

      __discount = 0   # 私有的静态变量

      print(__discount)

    print(Goods.__discount)  # 在类的外部不能引用私有的静态变量

    类中的静态变量和方法名在程序加载的过程中就已经执行完了,不需要等待调用

    在这个类加载完成之前,Goods这个名字还没有出现在内存空间中

    私有的静态属性可以在类的内部使用,用来隐藏某个变量的值

  类中的私有成员:

    1、私有的静态属性

    2、私有的对象属性

    3、私有的方法

  为什么要定义一个私有变量?

    1、我不想让你看到这个值

    2、我不想让你修改这个值

    3、我想让你在修改这个值的时候有一些限制:保证了数据的安全

    4、有些方法或属性不希望被子类继承

  私有变量和私有方法:

    在Python中用双下划线开头的方式将属性隐藏起来(设置成私有的)   

#其实这仅仅这是一种变形操作
#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

class A:
    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X=10 #变形为self._A__X
    def __foo(self): #变形为_A__foo
        print(‘from A‘)
    def bar(self):
        self.__foo() #只有在类内部才可以通过__foo的形式访问到.

#A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形  

  这种自动变形的特点:

    1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果

    2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

    3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

  

  这种变形需要注意的问题是:

    1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形

    

  在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

#正常情况
>>> class A:
...     def fa(self):
...         print(‘from A‘)
...     def test(self):
...         self.fa()
...
>>> class B(A):
...     def fa(self):
...         print(‘from B‘)
...
>>> b=B()
>>> b.test()
from B

#把fa定义成私有的,即__fa
>>> class A:
...     def __fa(self): #在定义时就变形为_A__fa
...         print(‘from A‘)
...     def test(self):
...         self.__fa() #只会与自己所在的类为准,即调用_A__fa
...
>>> class B(A):
...     def __fa(self):
...         print(‘from B‘)
...
>>> b=B()
>>> b.test()
from A

  封装与扩展性

    封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

#类的设计者
class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width
        self.__length=length
        self.__high=high
    def tell_area(self): #对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
        return self.__width * self.__length

#使用者
>>> r1=Room(‘卧室‘,‘egon‘,20,20,20)
>>> r1.tell_area() #使用者调用接口tell_area

#类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width
        self.__length=length
        self.__high=high
    def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
        return self.__width * self.__length * self.__high

#对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
>>> r1.tell_area()

原文地址:https://www.cnblogs.com/zyling/p/12641032.html

时间: 2024-07-30 10:56:12

《Python》 面向对象三大特性之多态、封装的相关文章

面向对象编程(十四)——面向对象三大特性之多态②

面向对象最核心的机制——动态绑定,也叫多态. 通过下面的例子理解动态绑定,即多态 1 package javastudy.summary; 2 3 class Animal { 4 /** 5 * 声明一个私有的成员变量name. 6 */ 7 private String name; 8 9 /** 10 * 在Animal类自定义的构造方法 11 * @param name 12 */ 13 Animal(String name) { 14 this.name = name; 15 } 16

python面向对象三大特性

面向对象的三大特性: 封装.继承和多态 一.封装 封装,顾名思义就是将内容封装到某个地方,以后可以直接调用被封装到某处的内容. - 将内容封装到某处 - 从某处调用被封装的内容 第一步,将内容封装到某处: class Foo: def __init__(self,name,age): self.name=name self.age=age obj1=Foo('梅西','31') obj2=Foo('C罗','33') print(obj1.name,obj1.age) print(obj2.na

Java中面向对象三大特性之——多态

多态的概述:  多态是继封装.继承之后,面向对象的第三大特性. 生活中,比如跑的动作,小猫.小狗和大象,跑起来是不一样的.再比如飞的动作,昆虫.鸟类和飞机,飞起来也是不一样的.可见,同一行为,通过不同的事物,可以体现出来的不同的形态.多态,描述的就是这样的状态. 多态的条件 1.继承 2.方法的重写 (为了让多态有意义) 3.父类的引用指向子类的对象 多态的体现 父类类型 变量名 = new 子类对象: 变量名.方法名(); 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译

【华为云技术分享】Python 面向对象三大特征之多态

[摘要] 面向对象的三大特性多态相关知识. 多态 1.多态 多态指的是一类事物有多种形态 动物有多种形态:人,狗,猪 1 import abc 2 class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 3 @abc.abstractmethod 4 def talk(self): 5 pass 6 7 class People(Animal): #动物的形态之一:人 8 def talk(self): 9 print('say hello') 10 11

Python面向对象三大特性之封装

面向函数的编程和面向对象编程对比 vim day7-2.py #!/usr/bin/python # -*- coding:utf-8 -*- def Bar(): print 'Bar' def Hello(name): print 'I am %s' %name class Foo: def Bar(self): print 'Bar' def Hello(self,name): print 'I am %s' %name Bar() Hello('liuyueming') obj = Fo

python面向对象三大特性之继承、多态

继承 什么是继承          所谓继承指提供了同一类对象共性的处理方法,子类继承父类共性的东西. 这样有利于代码的复用性,即子类拥有父类的方法.通过继承创建的新类称为"子类"或"派生类",被继承的类称为"基类"."父类"或"超类". 继承可以想象成什么是什么的关系 python中类的继承分为:单继承和多继承 class Parent1: # 父类1 pass class Parent2: #父类2 p

python面向对象三大特性-多态

import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' with open('filaname') as f: pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass class

[黑马程序员]Objective-C 面向对象三大特性之多态

什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作.简单地说就是:允许将子类类型的指针赋值给父类类型的指针. 简单示例 #import <Foundation/Foundation.h> @interface Animal : NSO

4月28日 面向对象三大特性之多态

---恢复内容开始--- <?php //多态 //概念:当父类引用指向子类实例的时候,由于子类对父类函数进行了重写,导致我们在使用该引用去调用相应的方法表现出的不同 //条件: //1.必须有继承 //2.子类必须对父类的方法进行重写 class Ren { public $name; public $sex; function say() { echo "hello"; } } class China extends Ren { function Say() { echo &