Python__类的封装

python不依赖语言特性去封装数据,而是通过遵循一定的数据属性和函数属性的命名约定来达到封装的效果

 

约定一:任何一单下划线开头的名字都应该是内部的,私有的

#_*_coding:utf-8_*_
__author__ = 'Simon'

class People:
    __star=earth111111111111' 单下划线开头的就代表隐藏起来的
    __star1='
    __star2=__star3='
    def __init__(self,id,name,age,salary):
        print(----->',self.__star)
        self.id=id
        self.name=name
        self.age=age
        self.salary=salary

    def get_id(self):
        我是私有方法啊,我找到的id是[%s]' %self.id)

    访问函数
     get_star(self):
        print(self.)



p1=People(123123123123alex18)
 print(p1.__star)
print(People.__dict__print(p1._People__star)
#
# p1.get_star()
p1.get_star()

约定二:双下划线开头的名字

 

第三个层面的封装:

隐藏方式

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

其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形
#类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式:

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

A._A__N是可以访问到的,这种,在外部是无法通过__x这个名字访问到。

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

1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形,主要用来限制外部的直接访问。

2.变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形

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

正常情况
>>>  A:
...      fa(self):
...         )
...      test(self):
...         self.fa()
... 
>>>  B(A):
...     from B)
... 
>>> b=B()
>>> b.test()
from B
 

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

 

封装的意义

封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,然而定义属性的目的终归是要用,外部要想用类隐藏的属性,需要我们为其开辟接口,让外部能够间接地用到我们隐藏起来的属性,那这么做的意义何在???

 Teacher:
     self.__name=name
         self.__age=age
        self.set_info(name,age)

     tell_info(self):
        姓名:%s,年龄:%s' %(self.__name,1)">__age))
     set_info(self,1)">if not isinstance(name,str):
            raise TypeError(姓名必须是字符串类型)
         isinstance(age,int):
            年龄必须是整型)
        self.__name=name
        self.__age=age


t=Teacher(egon)
t.tell_info()

t.set_info()
t.tell_info()

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

取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做隔离了复杂度,同时也提升了安全性

 ATM:
    __card(self):
        插卡__auth用户认证__input输入取款金额__print_bill打印账单__take_money取款)

     withdraw(self):
        self.()
        self.()

a=ATM()
a.withdraw()

隔离复杂度的例子

什么是特性property

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

例一: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
 People:
    name
        self.weight=weight
        self.height=height
    @property
     bmi(self):
        return self.weight / (self.height**2)

p1=People(print(p1.bmi)

例二:圆的周长和面积 

import math
 Circle:
    __init__(self,radius): 圆的半径radius
        self.radius=radius

    @property
     area(self):
        return math.pi * self.radius**2 计算面积

    @property
     perimeter(self):
        return 2*math.pi*self.radius 计算周长

c=Circle(10(c.radius)
print(c.area) 可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) 同上
'''
输出结果:
314.1592653589793
62.83185307179586
'''

为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

除此之外,看下

ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现
 Foo:
    __NAME=val 将所有的数据属性都隐藏起来
 name(self):
        return self.__NAME obj.name访问的是self.__NAME(这也是真实值的存放位置)

    @name.setter
     name(self,value):
        not isinstance(value,str):  在设定值之前进行类型检查
            %s must be strvalue)
        self.__NAME=value 通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter
    Can not delete)

f=Foo((f.name)
 f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name 抛出异常'TypeError: Can not delete'

 

封装性与扩展性

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

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


使用者
>>> r1=Room(卧室)
>>> r1.tell_area() 使用者调用接口tell_area


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


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

 

原文地址:https://www.cnblogs.com/tracydzf

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Python中的函数(二) 在上一篇文章中提到了Python中函数的定义和使用,在这篇文章里我们来讨论下关于函数的一些更深的话题。在学习C语言函数的时候,遇到的问题主要有形参实参的区别、参数的传递和改变、变量的作用域。同样在Python中,关于对函数的理解和使用也存在这些问题。下面来逐一讲解。一.函
Python中的字符串 可能大多数人在学习C语言的时候,最先接触的数据类型就是字符串,因为大多教程都是以"Hello world"这个程序作为入门程序,这个程序中要打印的"Hello world"就是字符串。如果你做过自然语言处理方面的研究,并且用Python
Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。 类是对现实世界中一些事物的封装,
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定义和使用方法,这只体现了面向对象编程的三大特点之一:封装。下面就来了解一下另外两大特征:继承和多态。 在Python中,如果需要的话,可以让一个类去继承一个类,被继承的类称为父类或者超类、也可以称作基类,继承的类称为子类。并且Pytho
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非常熟悉,无论在哪门编程语言当中,函数(当然在某些语言里称作方法,意义是相同的)都扮演着至关重要的角色。今天就来了解一下Python中的函数用法。一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明
在windows下如何快速搭建web.py开发框架 用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不幸的是这位创建者于2013年自杀了。据说现在由
将Sublime Text 2搭建成一个好用的IDE 说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款编辑器了...
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include<math.h>"引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?在Python中
Python的基础语法 在对Python有了基础的认识之后,下面来了解一下Python的基础语法,看看它和C语言、java之间的基础语法差异。一.变量、表达式和语句 Python中的语句也称作命令,比如print "hello python"这就是一条语句。 表达式,顾名思义,是
Eclipse+PyDevʽjango+Mysql搭建Python web开发环境 Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看好的框架之一。下面就来讲讲如何搭建Django的开发环境。一.准备工作 需要下载的
在windows下安装配置Ulipad 今天推荐一款轻便的文本编辑器Ulipad,用来写一些小的Python脚本非常方便。 Ulipad下载地址: https://github.com/limodou/ulipad http://files.cnblogs.com/dolphin0520/u...
Python中的函数(三) 在前面两篇文章中已经探讨了函数的一些相关用法,下面一起来了解一下函数参数类型的问题。在C语言中,调用函数时必须依照函数定义时的参数个数以及类型来传递参数,否则将会发生错误,这个是严格进行规定的。然而在Python中函数参数定义和传递的方式相比而言就灵活多了。一.函数参数的
在Notepad++中搭配Python开发环境 Python在最近几年一度成为最流行的语言之一,不仅仅是因为它简洁明了,更在于它的功能之强大。它不仅能够完成一般脚本语言所能做的事情,还能很方便快捷地进行大规模的项目开发。在学习Python之前我们来看一下Python的历史由来,"Pytho
Python中的条件选择和循环语句 同C语言、Java一样,Python中也存在条件选择和循环语句,其风格和C语言、java的很类似,但是在写法和用法上还是有一些区别。今天就让我们一起来了解一下。一.条件选择语句 Python中条件选择语句的关键字为:if 、elif 、else这三个。其基本形式如
关于raw_input( )和sys.stdin.readline( )的区别 之前一直认为用raw_input( )和sys.stdin.readline( )来获取输入的效果完全相同,但是最近在写程序时有类似这样一段代码:import sysline = sys.stdin.readline()
初识Python 跟学习所有的编程语言一样,首先得了解这门语言的编程风格和最基础的语法。下面就让我们一起来了解一下Python的编程风格。1.逻辑行与物理行 在Python中有逻辑行和物理行这个概念,物理行是指在编辑器中实际看到的一行,逻辑行是指一条Python语句。在Python中提倡一个物理行只
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现。
1.经典迭代器 2.将Sentence中的__iter__改成生成器函数 改成生成器后用法不变,但更加简洁。 3.惰性实现 当列表比较大,占内存较大时,我们可以采用惰性实现,每次只读取一个元素到内存。 或者使用更简洁的生成器表达式 4.yield from itertools模块含有大量生成器函数可
本文介绍简单介绍socket的常用函数,并以python-kafka中的源码socketpair为例,来讲解python socket的运用
python实践中经常出现编码相关的异常,大多网上找资料而没有理解原理,导致一次次重复错误。本文对常用Unicode、UTF-8、GB2312编码的原理进行介绍,接着介绍了python字符类型unicode和str以及常见编解码错误UnicodeEncodeError和UnicodeDEcodeEr