博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python面向对象之 封装(Day25)
阅读量:6181 次
发布时间:2019-06-21

本文共 4266 字,大约阅读时间需要 14 分钟。

封装:

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

好处:1.将变化隔离

   2.便于使用

   3.提高复用性

   4.提高安全性

封装原则:

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

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

二.私有变量和私有方法

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

2.1 私有变量

#其实这仅仅这是一种变形操作#类中所有双下划线开头的名称如__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,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

2.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()
View Code

四.property属性

1. 什么是property呢?

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

#@property把一个类中的方法 伪装成属性#obj.func()#obj.func  -->属性#因为属性不能被修改#@funcname.setter#obj.func = new_value 调用的是被@funcname.setter装饰器装饰的方法#被@property装饰的方法名必须和被@funcname.setter装饰的方法同名#@funcname.deleter#在执行del obj.func 的时候会调用被这个装饰器装饰的方法(同名)

 

例一: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例一
测试成年人身体健康标准
class People:    def __init__(self,name,weight,height):        self.name=name        self.weight=weight        self.height=height    @property    def bmi(self):        return self.weight / (self.height**2)p1=People('egon',75,1.85)print(p1.bmi)
import mathclass Circle:    def __init__(self,radius): #圆的半径radius        self.radius=radius    @property    def area(self):        return math.pi * self.radius**2 #计算面积    @property    def perimeter(self):        return 2*math.pi*self.radius #计算周长c=Circle(10)print(c.radius)print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值print(c.perimeter) #同上'''输出结果:314.159265358979362.83185307179586'''例二:圆的周长和面积
圆的周长和面积
#注意:此时的特性area和perimeter不能被赋值c.area=3 #为特性area赋值'''抛出异常:AttributeError: can't set attribute'''

2. 超市打折实例:

class Goods:    def __init__(self):        # 原价        self.original_price = 100        # 折扣        self.discount = 0.8    @property    def price(self):        # 实际价格 = 原价 * 折扣        new_price = self.original_price * self.discount        return new_price    @price.setter    def price(self, value):        self.original_price = value    @price.deleter    def price(self):        del self.original_priceobj = Goods()obj.price         # 获取商品价格obj.price = 200   # 修改商品原价print(obj.price)del obj.price     # 删除商品原价

classmethod

class Classmethod_Demo():    role = 'dog'    @classmethod    def func(cls):        print(cls.role)c = Classmethod_Demo()c.func()

 

staticmethod

class Staticmethod_Demo():    role = 'dog'    @staticmethod    def func():        print("当普通方法用")c = Staticmethod_Demo()c.func()

 

转载于:https://www.cnblogs.com/shaojiafeng/p/7365387.html

你可能感兴趣的文章
支持metro style app 的框架已经出来了
查看>>
windows 10 自适应布局
查看>>
mybatis insertUseGeneratedKeys
查看>>
Python的安装和详细配置(转)
查看>>
java实现电脑远程控制完整源代码(转)
查看>>
RepositoryClassLoader.java
查看>>
[python]什么是生成器
查看>>
解决Autofac MVC 自动注入在 Areas拆分到不同dll下的注入失败问题
查看>>
[angularjs] angularjs系列笔记(六)http
查看>>
[Go] golang的用途和windows搭建环境
查看>>
SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
查看>>
java基础编程一
查看>>
select获取选中的option(包含value和text,重点是text怎么获取)
查看>>
使用C#创建windows服务续之使用Topshelf优化Windows服务
查看>>
java:transient是什么,有什么作用
查看>>
转载文章
查看>>
flex 弹性盒子模型一些案例.html
查看>>
文档注释和显示图片
查看>>
请简述以下两个for 循环的优缺点
查看>>
服务端程序设计和实现总结 【转】
查看>>