1.封装方法

如何封装:给方法名称前面加上双下划线

    # ATM 的取款功能
# 1.插入银行卡 2.输入密码 3.选择取款金额 4.取款 class ATM:
def __insert_card(self):
print("插入银行卡...")
def __input_pwd(self):
print("输入密码...")
def __select_money(self):
print("选择取款金额...")
def withdraw(self):
self.__insert_card()
self.__input_pwd()
self.__select_money()
print("取款成功!....") atm = ATM()
atm.withdraw() # 外部调用这个简单的接口 就能完成一系列复杂的操作
# atm.select_money() #直接调用内部的方法 是没有意义的无法完成整个功能 # 当然用户按照流程一一调用也可以完成功能 但是太麻烦
# atm.insert_card()
# atm.input_pwd()
# atm.select_money() 封装方法的好处:
1.提高安全性
2.隔离复杂度(将复杂的内容隔离到内部,外部只留下简单的接口,对于使用者,难度降低)

什么时候用封装

当一个类中某些属性或方法,不应该让外界直接访问,那就应该将其进行封装

封装的实现原理

本质上python并没有强行限制你的访问,而是通过语法转换来实现的封装

class Person:
def __init__(self,name,sex,age,idCard):
self.name = name
self.sex = sex
self.__age = age
self.__idCard = idCard def get_idCard(self):
return self.__idCard def __test(self):
pass print("aaaaaaaaaa") p = Person("比尔盖茨","男",20,"322323232332332") # print(p.__idCard)
p.__idCard = "XXXXXX"
print(p.__idCard) print(p.get_idCard()) print(p.__dict__)
print(Person.__dict__) p.__xxxxxxxxxxxx = 1 print(p.__dict__) 1.通过__dict__可以发现,私有的属性名称前自动加上了_类名,python就是通过这样的转换方式来实现封装
2.只有在类的内部的双下划线才会被自动转换,并且这个转换过程只执行一次,在类丁已完成后,在添加的双下划线开头的
3.父类中私有的方法,子类中无法使用

子类无法覆盖父类的私有方法

class  A:
def f(self):
self.__f1() #_A__f1 def __f1(self):
print("A __f1") class B(A):
def __f1(self): # _B__f1
print("B __f1") def f2(self):
self.f() b = B()
b.f2() # 之所以无法覆盖 是因为 子类和父类中的私有方法 名称必然不相同 所以无法覆盖 子类的方法一定子类独有的 因为名称不同 class A:
__age = 10 # 绕过封装的限制直接访问 这是毫无意义的
print(A._A__age)

使用property可以将一个方法伪装成一个属性

当一些属性的值不是固定的,而是通过计算得来的时候,我们必须为这个属性增加方法,才能完成计算,但是一旦使用方法后,该属性的访问,就变成了方法调用,很明显与其他的属性访问方式不同,这样会给使用者造成迷惑
所有需要将这个方法伪装成普通属性,这就用到了Property property可以将方法伪装成属性,利用这个特点,我们也可以将其使用到封装中
之前没有这个装饰器我们需要为私有的属性,提供两个方法,但是这样一来访问私有属性时的方式就发生了变化
这时候可以使用property来进行伪装,使得访问私有属性与访问普通属性的方式一致
另外 property还提供了 setter(用于修改属性的值) 和 deleter(删除属性的值) # BIM案例:
class Person:
def __init__(self,name,weight,height):
self.name = name
self.weight = weight
self.height = height
# self.bmi = weight/(height*height)
# def bmi(self):
# return self.weight / (self.height * self.height)
@property
def bmi(self):
return self.weight / (self.height * self.height) p = Person("尔晴",50,1.5)
# print(p.bmi)
# p.weight = 90
# print(p.bmi) # 现在 虽然可以实现需求 但是我们把一个属性变成了一个行为 这是不合理的
# print(p.bmi())
# p.weight = 90
# print(p.bmi()) # 使用property装饰器 可以将一个方法伪装成一个属性
print(p.bmi)
p.height += 0.2
print(p.bmi) class Student:
def __init__(self,name,sex,idCard):
self.name = name
self.sex = sex
self.__idCard = idCard def get_idCard(self):
return self.__idCard def set_idCard(self,new_id):
self.__idCard = new_id @property # 需要掌握
def idCard(self):
return self.__idCard @idCard.setter #了解的
def idCard(self,new_id):
self.__idCard = new_id @idCard.deleter # 了解的
def idCard(self):
print("身份证属性被删除了.....")
del self.__idCard stu = Student("尔康","男","323254554554") # print(stu.get_idCard()) # stu.set_idCard("xxxx") print(stu.get_idCard()) # 使用装饰器前
print(stu.name) # 普通属性的访问 print(stu.idCard) # 使用装饰器后 stu.idCard = "aaaaaaa" # 使用装饰器后的修改操作 print(stu.idCard) del stu.idCard print(stu.__dict__)
print(Student.__dict__)

封装的特点

被隐藏的内容 在内部是可以直接访问,外部无法访问

2. 多态

什么是多态
多种状态,形态
生活中具备多种形态的事物,水(水蒸气,冰,液态水),奥特曼,数码宝贝
一种事物,具备多种形态或状态,就称之为多态
官方解释:不同对象,可以响应同一方法,并作出不同的行为,产生不同结果 如何实现多态?
让几个不同类拥有相同的父类,这样一来他们就具备了相同的方法,每个子类覆盖父类的方法
class Animal:
def eat(self):
print("动物在吃东西...")
def sleep(self):
print("动物在睡觉...")
def drink(self):
print("动物需要水.....") class Person(Animal):
def eat(self):
print("人吃粮食...") class Pig(Animal):
def eat(self):
print("猪吃饲料...") class Dog(Animal):
def eat(self):
print("狗吃骨头...") person = Person()
pig = Pig()
dog = Dog() person.eat()
pig.eat()
dog.eat() #假设你学习了C1驾照 意味着 所有C1类的汽车都能开 因为每种C1汽车的驾驶方式相同 # 当使用了多态之后 对象的使用者不需要关系这个对象具体的实现,只需要知道该对象属于哪个基类,就能直接使用它
# 如此扩展性变高了 class Phone:
def call(self):
print("手机就能打电话..") def send_msg(self):
print("手机能发短信..") class WindowsPhone(Phone):
def call(self):
print("拨号打电话..") def send_msg(self):
print("输入号码发短信..") class IPhone(Phone):
def call(self):
print("拨号打电话..") def send_msg(self):
print("输入号码发短信..") # 可以定义一个方法接受一个手机为参数 无论是是类型的手机 都可以被使用 def CALL(phone):
phone.call() wp = WindowsPhone()
ipx = IPhone() CALL(wp)
CALL(ipx) # 系统内置的方法有很多都体现了多态 print(len("abc"))
print(len([1,2,3,4,]))
print(len({"name":"123","sex":"man"})) print("abc".__len__())
print([1,2,3,4,].__len__())
print({"name":"123","sex":"man"}.__len__())
print(len({1,23,4,5}))

多态值abc模块

多态是多个类的对象拥有相同的方法,但是我们没有从语法严格要求说必须提供这些方法,子类完全可以不提供这些方法
#现在要做的就是 严格要求 子类必须实现父类声明的方法 import abc
#abc是abstract class ,是抽象类的缩写,抽象的意思是 不清晰 不具体 看不懂 不清晰不具体的类,就是抽象类 使用abc模块来限制子类的步骤
1.为类中指定元类为abc.ABCMeta
2.在相应的方法上加上abc.abstractmethod class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod
def eat(self):
pass @abc.abstractmethod
def drink(self):
pass class Cat(Animal):
def eat(self):
print("猫爱吃鱼肉...") def drink(self):
print("用舌头舔..") class Dog(Animal):
def eat(self):
print("狗爱吃骨头...")
def drink(self):
print("用舌头舔..") class Pig(Animal):
def eat(self):
print("猪 爱吃草...") def drink(self):
print("用嘴吸的..") p = Pig()
# p.eat() c = Cat()
# c.eat() # 多态的好处 完全不需要考虑得到的对象时声明类型 只要知道了其基类中的内容就能使用
def feeding(animal):
animal.eat()
animal.drink() feeding(c)
feeding(p)
# 多态中的基类 相当于(协议 标准 规范) 要求子类必须满足这些标准 多态练习 import abc # 电脑基类
class Computer(metaclass=abc.ABCMeta): @abc.abstractmethod
def open(self):
pass @abc.abstractmethod
def shutdown(self):
pass class DesktopComputer(Computer):
def open(self):
print("台式机正在启动....") def shutdown(self):
print("台式机正在关机....") class Worker:
def working(self,pc):
# 先开机
pc.open()
print("工作中.....")
pc.shutdown() w1 = Worker() dp = DesktopComputer() w1.working(dp) # 增加了笔记本电脑
class BookComputer(Computer): def open(self):
print("笔记本正在启动....") def shutdown(self):
print("笔记本正在关机....") bc = BookComputer()
w1.working(bc) class PadComputer(Computer):
def open(self):
print("平板正在启动....") def shutdown(self):
print("平板正在关机....") bc = PadComputer()
w1.working(bc)

3. 鸭子类型

python推崇简单的编程方式
鸭子类型,如果一个对象叫声像鸭子,走路也像鸭子,那就把它当成鸭子 对应到代码中,就是只要你的行为一样,那就把你当成一个类型来看 class Duck: def bark(self):
print("鸭子嘎嘎叫...") def run(self):
print("摇摇晃晃走....") class Chicken:
def bark(self):
print("鸡咯咯叫...") def run(self):
print("摇摇晃晃走....") def test(obj):
obj.bark()
obj.run() duck = Duck()
c = Chicken() test(duck)
test(c) 如果你足够自觉,你可以不适用abc模块,也不需要公共的基类,自觉地将方法名都写成一样,同样可以实现多态
这种方式称之为鸭子类型

day25 面向对象之多态和鸭子类型的更多相关文章

  1. python基础语法17 面向对象4 多态,抽象类,鸭子类型,绑定方法classmethod与staticmethod,isinstance与issubclass,反射

    多态 1.什么是多态? 多态指的是同一种类型的事物,不同的形态. 2.多态的目的: “多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字). 多 ...

  2. PythonI/O进阶学习笔记_3.1面向对象编程_python的多态和鸭子类型

    前言: 与第一篇的面向对象内容不同的是,第一篇中的面向对象更多的是与类.对象结合起来的概念粗浅理解,就是在编程历史中诞生的一种思想方法. 这篇的面向对象编程,更多落实到在语言设计实现中,是如何体现面向 ...

  3. Python面向对象04 /封装、多态、鸭子类型、类的约束、super

    Python面向对象04 /封装.多态.鸭子类型.类的约束.super 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 3. 鸭子类型 4. 类的 ...

  4. python 面向对象专题(四):封装、多态、鸭子类型、类的约束、super

    https://www.cnblogs.com/liubing8/p/11321099.html 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 ...

  5. 第7.3节 Python特色的面向对象设计:协议、多态及鸭子类型

    Python是一种多态语言,其表现特征是:对象方法的调用方只管方法是否可调用,不管对象是什么类型,从而屏蔽不同类型对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化. 一.    P ...

  6. 多态 与 鸭子类型 duck duck duck

    # --> ''' 多态 与 鸭子类型 --> 什么是多态 对象的多种状态,父类对象的多种 (子类对象) 状态 --> 什么是鸭子类型: 长的像就是 1.规定有什么属性及什么方法的对 ...

  7. Python面向对象----多态和鸭子类型

    1. C#中多态实现的条件是 继承, 重写以及父类指向子类. 但是在弱类型Python里面, 实现多态的条件就显得很简洁, 只需要在子类中实现父类相同名称的方法即可. 2. 鸭子类型的解释: 若一个类 ...

  8. 面向对象—多态、鸭子类型(Day21)

    编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...

  9. day25 面向对象继承,多态,

    这两天所学的都是面向对象,后面还有几天也是它,面向对象主要有三个大的模块,封装,继承,多态,(组合),昨天主要讲了面向对象的命名空间,还有组合的用法,今天是讲的继承还有继承里面所包括的钻石继承,以及多 ...

随机推荐

  1. 写了一个bug----使用已经被删除的内存

    #include <iostream> #include <stdio.h> #include <memory.h> using namespace std; ; ...

  2. 《汇编语言 基于x86处理器》第十章结构和宏部分的代码

    ▶ 书中第十章的程序,主要讲了结构与宏的使用 ● 代码,使用结构,对比是否对齐的性能差距 INCLUDE Irvine32.inc INCLUDE macros.inc structN STRUCT ...

  3. Linux将某目录授权给某组里的某用户

    chown -Rf 用户名:组名 目录

  4. workerman-todpole 执行流程(1)

    该系列文章主要是彻底扒一下 workerman todpole 游戏的实现原理. 提前打个预防针: 由于 Worker 类的静态属性和子类对象的混用(当前类的静态属性存放当前类对象,静态方法循环静态属 ...

  5. 使用MediaPlayer类和SurfaceView来播放视频

    MediaPlayer可以播放视频,只需需要SurfaceView的配合,SurfaceView主要用于显示MediaPlayer播放的视频流媒体的画面渲染. SurfaceView是配合MediaP ...

  6. python大法好——变量、常量、input()、数据类型、字符串、格式化输出、运算符、流程控制语句、进制、字符编码

    python基础知识 1.变量 变量:把程序运算的中间结果临时存到内存里,以备后面的代码可以继续调用. 作用:A.存储数据. B.标记数据. 变量的声明规则: A:变量名只能是字母,数字或下划线任意组 ...

  7. git fail to push some refs....

    出现错误的主要原因是github中的README.md文件不在本地代码目录中 可以通过如下命令进行代码合并[注:pull=fetch+merge] git pull --rebase origin m ...

  8. XML中的变量传值

    在action的java类中定义变量之后,在XML中获取该变量进行对应传值:: 在指定方法中获取XML配置文件的变量传值::

  9. Linux下Mongodb安装和启动配置 原

    1.安装 略 2.配置 01.mkdir /usr/local/mongodb/data 0.touch /usr/local/mongodb/logs 03.cd /usr/local/mongod ...

  10. js 引入外部文件之 script 标签

    在我的理解看来,html 就是一个单纯的管显示问题,js就是单纯的管动作问题,css就是单纯的管布局问题,这三个构成了一个网页 在HTML中,经常会用到引入js 文件. 引入js的方法很简单: 1. ...