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 ...
随机推荐
- 浅入深出ETCD之【raft原理】
前言 这次我们来说说,有关于etcd原理的一些事情.之前我们已经了解到了etcd是一个分布式的k-v存储,那么它究竟是如何保证数据是如何复制到每个节点上面去的呢?又是如何保证在网络分区的情况下能正常工 ...
- Docker入门-docker运行springboot应用(二)
环境准备 jdk8 安装docker 镜像加速器配置 docker私有仓库 springboot工程的jar包 docker部署项目 dockfile Dockfile是一种被Docker程序解释的脚 ...
- squid4
主机上的squid一直是傻瓜型使用,yum安装.默认配置.千年不动.突然漏扫出来3.X版本不能用了,搜了下,得升4.神奇的发现centos7的源(阿里源)里面竟然最高只有3.网上搜使用yum装的也都是 ...
- java 快速定位线上cpu偏高
1.top -c 加 大写P 查找高进程ID 2.top -Hp 加 大写 P 查找高线程ID 3.printf '%x\n' 线程ID 转成16进制 4.jstack 进程ID | grep 16进 ...
- mysql数据库每天备份
以备份mysql下的test数据库为例,备份到/home/data 使用mysqldunp命令 dump.sh mysqldump -h127. -uadmin -P3306 -ppassword t ...
- C#.NET LoadXml 时 “根级别上的数据无效。 行 1,位置 1”
去除XML HEADER: <?xml version="1.0" encoding="utf-8"?> if (rspBusiXml.Contai ...
- Xcode 创建使用多个 target (1)
前段时间,浏览了一个项目:手机和平板同时适配的.见识到了多个target 应用的妙处: 一个target 担任 手机开发,一个target 担任 平板开发,设计的很巧妙. 一口吃不成胖子,这篇先写 第 ...
- sql server 2008 自动备份
身份验证:包含Windows身份验证和 SQL Server身份验证,此处选择Windows 身份验证; 选择[管理]-->[维护计划]-->[维护计划向导] 必须启用代理服务(启动模式请 ...
- phpredis封装
<pre><?php/** * This is a Redis exntend class */ class RedisClient{ private static $instanc ...
- Java操作fastDFS
一.加入Maven依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs- ...