封装

广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见

私有属性

私有属性表示方式即在一个属性名前加上两个双下划线

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学习日记(二十六) 封装和几个装饰器函数的更多相关文章

  1. Python学习札记(二十六) 函数式编程7 修饰器

    修饰器 NOTE 1.函数对象有一个__name__属性,可以拿到函数的名字: #!/usr/bin/env python3 def now(): print('2017/2/19') def mai ...

  2. Python学习(二十六)—— Django基础一

    转载自:http://www.cnblogs.com/liwenzhou/p/8258992.html 一.Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的 ...

  3. Python学习日记(三十六) Mysql数据库篇 四

    MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...

  4. Python学习日记(二十八) hashlib模块、configparse模块、logging模块

    hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...

  5. Python学习日记(二十二) 初识面向对象

    引子 假设我们要开发一个关于飞机大战的游戏,那么游戏的里面就会有两个角色,分别是属于玩家操控的战机和敌方的战机,并且两个战机都有不同的技能或攻击方式,现在我们用自己目前所学的去写出下面的这些代码: d ...

  6. Python学习日记(二十九) 网络编程

    早期的计算机通信需要有一个中间件,A要给B传东西,A必须要把信息传给中间件,B再把从中间件中拿到信息 由于不同机器之间需要通信就产生了网络 软件开发的架构 1.C/S架构 服务器-客户机,即Clien ...

  7. Python学习日记(二十五) 接口类、抽象类、多态

    接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...

  8. Python学习日记(二十四) 继承

    继承 什么是继承?就是一个派生类(derived class)继承基类(base class)的字段和方法.一个类可以被多个类继承;在python中,一个类可以继承多个类. 父类可以称为基类和超类,而 ...

  9. python学习(二十六) 字典

    # 访问字典car = {'make':'bmw', 'model':'550i', 'year':2016}print(car)print(car['make']) # 添加元素d = {}d['o ...

随机推荐

  1. Linux find命令忽略目录的查找方法

    在Linux操作系统中,find命令非常强大,在文件与目录的查找方面可谓无所不至其极,如果能结合xargs命令使得,更是强大无比. 以下来看看find命令忽略目录查找的用法吧. 例1,根据文件属性查找 ...

  2. mysql 日期自动自动添加及更新为当前时间

    1. 虽然mysql中日期时间类型比较多,但是支持默认值的类型只有timestamp,详见这里. 2. 希望新增记录时自动写入当前时间,建表语句如下: `create_time` timestamp ...

  3. matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段

    一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...

  4. Mac mysql 忘记root密码的解决方法

    1.执行命令以安全模式启动MySQL cd /usr/local/mysql/bin sudo ./mysqld_safe --skip-grant-tables 2.同上面目录下执行 '\) whe ...

  5. Flink Table Api & SQL 翻译目录

    Flink 官网 Table Api & SQL  相关文档的翻译终于完成,这里整理一个安装官网目录顺序一样的目录 [翻译]Flink Table Api & SQL —— Overv ...

  6. makefile那些事儿

    一.好处 自动化编译,一条make命令,整个工程可以完全自动编译,make命令是构建大型项目的首选方案. makefile就像一个shell脚本一样,用来定义规则,一个名称包含一条或多条命令,在终端m ...

  7. Centos7——Firefox浏览器个性化配置调教

    因为谷歌浏览器无法正常登陆帐号,只能切换到火狐浏览器 默认浏览器我使用的是bing搜索 1.隐藏顶部标题栏 顶部标题栏真的占地方,所以直接选择隐藏 点击设置->自定义customize-> ...

  8. 【NPDP笔记】第一章 新产品开发战略

    1.1 战略很重要 1.2 战略定义 使命/愿景/核心价值观:成为领导者 公司/经营战略:市场份额扩大10% 创新战略:强调技术,外部合作 职能战略:IT战略,人力资源战略 1.3明确组织方向 组织身 ...

  9. kafka高可用性集群

    kafka集群并测试其高可用性 介绍 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站 ...

  10. Ubuntu下重启mysql

    启动mysql: 方式一:sudo /etc/init.d/mysql start 方式二:sudo service mysql start 停止mysql: 方式一:sudo /etc/init.d ...