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 ...
随机推荐
- 解决bootstrap-table表头filter-control select控件被遮挡显示不全的问题
[本文出自天外归云的博客园] 在使用bootstrap-table的extension——filter-control时(对应表格的data-filter-control="true&quo ...
- C++ vector使用实例
C++ vector #include <iostream> #include <vector> #include <string> #include <al ...
- jzy3D从入门到弃坑_4尝试使用jzy3D1.0画图失败
jzy3D从入门到弃坑_4 尝试使用jzy3D1.0画图失败 觉得有用的话,欢迎一起讨论相互学习~Follow Me 记录一下使用jzy3D1.0失败 究其原因在于 本人才疏学浅,对于JAVA ope ...
- SpringBoot小技巧:Jar包换War包
SpringBoot小技巧:Jar包换War包 情景 我们都知道springBoot中已经内置了tomcat,是不需要我们额外的配置tomcat服务器的,但是有时这也可能是我们的一个瓶颈,因为如果我们 ...
- mysq5.7 主主同步
db01 172.21.0.10 db02 172.21.0.14 一.安装数据库看上一遍博客 修改配置文件 db01 172.21.0.10 [root@VM_0_10_centos mys ...
- .net桌面程序或者控制台程序使用NLog时的注意事项
Nuget添加NLog 添加nlog.config文件,并选择属性->始终复制 不选择始终复制,编译后nlog.config是没有的. 具体使用: private static readonly ...
- 怎么去掉织梦(dedecms)网站首页默认携带的index.html尾巴
如果你的网站带小尾巴,比如这样的 那你就要注意了,因为这会导致搜索引擎会认为和不带尾巴的页面是两个页面,都会参与排名,会分散首页的权重. 那我们怎么去除呢? 方法1: 1)在空间面板里面找到默认首页设 ...
- python的mysql数据库操作
python操作mysql数据库 Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口. Python 数据库接口支持非常多的数据库 ...
- jquery预加载显示百分比
jquery预加载显示百分比 <pre> <img class="bj loadimg" loadimg="/weiqingshu/images/1/b ...
- Mybaties的简单使用(全当做复习了)
在使用mybaties的时候,最容易忘掉的是他的动态SQL,不过网上有关这方面的文章很多. 在动态SQl中最常见的几种SQL的语法就是: if choose (when, otherwise) tri ...