python 3 封装

从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小鱼,小虾,小王八,一起装进麻袋,然后把麻袋封上口子。照这种逻辑看,封装=‘隐藏’,这种理解是相当片面的。

先看如何隐藏

在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.变形的过程只在类的定义时放生一次,在定义后的赋值操作,不会变形

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

python并不会真的阻止你访问私有的属性,模块也遵循这种约定,如果模块名以单下划线开头,那么from module import *时不能被导入,但是你from module import _private_module依然是可以导入的其实很多时候你去调用一个模块的功能时会遇到单下划线开头的(socket._socket,sys._home,sys._clear_type_cache),这些都是私有的,原则上是供内部调用的。作为外部也可以用,只过写出代码比较傻了,python要想与其他编程语言一样,严格控制属性的访问权限,只能借助内置方法如__getattr__

#先看如何隐藏

class Foo:

    __N=111111 #_Foo__N

    def __init__(self,name):

        self.__Name=name #self._Foo__Name=name

    def __f1(self): #_Foo__f1

        print('f1')

    def f2(self):

        self.__f1() #self._Foo__f1()

f=Foo('egon')

# print(f.__N)

# f.__f1()

# f.__Name

f.f2() #通f

#这种隐藏需要注意的问题:

#1:这种隐藏只是一种语法上变形操作,并不会将属性真正隐藏起来

print(Foo.__dict__)

print(f.__dict__)

print(f._Foo__Name)

print(f._Foo__N)

#2:这种语法级别的变形,是在类定义阶段发生的,并且只在类定义阶段发生

Foo.__x=123123123123123123123123123123123123123123

print(Foo.__dict__)

print(Foo.__x)

f.__x=123123123

print(f.__dict__)

print(f.__x)

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

class Foo:

    def __f1(self): #_Foo__f1

        print('Foo.f1')

    def f2(self):

        self.__f1() #self._Foo_f1

class Bar(Foo):

    def __f1(self): #_Bar__f1

        print('Bar.f1')

b=Bar()

b.f2()

#封装不是单纯意义的隐藏

#1:封装数据属性:将属性隐藏起来,然后对外提供访问属性的接口,关键是我们在接口内定制一些控制逻辑从而严格控制使用对数据属性的使用

class People:

    def __init__(self,name,age):

        if not isinstance(name,str):

            raise TypeError('%s must be str' %name)

        if not isinstance(age,int):

            raise TypeError('%s must be int' %age)

        self.__Name=name

        self.__Age=age

    def tell_info(self):

        print('<名字:%s 年龄:%s>' %(self.__Name,self.__Age))

    def set_info(self,x,y):

        if not isinstance(x,str):

            raise TypeError('%s must be str' %x)

        if not isinstance(y,int):

            raise TypeError('%s must be int' %y)

        self.__Name=x

        self.__Age=y

p=People('egon',18)

p.tell_info()

# p.set_info('Egon','19')

p.set_info('Egon',19)

p.tell_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()
# _x=123

示例代码

python 3 封装的更多相关文章

  1. 将Python脚本封装成exe可执行文件 转

    将Python脚本封装成exe可执行文件 http://www.cnblogs.com/renzo/archive/2012/01/01/2309260.html  cx_freeze是用来将 Pyt ...

  2. python继承——封装

    python继承--封装 1 为什么要封装 封装数据的主要原因是:保护隐私 封装方法的主要原因是:隔离复杂度 2 封装分为两个层面 第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空 ...

  3. 【转】Python基础-封装与扩展、静态方法和类方法

    [转]Python基础-封装与扩展.静态方法和类方法 一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数 ...

  4. python面向对象-封装-property-接口-抽象-鸭子类型-03

    封装 什么是封装: # 将复杂的丑陋的隐私的细节隐藏到内部,对外提供简单的使用接口 或 # 对外隐藏内部实现细节,并提供访问的接口 为什么需要封装 1.为了保证关键数据的安全性 2.对外部隐藏内部的实 ...

  5. python学习笔记:安装boost python库以及使用boost.python库封装

    学习是一个累积的过程.在这个过程中,我们不仅要学习新的知识,还需要将以前学到的知识进行回顾总结. 前面讲述了Python使用ctypes直接调用动态库和使用Python的C语言API封装C函数, C+ ...

  6. python文件封装成*.exe

    python文件封装成*.exe文件(单文件和多文件) 环境:win10 64位 python3.7 原文: https://www.cnblogs.com/jackzz/p/9431923.html ...

  7. 第7.9节 案例详解:Python类封装

    上节介绍了Python中类的封装机制,本节结合一个具体例子进行详细说明. 我们定义一个Person类,其内部有姓名.年龄和类型三个实例变量,并定义了相关的存取方法: class Person():   ...

  8. python面向对象(封装,继承,多态)

    python面向对象(封装,继承,多态) 学习完本篇,你将会深入掌握 如何封装一个优雅的借口 python是如何实现继承 python的多态 封装 含义: 1.把对象的属性和方法结合成一个独立的单位, ...

  9. 利用PyInstaller将python代码封装成EXE(亲测可用)

    有些不能成功,有些不全的,下面总结一下,给自己以后看看.   1下载PyInstaller..去官网下载http://www.pyinstaller.org/(我下载的版本)   2不需要安装,解压即 ...

随机推荐

  1. 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)

    并发编程概述   前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...

  2. java之UDP(datagramsocket,datagramPacket)实例

    import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import ...

  3. Linux下安装jdk8的方法

    一.yum安装 只需要一条命令就可以安装jdk: yum install java--openjdk* -y 执行过这条命令无需配置,直接可以使用. 二.下载tar包安装 下载jdk8 登录网址:ht ...

  4. MySQL:习题(单表多条件查询二)

    Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 否 否 Sex 性 ...

  5. jquery的push()

    JavaScript push() 方法 JavaScript Array 对象 定义和用法 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. 语法 arrayObject.pus ...

  6. java多线程编码注意事项

    Sole purpose of using concurrency is to produce scalable and faster program. But always remember, sp ...

  7. APPLE ID随意转区到US或者HK.不需要信用卡

    看到论坛有封釉想去US 或者HK 的商店下载大陆商店没有的APP.(比如 Tumblr) 但是现在在手机上或者是网页管理apple id 更改地区,需要输入付款信息. 现在教大家利用旧版的icloud ...

  8. spring boot日志配置

    spring boot的application.properties提供了日志的配置,但我还是习惯于老的logback的使用方式.以下内容介绍如何在springboot中使用自定义的logback. ...

  9. flex弹性盒模型

    flex 意思是弹性布局,用来给盒模型提供最大的灵活度,指定容器中的项目为弹性布局,类似于float:left; 比float的好处是容器没有设置高度,会根据项目来自适应高度,我们都知道,设置floa ...

  10. SimpleAdapter的用法

    学习listView的时候,按照例子设定item的布局为系统提供的simple_list_item_single_choice.xml@frameworks/base/core/res/res/lay ...