day-26-封装-property装饰器-反射
一、super进阶
在多继承中:严格按照mro顺序来执行
super是按照mro顺序来寻找当前类的下一类
在py3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象). 函数名()
这样才能够帮我们调用到这个子类的mro顺序的下一个类中的方法
在py2的经典类中,并不支持使用super来找下一个类
class A:
def func(self):
print('is A')
class B(A):
def func(self):
super().func()
print('is B')
class C(A):
def func(self):
super().func()
print('is C')
class D(B, C):
def func(self):
super().func()
print('is D')
d = D()
print(D.mro())
d.func()
# 输出
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
is A
is C
is B
is D
在单继承中:super就是找父类
class Foo:
def func(self):
print('is Foo')
class Son(Foo):
def func(self):
super().func() # 先找父类的func方法--->打印is Foo
print('is Son') # 在打印自己的is Son
s = Son()
s.func()
# 输出
is Foo
is Son
二、封装
封装:就是把属性或方法装起来
广义:把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用
狭义:把属性和方法藏起来,外面不能调用,只能在内部偷偷调用
所有的私有化都是为了让用户不在外部调用类中的某个名字
如果完成私有化,那么这个类的封装度就更高了,封装度越高各种属性和方法的安全性也越高,但代码越复杂
封装的语法:
1、给一个名字前面加上了双下滑线的时候,这个名字就变成了一个私有的
2、所有私有的内容或者名字都不能在类的外部调用,只能在类的内部使用了
# 不想让你看也不想让你改
class User:
def __init__(self, name, pwd):
self.name = name
self.__pwd = pwd # 私有的实例变量/私有的对象属性
use = User('admin', 'abc123')
print(use.__pwd) # 报错
print(use.pwd) # 报错
在外部查看和修改私有对象属性:
# 可以给你看也可以给你改,但你要用我自定义的方法看,和按照我的规则改
class User:
def __init__(self, name, pwd):
self.name = name
self.__pwd = pwd
def get_pwd(self): # 表示用户不能改只能看
return self.__pwd def change_pwd(self, count): # 表示用户必须调用我们自定义的修改方式来进行变量的修改
if count.isdigit(): # 是数字我就改,不是我就不改,还是原样
self.__pwd = count
return self.__pwd
use = User('admin', 'abc123')
print(use.get_pwd())
use.change_pwd('123456789') # 实际上是调用了对象内部的函数进行修改
print(use.get_pwd())
# 输出
abc123
123456789
1、加了双下划线的名字为啥不能从外部调用了?
class User:
__Country = '中国' # 私有的静态变量
__job = '攻城狮' # 私有的静态变量
def func(self):
# 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形(_User__Country)
print(User.__Country) # __Country已经变形成(_User__Country)
print(User.__dict__)
User().func()
'''
此时,变量做了一个转换所以在外部找不到了,如果外部调用转换后的变量还是可以调用的。(但不介意这样用)
__Country ---> _User__Country
__job ---> _User__job
'''
# 输出
{..., '_User__Country': '中国', '_User__job': '攻城狮',...}
中国
2、私有的内容不能被子类使用。
class Foo:
# __func:为私有的绑定方法
def __func(self): # 3、而父类Foo中的私有方法已经变形为_Foo__func了不是_Son__func方法了
print('is Foo')
class Son(Foo):
def __init__(self):
self.__func() # 2、子类__func方法变形成了_Son__func方法了,没有会去父类Foo找
Son() # 1、实例化时,自动调用init方法
# 输出 报错
AttributeError: 'Son' object has no attribute '_Son__func'
3、在其他语言中的数据的级别都有哪些?在python中有哪些?
public 公有的 类内类外都能用,父类子类都能用 python支持
protect 保护的 类内能用,父类子类都能用,类外不能用 python不支持
private 私有的 本类的类内部能用,其他地方都不能用 python支持
三、内置的装饰器:property,setter,delter
property方法:把一个方法伪装成属性,在掉用这个方法的时候不需要加()就可以直接得到返回值。
方法一:
from math import pi
class Circle:
def __init__(self, r):
self.r = r
@property # 把area()函数伪装成属性
def area(self):
print(pi * self.r ** 2)
# 实例化一个半径为5的圆
y = Circle(5)
y.area # 被伪装后圆的面积函数不用加()
# 输出
78.53981633974483
方法二:和私有的属性合作的
class User:
def __init__(self, name, pwd):
self.name = name
self.__pwd = pwd
@property
def pwd(self):
print(self.__pwd)
u = User('小杨', '1234')
u.pwd
# 输出
1234
setter方法:对伪装方法可以使用和属性一样的 = 号了
class User:
def __init__(self, name, pwd):
self.name = name
self.__pwd = pwd
@property
def pwd(self):
print(self.__pwd)
@pwd.setter
def pwd(self, count):
print('我这里setter被调用了')
if isinstance(count, int): # 满足条件(count是int类型)我就修改
self.__pwd = count
u = User('小杨', '1234')
u.pwd = 1111 # 可以使用 = 进行满足条件的赋值了,不满足原样不变
u.pwd
# 输出
我这里setter被调用了
1111
delter方法:(了解)
class User:
def __init__(self, name, pwd):
self.name = name
self.__pwd = pwd @property
def pwd(self):
print(self.__pwd) @pwd.deleter
def pwd(self):
print('我这里delter被调用了') u = User('小杨', '1234') del u.pwd
# 输出
我这里delter被调用了
四、反射getatter、hasatter
反射:用字符串类型的名字来操作这个名字对应的函数、实例变量、绑定方法、各种方法
在明明知道一个变量的字符串数据类型的名字,想直接调用它,但是调不到的时候,用反射
getattr方法:
1、反射对象的:实例变量、绑定方法
class Person:
def __init__(self, name , age):
self.name = name
self.age = age
def func(self):
print('is func')
# 实例化一个对象
Bob = Person('鲍勃', 18)
print(getattr(Bob, 'name')) # 反射对象的实例变量
getattr(Bob, 'func')() # 反射对象的绑定方法
# 输出
鲍勃
is func
2、反射类的:静态变量
class Person:
attribute = '会思考'
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('is func')
print(getattr(Person, 'attribute')) # 反射类的静态变量
# 输出
会思考
3、反射模块中的所有变量
反射被导入的模块:
# 模块 my_module.py 内容
count = '模块 my_module.py 中count的内容'
def func():
return '这是 my_module 模块中的 func 函数'
# --------------------------------------------------------------
import my_module
ret = getattr(my_module, 'count')
ret2 = getattr(my_module, 'func')
print(ret)
print(ret2())
# 输出
模块 my_module.py 中count的内容
这是 my_module 模块中的 func 函数
4、反射当前执行的py文件 ——> 当前脚本
import sys
lis = [1, 2, 3]
def func():
return 'is func'
ret1 = getattr(sys.modules['__main__'], 'lis') # 反射当前脚本的变量
ret2 = getattr(sys.modules['__main__'], 'func') # 反射当前脚本的函数
print(ret1)
print(ret2())
# 输出
[1, 2, 3]
is func
hasattr方法:
hasattr 方法其实是和 getattr 方法成对使用的,主要用来判断反射变量是否存在
class Person:
def __init__(self, name, age):
self.name = name
self.age = age def func(self):
print('is func') Bob = Person('鲍勃', 18)
print(hasattr(Bob, 'name')) # name 变量名存在就返回True
print(hasattr(Bob, 'sex')) # sex 变量不存在就返回False if hasattr(Bob, 'func'): # 判断 func 是否存在
# 存在,判断 func 是否可以被调佣(用 callable 判断是否是函数)
if callable(getattr(Bob, 'func')):
getattr(Bob, 'func')() # 是函数就加括号()
getattr(Bob, 'func') # 不是就不用加括号() # 输出
True
False
is func
五、反射例子
反射例子一:
import sys
class WeChat:
def __init__(self, username):
self.username = username
def pay(self, money):
print(f'{self.username}通过微信充值了{money}')
class Alipay:
def __init__(self, username):
self.username = username
def pay(self, money):
print(f'{self.username}通过支付宝充值了{money}')
# 简化归一化设计:
def pay(username, money, kind):
class_name = getattr(sys.modules['__main__'], kind) # 输入的类名,反射本地的类
obj = class_name(username) # 用上一步反射的类来创建实例化对象
obj.pay(money)
pay('小杨', 200, 'WeChat')
# 输出
小杨通过微信充值了200
反射例子二:
用户输入用户名密码性别
实例化对象
用户任意输入内容 : 不能用异常处理
如果输入的是属性名 打印属性值
如果输入的是方法名 调用方法
如果输入的什么都不是 不做操作
class User:
def __init__(self, name, pwd, sex):
self.name = name
self.pwd = pwd
self.sex = sex
def eat(self):
print(f'{self.name},在吃饭')
def sleep(self):
print(f'{self.name},在睡觉')
Bob = User('鲍勃', 18, '男')
count = input('需要操作的方法:')
if hasattr(Bob, count):
if callable(getattr(Bob, count)):
getattr(Bob, count)()
print(getattr(Bob, count))
反射例子三:
循环这个列表 显示 序号 用户要做的操作
用户输入序号
你通过序号找到对应的login或者register方法
先实例化
调用对应的方法,完成登录或者注册功能
class Authentic:
ll = [('登录', 'login'), ('注册', 'register')]
def __init__(self, username, pwd):
self.username = username
self.pwd = pwd
def register(self):
print('注册成功:')
def login(self):
print('登录成功:')
Bob = Authentic('python', 123456)
for index, func in enumerate(Authentic.ll, 1):
print(index, func[0])
count = int(input('请选择需要操作的序号>>:'))
if hasattr(Bob, Authentic.ll[count - 1][1]):
getattr(Bob, Authentic.ll[count - 1][1])()
# 输出
1 登录
2 注册
请选择需要操作的序号>>:2
注册成功:
day-26-封装-property装饰器-反射的更多相关文章
- Python10/24--组合/封装/property装饰器/多态
组合的应用: 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 3. 如何用组合 '''class Foo: aaa=111 ...
- 面向对象之组合、封装、多态、property装饰器
概要: 组合 封装 property装饰器 多态 Python推崇鸭子类型:解耦合,统一标准(不用继承) 1. 组合 继承:会传递给子类强制属性 组合:解耦合,减少占用内存.如:正常继承,如果一个班级 ...
- 组合,多态与多态性,封装以及property装饰器介绍
一:组合: 什么是组合:组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象. 为何要用组合:通过为某一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合 ...
- PYTHON-组合 封装 多态 property装饰器
# 组合'''软件重用的重要方式除了继承之外还有另外一种方式,即:组合组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之 ...
- 面向对象之 组合 封装 多态 property 装饰器
1.组合 什么是组合? 一个对象的属性是来自另一个类的对象,称之为组合 为什么要用组合 组合也是用来解决类与类代码冗余的问题 3.如何用组合 # obj1.xxx=obj2''''''# class ...
- 面向对象(三)--多态、封装、property装饰器
一.多态与多态性 1.什么是多态 多态指的是同一种类/事物的不同形态 class Animal: def speak(self): pass class People(Animal): def spe ...
- python面向对象:组合、封装、property装饰器、多态
一.组合二.封装三.property装饰器四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 3. ...
- python面向编程:类的组合、封装、property装饰器、多态
一.组合 二.封装 三.propert装饰器 四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 ...
- 面向对象之封装 及@property装饰器使用
目录 封装 1.封装的定义 2.封装的目的: 3.封装的三种方式 4.封装的优点 5.访问限制(封装) @property 装饰器 属性property底层实现 封装 1.封装的定义 将复杂的丑陋的, ...
随机推荐
- 箭头函数this的指向
箭头函数的this 什么是箭头函数,箭头函数是es6的新特性,其出现就是为了更好的表示(代替)回调函数 // 箭头函数 (arg1, arg2) => {} // 当箭头函数只有一个参数 arg ...
- 如何使用python爬取网页动态数据
我们在使用python爬取网页数据的时候,会遇到页面的数据是通过js脚本动态加载的情况,这时候我们就得模拟接口请求信息,根据接口返回结果来获取我们想要的数据. 以某电影网站为例:我们要获取到电影名称以 ...
- 5G时代,为什么NoSQL和SQL存在短板?
01 介绍 当今的通信服务提供商(CSP)需要能够在处理海量复杂的数据的同时,不会下降或者减慢网路响应速度和可靠性.5G时代,设备和用户数量呈指数级增长,这对业务支持服务(BSS)提出了新需求,也成为 ...
- 剑指 Offer 04. 二维数组中的查找 (思维)
剑指 Offer 04. 二维数组中的查找 题目链接 本题的解法是从矩阵的右上角开始寻找目标值. 根据矩阵的元素分布特性, 当目标值大于当前位置的值时将row行号++,因为此时目标值一定位于当前行的下 ...
- 13. Vue CLI脚手架
一. Vue CLI 介绍 1. 什么是Vue CLI? Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.Vue CLI 致力于将 Vue 生态中的工具基础标准化.它确保了各种构建工 ...
- HiveHA机制源码分析
hive让大数据飞了起来,不再需要专人写MR.平常我们都可以用基于thrift的任意语言来调用hive. 不过爱恨各半,hive的thrift不稳定也是出了名的.很容易就出问题,让人无计可施.唯一的办 ...
- c++ 反汇编 异常处理
c++异常处理 int main(){ try { throw 1; } catch ( int e ) { printf("catch int\r\n"); } catch ( ...
- Apache JMeter 5.4.1 Build Development
1. 说明 经过漫长的等待终于将开发环境搭建成功了!网络慢真的是伤不起!grade,确实要比maven简洁.....嗯!真香! 2. 工具准备 JDK1.8+ 这... ...
- Java学习之浅析高内聚低耦合
•前言 如果你涉及软件开发,可能会经常听到 "高内聚,低耦合" 这种概念型词语. 可是,何为 "高内聚,低耦合" 呢? •概念 "高内聚,低耦合&qu ...
- MarkDown-简单学习
标题 注意:首部添加1-6个"#"号来设置标题大小: 字体 1:粗体 (注意:首尾同时添加2个"*"号来设置) 2:斜体 (注意:首尾同时添加1个"* ...