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. Docker: devicemapper fix for “device or resource busy” (EBUSY) Cannot start container

    受众:本文适用于熟悉码头工作的人员,并希望解决使用devicemapper存储/图形驱动程序时遇到的特定问题. 概述:虽然这不是专门用于设计师的问题,但是目前参与此驱动程序的技术人员会受到此影响. 使 ...

  2. 官方教程Stealth学习笔记(一)

    今天開始要更新官方教程stealth的学习笔记啦, 我将会记录和解说一个小游戏基本的流程和关键地方的技巧. 我会依照官方教程的顺序来更新.                                ...

  3. smarty模版使用php标签,如何获取模版变量

    smarty模版使用php标签,如何获取模版变量 in: 后端程序 已经assign一个模版变量$assign,由于要做特殊的循环输出,使用for循环,因此使用到了php标签,但是php语句和模版语句 ...

  4. 【机器学习详解】SMO算法剖析(转载)

    [机器学习详解]SMO算法剖析 转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/51227754 CSDN−勿在浮沙筑高台 本文力 ...

  5. Android下的数据存储与访问、权限

    弹出吐司 在onCreate中可以先获取控件对象 /data/data/程序的包名/          在这个目录下面进行文件的读写可能因为包名的改变而变得不可靠. this可以是Activity,也 ...

  6. 篇二、理解Android Studio的视图和目录分析,这个是转载

    看不清的话可以可以将图片在新窗口中打开,以原图的大小显示.   原文链接:http://blog.csdn.net/siyehuazhilian/article/details/42123563   ...

  7. ARM初学引导_转

    一直都在听说ARM有多么好,有多神奇,有多难学.故学它时都兴奋加恐惧.呵呵,我刚好用ARM也有一段时间了.写点东西给ARM的初学者,希望能起到帮助作用. 1,记住:ARM很简单,就如从51转换到PIC ...

  8. k8s集群容器监控

    硬件环境: 两台虚拟机, 10.10.20.203 部署docker.etcd.flannel.kube-apiserver.kube-controller-manager.kube-schedule ...

  9. sublime使用技巧(4)-- 其他技巧【持续更新】

    命令模式 1.切换语言格式,ctrl + shirt + p 2.简化操作 ctrl + shirt + p 输入 snippet:function 自动生成function的基本结构!tab键 移动 ...

  10. ubuntu 下使用polipo转换HTTP代理

    ***默认是用Socks5协议的,对于Terminal的get,wget等走http协议的地方是无能为力的,所以需要转换成http代理,加强通用性,这里使用的转换方法是基于Polipo的. sudo ...