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 ...
随机推荐
- 查找算法(7)--Hash search--哈希查找
1.哈希查找 (1)什么是哈希表(Hash) 我们使用一个下标范围比较大的数组来存储元素.可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用 ...
- promise简单实现
function isFunction(fn){ return Object.prototype.toString.call(fn) === '[object Function]'; } let ST ...
- Docker使用 - 容器
查看容器 命令:docker ps [options] options有: -a:查看所有容器,包含不在运行中的(不带-a参数,是只显示运行中的容器) -q:只显示容器ID -s:多加一列来显示总 ...
- CentOS7下Redis的安装与使用
一.安装过程 1.准备工作(安装gcc依赖) # yum install gcc-c++ 2.下载并解压源码包 # cd /usr/local # wget http://download.redis ...
- 安装 python 爬虫框架 Scrapy
官方安装说明文档:https://doc.scrapy.org/en/latest/intro/install.html#installing-scrapy 一.scrapy 需要以下依赖 二.一般来 ...
- replace into 详解 update mysql
转replace 与 update 区分本文主要对比一下 Sqlite 中的 replace 语句和 update 语句 . 在本例中使用如下数据库表: 图1 该表的表名为student, 存储学 ...
- Python unittest(PyUnit)单元测试框架
PyUnit(unittest) 是 Python 自带的单元测试框架,用于编写和运行可重复的测试.PyUnit 是 xUnit 体系的一个成员,xUnit 是众多测试框架的总称,PyUnit 主要用 ...
- 定时杀死mysql中sleep的进程
#!/bin/sh date=`date +%Y%m%d\[%H:%M:%S]` n=`mysqladmin -uroot -p** processlist | grep -i sleep | wc ...
- idea springboot启动报SLF4J:Failed to load class “org.slf4j.impl.StaticLoggerBinder”
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artif ...
- Git 删除所有历史提交记录方法
Git 删除所有历史提交记录方法 切换分支 git checkout --orphan latest_branch 添加所有文件 git add -A 提交更改 git commit -am &quo ...