自学Python5.7-面向对象三大基本特征_封装
自学Python之路-Python基础+模块+面向对象
自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django
自学Python5.7-面向对象三大基本特征_封装
一、封装
1.1 封装概念
广义上面向对象的封装 :代码的保护,面向对象的思想本身就是一种封装,只让自己的对象调用自己的方法。
狭义上的封装:面向对象的三大基本特征之一,隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的好处:
- 将变化隔离;
- 便于使用;
- 提高复用性;
- 提高安全性;
封装原则:
- 将不需要对外提供的内容都隐藏起来;
- 把属性都隐藏,提供公共方法对其访问。
class Person:
def __init__(self,name,passwd):
self.name = name
self.passwd = passwd
carlos = Person("carlos","carlos7628")
print(carlos.passwd) # 打印出carlos的密码

1.2 私有属性
1.2.1 私有属性,在外部调用不到
# 若不想别人查看carlos的密码
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏属性,----私有属性
carlos = Person("carlos","carlos7628")
print(carlos.__passwd)

1.2.2 私有属性,使用一种方法可以在外部调用(通常不使用)
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏方法
carlos = Person("carlos","carlos7628")
print(carlos.__dict__) # 查看属性里面都有什么

此时查看到密码的真实属性是“_Person__passwd'”, 再来print一下:
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏方法
carlos = Person("carlos","carlos7628")
print(carlos._Person__passwd) # _类的名字__属性的名字,就能查看到私有属性的内容

1.2.3 私有属性,只要在类的内部使用私有属性,就会自动的转换成带上_类名
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏方法 ,
def get_pwd(self):
return self.__passwd #只要在类的内部使用私有属性,就会自动的转换成带上_类名。 就是_Person__passwd
carlos = Person("carlos","carlos7628")
print(carlos._Person__passwd)
print(carlos.get_pwd())

1.2.4 只要在类的内部使用私有属性,就会自动的转换成带上_类名,就是_Person__passwd。但是在类的外部不是的。
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏方法
def get_pwd(self):
print(self.__dict__)
return self.__passwd #只要在类的内部使用私有属性,就会自动的转换成带上_类名
carlos = Person("carlos","carlos7628")
print(carlos._Person__passwd)
carlos.__high = 181
print(carlos.get_pwd())
print(carlos.__high)

举例:
# 定一个房子类, 计算面积
class Room:
def __init__(self,name,length,width):
self.name = name
self.__length = length #私有属性
self.__width = width #私有属性
def area(self):
return self.__length * self.__width
Tong = Room('Tong',2,1)
print(Tong.area())

现在有个问题,如果更改name,使用方法如下:
class Room:
def __init__(self,name,length,width):
self.name = name
self.__length = length
self.__width = width
def area(self):
return self.__length * self.__width
Tong = Room('Tong',2,1)
print(Tong.area())
Tong.name = "Carlos"
print(Tong.name)

最好的解决办法如下,name采用私有属性。 (对私有属性的保护,不可以随便更改名字name)
class Room:
def __init__(self,name,length,width):
self.__name = name
self.__length = length
self.__width = width
def get_name(self):
return self.__name
def set_name(self,newName):
if type(newName) is str and newName.isdigit() == False: # 非数字的字符串
self.__name = newName
else:
print('不合法的姓名')
def area(self):
return self.__length * self.__width
Tong = Room('Tong',12,6)
print(Tong.area()) # 打印tong房子的面积
Tong.set_name("carlos") # 设置名字为carlos
print(Tong.get_name())
Tong.set_name("2") # 设置了非法的名字2
print(Tong.get_name())

1.2.5 父类的私有属性不能被子类调用
# 父类的私有属性不能被子类调用
class Foo:
__key = '123' # _Foo__key 静态私有属性 class Son(Foo):
print(Foo.__key) # _Son__key

1.3 私有方法
class Person:
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd #加上"__",隐藏方法
def __get_pwd(self): #私有方法
return self.__passwd #只要在类的内部使用私有属性,就会自动的转换成带上_类名
def login(self): # 正常的方法调用私有的方法
self.__get_pwd()
1.4 总结
- # 所有的私有 都是在变量的左边加上双下划綫
- 对象的私有属性
- 类中的私有方法
- 类中的静态私有属性
- # 所有的私有的 都不能在类的外部使用
- # 采用私有概念的场景:①隐藏起一个属性 ,不想让类的外部调用;②我想保护这个属性,不想让属性随意被改变;③我想保护这个属性,不被子类继承
二、property内置函数
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值。
举例1: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('carlos',75,1.85)
print(p1.bmi) # @Property直接调用属性bmi====== 没有Property调用方法bmi()

举例2: 圆的面积和周长
from math import pi
class Circle:
def __init__(self,r):
self.r = r
def permeter(self):
return 2*pi*self.r
def area(self):
return self.r**2*pi
c1 = Circle(5)
print(c1.permeter()) #圆的周长
print(c1.area()) #圆的面积

from math import pi
class Circle:
def __init__(self,r):
self.r = r
@property
def permeter(self):
return 2*pi*self.r
@property
def area(self):
return self.r**2*pi
c1 = Circle(5)
print(c1.permeter) #圆的周长,可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c1.area) #圆的面积

注意:此时的特性area和perimeter不能被赋值。
from math import pi
class Circle:
def __init__(self,r):
self.r = r
@property
def permeter(self):
return 2*pi*self.r
@property
def area(self):
return self.r**2*pi
c1 = Circle(5)
c.area=3 #为特性area赋值
此时特性area和perimeter不能被赋值

为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。
面向对象的封装有三种方式:
- 【public】这种其实就是不封装,是对外公开的
- 【protected】这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
- 【private】这种封装对谁都不公开
python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现。
class Foo:
def __init__(self,val):
self.__NAME=val #将所有的数据属性都隐藏起来 @property
def name(self):
return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置) @name.setter
def name(self,value):
if not isinstance(value,str): #在设定值之前进行类型检查
raise TypeError('%s must be str' %value)
self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME @name.deleter
def name(self):
raise TypeError('Can not delete') f=Foo('egon')
print(f.name)

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

一个静态属性property本质就是实现了get,set,delete三种方法。
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊') @AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

实际超市促销的例子:
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) Classmethod_Demo.func()
四、staticmethod内置函数
class Staticmethod_Demo():
role = 'dog' @staticmethod
def func():
print("当普通方法用") Staticmethod_Demo.func()
.....
自学Python5.7-面向对象三大基本特征_封装的更多相关文章
- 自学Python5.6-面向对象三大基本特征_多态
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- 自学Python5.5-面向对象三大基本特征_继承
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- [Java入门笔记] 面向对象三大特征之:封装
了解封装 什么是封装? 在Java的面向对象程序设计中,有三大基本特征:封装.继承和多态.首先我们先来看看封装: 在Java的面对对象程序设计中,封装(Encapsulation)是指一种将函数功能实 ...
- 面向对象的基本特征:封装(接口 、struct、枚举、委托、匿名函数) 继承,多态。
如何理解面向对象的基本特征:封装 我们通过接口 .struct.枚举.委托.泛型.匿名函数的去理解封装 接口 .struct.枚举.委托.泛型.匿名函数有什么区别?我们通过这些IL探究真相,案例如下: ...
- Java 基础入门随笔(7) JavaSE版——面向对象定义、特征:封装、构造函数
面向对象 面向过程:对于面向过程思想,强调的是过程(动作). 面向对象:对于面向对象思想,强调的是对象(实体). 特点: 1,面向对象就是一种常见的思想.符合人们的思考习惯.2,面向对象的出现,将复杂 ...
- Java修炼——面向对象的三大特征_封装的使用
封装的作用含义:程序设计追求"高内聚,低耦合" 1.提高代码的安全性 2.提高代码的复用性 3."高内聚":封装细节,便于修改内部代码,提高可 维护性 4.&q ...
- C#面向对象三大特性之一:封装
面向对象的三大特性:封装.继承.多态. 1.封装概念 封装:每个对象都包含有它能进行操作的所有信息,这个特性称为封装.这样的方法包含在类中,通过类的实例来实现. 2.封装的优点 A.良好的封装能够减少 ...
- PHP面向对象三大特性之一:封装
面向对象的三大特性:封装.继承.多态 1.封装 封装的目的:让类更加安全,做法是不让外界直接访问类的成员 具体做法:1.成员变为私有:访问修饰符(public.private.protected) ...
- OOP面向对象 三大特征 继承封装多态
OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...
随机推荐
- notepad++ 插件说明(一)
notepad++插件说明(一) 1.xml插件安装 下载地址:https://sourceforge.net/projects/npp-plugins/files/XML%20Tools/Xml%2 ...
- ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - Data truncation: Incorrect datetime value: '' for column 'pubdate' at row 1
之前的Connector/J版本是:mysql-connector-java-5.0.4-bin.jar 后来换成mysql-connector-java-5.1.45-bin.jar,问题解决 20 ...
- python安装二进制k8s 1.11.0 一个master、一个node 查看node节点是主机名---apiserver无法启动,后来改了脚本应该可以
一.脚本说明: 本实验中master.node.etcd都是单体. 安装顺序为:先安装test1节点主要组件,然后开始安装test2节点,最后回头把test1节点加入集群中,这样做目的是理解以后扩容都 ...
- k8s1.11.0安装、一个master、一个node、查看node名称是主机名、node是扩容进来的、带cadvisor监控服务
一个master.一个node.查看node节点是主机名 # 安装顺序:先在test1 上安装完必要组件后,就开始在 test2 上单独安装node组件,实现node功能,再返回来配置test1加入集 ...
- Python的Multiprocessing多进程实例
最近在拜读RBG大神的faster-rcnn源码时发现他用了多进程去分阶段处理神经网络,原因如下: # ------------------------------------------------ ...
- 网络实验 04-利用三层交换机实现VLAN间路由
利用三层交换机实现VLAN间路由 一.实验目标 掌握交换机Tag VLAN 的配置 掌握三层交换机基本配置方法 掌握三层交换机VLAN路由的配置方法 通过三层交换机实现VLAN间相互通信 二.实验背景 ...
- ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE、personal/File、ShapeFile、CAD数据、影像图、影像数据集)
ArcEngine 可以接受多种数据源.在开发过程中我们使用了如下几种数据源 1.企业数据库(SDE) 企业数据库需要使用SDE来管理,所以需要使用SDE的Workspace来表示连接.在AE接口中, ...
- Linux文件权限码
权限 二进制值 八进制值 描述 --- 000 0 没有任何权限 --x 001 1 只有执行权限 -w- 010 2 只有写入权限 -wx 011 3 有写入和执行权限 r-- 100 4 只有读取 ...
- Pytorch修改ResNet模型全连接层进行直接训练
之前在用预训练的ResNet的模型进行迁移训练时,是固定除最后一层的前面层权重,然后把全连接层输出改为自己需要的数目,进行最后一层的训练,那么现在假如想要只是把 最后一层的输出改一下,不需要加载前面层 ...
- PhpMyAdmin提示未加密
新版本的PhpMyAdmin 增强了安全性,需要在配置文件设置一个短语密码.否则进入之后会有“配置文件现在需要一个短语密码.”的红色警叹提示. 解决方法: .将 phpMyAdmin/librarie ...