python面向对象之 封装(Day25)

封装:

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

好处: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()

四.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 math
class 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.1592653589793
62.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_price

obj = 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()
时间: 2024-10-07 09:54:45

python面向对象之 封装(Day25)的相关文章

Python面向对象编程-封装

1引言 你点击了桌面上的Chrome图标,一个浏览器窗口出现了,输入网址就可以在Internet世界愉快玩耍.这一切是怎么实现的呢?Chromium这个多进程的程序是如何启动各个进程的呢?浏览器主进程(界面进程)启动了哪些线程?如何启动的呢?这些问题一直萦绕在心头,一起来看看源代码吧.本文主要针对Chromium for Mac的源代码,其它操作系统大同小异. 2背景知识 浏览器作为一个应用程序,是以进程的形式运行在操作系统上的.首先,Chromium是一个多进程的应用程序,我们需要了解Chro

python面向对象编程 -- 封装、继承(python3.5)

面向对象编程三要素:封装.继承和多态.本文主要看和封装.继承相关的概念:在python中多态的概念比较模糊,本文不做讨论. 1 封装 封装:将数据和操作组装到一起,对外只暴露一些接口供类外部或子类访问,隐藏数据和操作的实现细节. 在其他面向对象语言,比如java中,属性访问控制一般有三种状态:private.protectd.public.python中没有什么东西是完全不可见的,没有任何机制可以强制性的隐藏数据.所以在python中不存在真正的只能在对象内部访问的属性.一个被大多数的pytho

Python面向对象特性 - 封装

类中的私有属性 私有属性包括私有变量和私有方法,在 Python 中,在变量名或者方法名前面加上双下划线,这个属性就成为了类的私有属性.? class Person: def __init__(self, name, age): self.__name = name self.__age = age def __fun(self): print(self.__class__) def say(self): self.__fun() # 自动转换为 调用 _Person__fun 方法 print

python—面向对象的封装

封装 私有属性 class Teacher: __identifier = 'Teacher' #私有静态属性 def __init__(self,name,pwd) self.name = name self.__pwd = pwd #私有属性 内部使用,外部不能使用 def pwd(self): print(self.__pwd) alex = Teacher('alex','3714') alex.pwd() class Teacher: __identifier = 'Teacher'

oldboy 21th day. I love Python. 面向对象之封装, 多态, 继承 三大特性

一, 主要内容: 接口类:( 只是在工作中, 书写的一种规范.) 抽象类: 用处: 在工作中, 如果你要是规定几个类, 必须有一样的方法, 你要是抽象类. 封装: 1, 将一些属性或者方法 (一些有用的信息) 放置在一个空间中. 2, 私有成员的封装:私有静态变量, 私有属性, 私有方法 特点: 在变量前+__双下划线, 并且在类外面,子类访问私有变量,私有方法 是访问不到的. 因为私有成员,在运行时, 都会变成: _类名__变量名 所以你在类的外部,或者派生类中都不可访问. 有些方法, 变量,

Python面向对象之封装

类class继承(单继承.多继承) 类方法@classmethod修饰实例方法def fn(self)静态方法@staticmethod修饰 代码区: class people: # 定义基本属性 name=''; age=0; # 定义私有属性,类的外部无法访问 __weight=0; def __init__(self, n, a, w): self.name = n; self.age=a; self.weight=w; def speak(self): print('%s is %s y

Python面向对象之类的封装、继承与多态

Python面向对象中类的三大特性,即封装.继承与多态,同时也是所有语言在面向对象编程中的重要特性,下面用实际的代码部分针对每一种特性做出说明. 一.封装 顾名思义,封装即把我们想要的内容封装到某个地方,因此在这里记录两个问题,一是如何封装.二是如何调用封装的内容. 1.封装数据 class Company:     def __init__(self, dept, leader):         self.dept = dept         self.leader = leader   

python之面向对象之封装

今天我们终于进入了面向对象,今天做一下面向的封装的总结 #面向对象的封装 #这里定义了一个类,名称为Role,object是所有类的父类 class Role(object): #这里是定义实例的属性,这个实例的属性分别有name,role,wepon,life_value,如果我们通过类Role去创建一个实例的时候,就必须传递这几个参数 #需要说的时候,这里的属性是实例的属性,而不是类的属性,具体关于类的属性,我们在后面介绍 def __init__(self,name,role,wepon,

Python 面向对象(创建类和对象,面向对象的三大特性是指:封装、继承和多态,多态性)

概念:                                                                                                                                                     ·        面向过程:根据业务逻辑从上到下写垒代码 ·        函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 ·        面向对象:对函数进行分类和封装,