Python学习日记(二十六) 封装和几个装饰器函数
封装
广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见
私有属性
私有属性表示方式即在一个属性名前加上两个双下划线
class Fighter:
def __init__(self,name,hp,atk,speed):
self.name = name
self.__hp = hp #私有属性 变形成self._Fighter__hp
self.__atk = atk #私有属性 变形为self._Fighter__atk
self.__speed = speed #私有属性 变形为self._Fighter__speed
f1 = Fighter('AKK-18',1500,200,300)
print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300}
python的私有属性只是在代码的级别给加了一层密,不允许你直接去访问这些私有属性,像你去打印一个私有属性它的结果就是报错,或者你想尝试修改一个私有属性的时候,结果并不能修改成功
f1.__hp = 1000
print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300, '__hp': 1000}
因为上面的私有属性都已经变形成_类名__属性名的格式,我们这样写,相当于直接给self添加了一个新的'键名'__hp,所以在类的外部调用双下划线就不行
那如何访问我们的私有属性呢?我们可以看到上面的私有属性都被变形成了_类名__属性名的形式,那么我们可以这样去访问:
print(f1._Fighter__hp) #
print(f1._Fighter__atk) #
print(f1._Fighter__speed) #
但光这样走这样的捷径是不完美的,我们可以在类内部添加一个get_value函数来获得那些私有属性
class Fighter:
def __init__(self,name,hp,atk,speed):
self.name = name
self.__hp = hp #私有属性
self.__atk = atk #私有属性
self.__speed = speed #私有属性
def get_value(self):
return self.__hp,self.__atk,self.__speed #只要在类内部使用私有属性就会自动带上'_类名’
f1 = Fighter('AKK-18',1500,200,300)
print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300}
print(f1.get_value()) #(1500, 200, 300)
for i in f1.get_value():
print(i) #
#
#
在get_value中return的写法其实就是变形后再获取私有属性
def get_value(self):
return self._Fighter__hp,self._Fighter__atk,self._Fighter__speed
私有静态属性
class Fighter:
__id = 1234445 #私有静态属性
def __init__(self,name,hp,atk,speed):
self.name = name
self.__hp = hp #私有属性
self.__atk = atk #私有属性
self.__speed = speed #私有属性
def get_value(self): #获取内部私有属性方法
return self.__hp,self.__atk,self.__speed
def get_id(self):
return self.__id
f1 = Fighter('AKK-18',1500,200,300)
print(f1._Fighter__id) #
print(f1.get_id()) #
私有方法
class Fighter:
__id = 1234445 #私有静态属性
def __init__(self,name,hp,atk,speed):
self.name = name
self.__hp = hp #私有属性
self.__atk = atk #私有属性
self.__speed = speed #私有属性
def get_value(self): #获取内部私有属性方法
return self.__hp,self.__atk,self.__speed
def get_id(self): #获取静态属性id的方法
return self.__id
def __shoot(self): #私有方法
print('Shooting!')
def get_shoot(self): #获取私有方法shoot
self.__shoot()
#self._Fighter__shoot()
f1 = Fighter('AKK-18',1500,200,300)
f1.get_shoot() #Shooting!
修改私有属性
class Room:
def __init__(self,name,length,width):
self.__name = name
self.__length = length
self.__width = width
def Area(self):
return self.__width*self.__length
def get_name(self): #获取这个私有名字的方法
return self.__name
def set_name(self,new_name):#重新设定这个房号
if type(new_name) is str and new_name.isdigit() == True:
self.__name = new_name
else:
print('错误的命名方式!')
r1 = Room('',15,20)
print(r1.Area()) #
print(r1.get_name()) #
r1.set_name('asd')
print(r1.__dict__) #{'_Room__name': '1103', '_Room__length': 15, '_Room__width': 20}
print(r1.get_name()) #
几个装饰器
1.@property
我们在用面向对象的思想去写一个圆经常会把它的周长和面积当成一个方法,然而我们知道方法是一个获取的动作,而不是一个属性名词,所以要想处理这种将一个方法伪装成为一个属性就要用到@property,这样这个方法它就看起来像是一个属性了
from math import pi as P
class Circle:
def __init__(self,r):
self.r = r
def Perimeter(self):
return 2*P*self.r
def Area(self):
return P*self.r**2
c = Circle(5)
print(c.Area()) #78.53981633974483
print(c.Perimeter()) #31.41592653589793
改进:
from math import pi as P
class Circle:
def __init__(self,r):
self.r = r
@property
def Perimeter(self): #这里在self的后面不能传任何参数
return 2*P*self.r
@property
def Area(self): #这里在self的后面不能传任何参数
return P*self.r**2
c = Circle(5)
print(c.Perimeter) #31.41592653589793
print(c.Area) #78.53981633974483
BMI问题:BMI指数(BMI)=体重(kg)÷身高^2(m)
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
非常肥胖:>32
class BMI:
def __init__(self,height,weight):
self.__height = height
self.__weight = weight
@property
def __bmi(self): #把计算bmi的方法伪装成一个属性
return self.__weight/self.__height**2 def get_bmi(self): #BMI判断
if self.__bmi > 32:
print('非常肥胖!')
elif 24 <= self.__bmi <= 27:
print('过重!')
elif 18.5 <= self.__bmi <= 23.9:
print('正常!')
else:
print('过轻!') b = BMI(1.75,72)
b.get_bmi() #正常!
在@property的前提下用@setter来修改属性
class Person:
def __init__(self,name,):
self.__name = name
@property
def name(self):
return self.__name + ' hello!'
@name.setter
def name(self,new_name):
self.__name = new_name
p1 = Person('Jogn')
print(p1.name) #Jogn hello!
#p1._Person__name = 'Maria' #Maria hello!
print(p1.name) #Maria hello!
在@property的前提下用@deleter来删除属性
class Person:
def __init__(self,name,):
self.__name = name
@property
def name(self):
return self.__name + ' hello!'
@name.deleter
def name(self):
del self.name
p1 = Person('Jogn')
print(p1.name) #Jogn hello!
del p1.name #del p1.name它在这里的作用是指向deleter下面这个方法,再去做这个方法的功能
print(p1.name) #找不到这个名字了
我们可以看一下在这里的del关键字它起到了什么的作用
class Person:
def __init__(self,name,):
self.__name = name
@property
def name(self):
return self.__name + ' hello!'
@name.deleter
def name(self):
print('执行了这个方法!')
p1 = Person('Jogn')
print(p1.name) #Jogn hello!
del p1.name #del p1.name它在这里的作用是指向deleter下面这个方法,再去做这个方法的功能
print(p1.name) #Jogn hello!
因为第二个name里面没有关于修改名字的操作所以在最后p1.name还能打印出原来的名字
2.@classmethod
当这个方法只涉及到静态属性的时候,就应该使用classmethod来装饰这个方法
class Goods:
__discount = 0.8 #折扣
def __init__(self,name,price):
self.name = name
self.__price = price
@property
def price(self):
return self.__price * self.__discount
@classmethod
def change_discount(cls,new_discount): #cls为类名
cls.__discount = new_discount #修改折扣
apple = Goods('苹果',4)
print(apple.price) #3.2
Goods.change_discount(0.5)
print(apple.price) #2.0
3.@staticmethod
在完全面向对象的程序中,如果一个函数和对象没有关系那么就用staticmethod把这个函数变成一个静态方法
class Login:
def __init__(self,name,password):
self.name = name
self.password = password
@staticmethod
def get_n_psw(): #没有默认参数就像函数一样
username = input('请输入用户名:')
psw = input('请输入密码:')
Login(username,psw) #请输入用户名:asdd
return username,psw #请输入密码:4564648
print(Login.get_n_psw()) #('asdd', '4564648')
Python学习日记(二十六) 封装和几个装饰器函数的更多相关文章
- Python学习札记(二十六) 函数式编程7 修饰器
修饰器 NOTE 1.函数对象有一个__name__属性,可以拿到函数的名字: #!/usr/bin/env python3 def now(): print('2017/2/19') def mai ...
- Python学习(二十六)—— Django基础一
转载自:http://www.cnblogs.com/liwenzhou/p/8258992.html 一.Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的 ...
- Python学习日记(三十六) Mysql数据库篇 四
MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...
- Python学习日记(二十八) hashlib模块、configparse模块、logging模块
hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...
- Python学习日记(二十二) 初识面向对象
引子 假设我们要开发一个关于飞机大战的游戏,那么游戏的里面就会有两个角色,分别是属于玩家操控的战机和敌方的战机,并且两个战机都有不同的技能或攻击方式,现在我们用自己目前所学的去写出下面的这些代码: d ...
- Python学习日记(二十九) 网络编程
早期的计算机通信需要有一个中间件,A要给B传东西,A必须要把信息传给中间件,B再把从中间件中拿到信息 由于不同机器之间需要通信就产生了网络 软件开发的架构 1.C/S架构 服务器-客户机,即Clien ...
- Python学习日记(二十五) 接口类、抽象类、多态
接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...
- Python学习日记(二十四) 继承
继承 什么是继承?就是一个派生类(derived class)继承基类(base class)的字段和方法.一个类可以被多个类继承;在python中,一个类可以继承多个类. 父类可以称为基类和超类,而 ...
- python学习(二十六) 字典
# 访问字典car = {'make':'bmw', 'model':'550i', 'year':2016}print(car)print(car['make']) # 添加元素d = {}d['o ...
随机推荐
- [转]TrueType(TTF)字体文件裁剪(支持简体中文,繁体中文TTF字体裁剪)
原文入口: TTF字体文件裁剪(支持简体中文,繁体中文TTF字体裁剪) 对于TrueType(TTF)字体格式的介绍可以看: https://www.cnblogs.com/slysky/p/1131 ...
- LeetCode 110. Balanced Binary Tree(判断平衡二叉树)
Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...
- Android Studio Error:Execution failed for task ':app:compileDebugJavaWithJavac' 根本解决方法
造成这种异常的原因有很多.具体的还是要去终端编译,查看到底是什么地方出错了,然后具体问题具体分析. 终端进入项目的根目录,然后输入命令 gradlew compileDebugJavaWithJava ...
- Ubuntu16.04安装Superset
Superset 是Airbnb 开源的大数据可视化平台 其支持的datasource https://superset.incubator.apache.org/index.html?highlig ...
- EasyNVR摄像机网页无插件直播方案H5前端构建之:通道内部搜索功能的实现方案与代码
EasyNVR网页摄像机直播方案 EasyNVR是一款拥有完整.自主.可控知识产权,同时又能够具备软硬一体功能的安防互联网化流媒体服务器,能够通过简单的网络摄像机通道配置,将传统监控行业里面的高清网络 ...
- 从原生Android 跳转到hbuilder项目
原文地址:https://blog.csdn.net/pentablet/article/details/80277157 前段时间做项目,需要把别人做的hbuilder项目,添加到自己的app中,找 ...
- 22 Oracle数据库基础入门
1.Oracle数据库的介绍 ORACLE 数据库系统是美国ORACLE 公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或 B/S 体 ...
- Flume和 Sqoop
Sqoop简介 Sqoop是一种旨在有效地在Apache Hadoop和诸如关系数据库等结构化数据存储之间传输大量数据的工具 原理: 将导入或导出命令翻译成Mapreduce程序来实现. 在翻译出的M ...
- 如何获取文件夹下所有文件名称(windows)
1. win+R -> cmd 打开dos命令窗口 2. 打开需获取文件名的位置 3. 获取名称 命令格式:dir /b >> 文件目标盘符:\文件夹位置(可省略)\目标名称.目标后 ...
- python3 安装 pyinstaller 时报错的解决办法
如上图所示,在安装的过程中发现是所关联的一个 future模块安装失败,庵后我有单独安装了一下这个future,发现还是失败 然后在网上寻找解决办法,最后找到了这个指令,pip install fut ...