第二十七天
反射
知道一个变量的字符串数据类型的名字,想要直接使用
反射对象的实例变量/反射对象的实例变量
反射类 的 静态变量/绑定方法/其他方法/
模块中的所有变量
# 被导入的文件叫模块
import a
print(a.sex)
# 当前执行的py文件 --脚本
sex=None
print(sex)
反射的例子 :
#知道一个变量的字符串数据类型的名字,想要直接使用
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
alex=Person('alex','83')
ylex=Person('ylex','74')
print(alex.name)
ret=getattr(alex,'name')
print(ret)
ret=getattr(ylex,'age')
print(ret)
# alex
# alex
# 74
ret=getattr(ylex,'字符串')
支付接口的 归一化设计
调用当前文件中的 模块 推到方法
这事放在a.py里面 模块
# --------------------------
# 把这个放在 a.py文件里
# # class Wechat:pass
# # class Alipay:pass
# # ------------------------
# import a
# print(a.Wechat)
# print(a.Alipay)
#
# # 对象名.属性名==> getattr(对象名,'属性名')
# # a.Alipay==>getattr(a,Alipay)
# print(getattr(a,'Alipay'))
# print(getattr(a,'Wechat'))
class Wechat:pass
class Alipay:pass
import a
import sys
print(a.Alipay)
print(getattr(a,'Alipay')) #发现 模块里面所有的名字都可以调用 a是一个内存地址
#我们 找到当前文件的内存地址 进行调用,我们就可以在当前文件里调用
# print(sys.modules)
print(sys.modules['a'].Alipay) #上下 作用一样
print(getattr(sys.modules['a'],'Alipay')) #这是对于模块来说
print(getattr(sys.modules['__main__'],'Alipay')) #对于当前文件来说呢 反射
print(sys.modules['__main__'].Alipay) #对于当前文件来说呢 对象.属性名
waha='asdasdasd'
print(getattr(sys.modules['__main__'],'waha'))
聚合支付利用 反射 改进
class Payment:
pass
class Alipay(Payment):
def __init__(self,name):
self.name=name
def pay(self,money):
dic={'uname':self.name,'money':money}
print(f'{self.name}通过支付宝支付{money}元成功')
class Wechat(Payment):
def __init__(self,name):
self.name=name
def pay(self,money):
dic={'username':self.name,'money':money}
print(f'{self.name}通过微信支付{money}元成功')
class Apple(Payment):
def __init__(self,name):
self.name=name
def pay(self,money):
dic={'name':self.name,'number':money}
# 想办法调用苹果支付多少多少钱
print(f'{self.name}通过Apple pay支付{money}元成功')
class QQpay(Payment):
def __init__(self, name):
self.name = name
def pay(self, money):
print(f'{self.name}通过QQ pay支付{money}元成功')
#
#
# # /改进
import sys
def pay(name,price,kind):
class_name=getattr(sys.modules['__main__'],kind)
# print(sys.modules['__main__'].Apple) #<class '__main__.Apple'>
# 如果这样调用,只能一个个调用, 反射 解决了 重复写的 问题
# 将类名 当做一个参数 传进来 然后调用
obj=class_name(name)
obj.pay(price)
pay("小明",400,'Apple')
pay("小明",400,'QQpay')
pay("小明",400,'Wechat')
pay("小明",400,'Alipay')
#小明通过Apple pay支付400元成功
#小明通过QQ pay支付400元成功
#小明通过微信支付400元成功
#小明通过支付宝支付400元成功
反射对象的实例变量
class A:
def __init__(self):
self.name='alex'
self.age=84
def func(self):
print('wahah')
return 666
a=A()
print(a.name)
print(getattr(a,'name'))
print(getattr(a,'age')) #反射对象的实例变量
alex
alex
84
print(getattr(a,'func')()) #
#wahah
#666
反射对象的绑定方法
class A:
role='治疗'
def __init__(self):
self.name='alex'
self.age=84
def func(self):
print('wahah')
return 666
print(getattr(a,'func')())
# wahah
# 666
print(getattr(a,'role')) #反射类中的静态变量
引用模块中任意变量
# 引用模块中任意变量
import a #引用模块中任意变量
print(a.sww) # 正常情况下
print(getattr(a,'sww')) #反射方法
getattr(a,'sww')() #执行
print(a.lst)
print(getattr(a,'lst')) #反射方法
print(a.dic
print(getattr(a,'dic')) #反射方法
print(a.we)
print(getattr(a,'we')) #反射方法
反射本模块中的名字
import sys #反射本模块中的名字
cat='小毛'
dog='小狗'
def pig():
print('小p')
print(getattr(sys.modules['__main__'], 'cat'))
print(getattr(sys.modules['__main__'], 'dog'))
getattr(sys.modules['__main__'],'pig')()
hasattr 反射的另一个函数 检验是否存在反射
存在 True
不存在False
class A:
sex='4524'
w='454'
a=A()
print(hasattr(a, 'sex'))
print(hasattr(a, 'w'))
print(hasattr(a, 'asdasw'))
True
True
False
if hasattr(a, 'asdasw'):
print(getattr(a, 'asdasw'))
#这两个函数是一个好兄弟
callable() 判断一个东西是否可调用
if hasattr(a, 'func'):
if callable(getattr(a,'func')):
getattr(a,'func')()
先判断是否是反射 hasattr
在判断是否可以调用 callable
总结
反射模块中的内容
反射本文件中的内容
反射对象 的属性或绑定方法
反射类的静态变量
callable
实际的例子-归一化设计
注册作业
class Auth:
def __init__(self,name,age):
self.name=name
self.age=age
def register(self):
print("开始注册啦")
def login(self):
print("开始登陆啦")
l=[('登陆','register'),('注册','login')]
print(l[0][1])
i=0
for j,k in l:
i+=1
print(i,".",j)
flag=True
while flag:
a = input("请输入序号")
if a.upper()=='Q':
break
else:
b=Auth('xiaowu',18)
if hasattr(b, l[int(a) - 1][1]):
if callable(getattr(b,l[int(a) - 1][1])):
getattr(b,l[int(a) - 1][1])()
flag=False
# 循环这个列表
# 显示序号 用户要做的操作
# 用户输入序号
# 你通过序号找到 对应的login 或者register方法
# 先实例化***************************************
# 调用对应的的方法,完成登陆或者注册的功能
@classmethod
什么时候使用classmethod?
定义了一个方法,默认传self 但是这个self 没有被使用
并且你在这个方法里面用到了当前类名 (cls)
# class Good:
# __discount=0.8
# def __init__(self):
# self.__price=5
# self.price=self.__price*self.__discount
# def change__discount(self,new):
# Good.__discount=new
# apple=Good()
#
# print(apple.price)
# apple.change__discount(0.6)
# apple2=Good()
# print(apple2.price)
# 定义了一个方法 默认传self 但这个self 没有被使用
# self 传进去多此一举
# 现在使用 @classmethod方法 把一个对象的绑定方法修改成一个类方法
class Good:
__discount=0.8
def __init__(self):
self.__price=5
self.price=self.__price*self.__discount
@classmethod
def change__discount(cls,new_discount):
cls.__discount=new_discount
apple=Good()
print(apple.price)
Good.change__discount(0.6) #*********************
apple2=Good()
print(apple2.price)
# 第一1在方法中仍然可以引用类中的静态变量
# 第二 可以不用实例化对象 直接用类名 在外部调用这个方法 或者你准备使用类的内存空间的名字的时候
Good.change__discount(0.6) #类方法可以通过类名调用
apple.change__discount(0.4) #类方法可以通过对象名调用
import time
t=time.localtime()
# t=time.time()
print(t)
# # print(f'{t.tm_mday}-{t.tm_mon}')
@staticmethod
帮我们把一个函数直接放到函数中使用 不传参数也不传self 直接使用和外面的区别 仅仅是 前面加上
类名.函数名().
补充:能定义在类的内容
静态变量 是个所有变量共享的变量
绑定方法 是个自带self 参数的函数 由对象调用
类方法 是个自带cls 参数的函数 由对象 \类调用
静态方法 是个手都不带的函数 由对象 \类调用
property 是个伪装成属性的方法 由对象调用 但是不加括号
_ call_
# callable(对象)
#
# 对象能不能运行 就是callable 判断得的事
# __call__ 对象() 调用这个 类中的 __call__方法
class A:
def __call__(self, *args, **kwargs):
print("-----------")
# Flask框架的源码
obj=A()()
# ----------- 成功了
_ _ len _ _
# __len__
class A :
def __init__(self,name):
self.name=name
self.students=[]
py22=A('py22')
py22.students.append('小屋')
py22.students.append('小丁')
# print(len(py22)) #报错
# 改进/
class A :
def __init__(self,name):
self.name=name
self.students=[]
def __len__(self):
return len(self.students)
py22=A('py22')
py22.students.append('小屋')
py22.students.append('小丁')
print(len(py22))
# 2 成功了
_ new_ 先调用new 再 init
为什么要用? 创建一个对象需要的空间的
单例模式(默写)
class A:
def __new__(cls, *args, **kwargs):
o=super().__new__(cls)
# o=object.__new__(cls) 这种也可以使用
print("执行o",o)
return o
def __init__(self):
print("执行init",self)
A()
# 实例化的时候 先调 new 再调 init
# 不能使用new 方法
# 先创建一个 空间 有一个指针指向__new__
# 调用init--> __init__
单例模式
# 设计模式--单例模式
# 一个类从头到尾 只会创建一次self 的空间
# class Baby:
# def __init__(self,cloth,pants):
# self.cloth=cloth
# self.pants=pants
# B1=Baby("红毛衣",'驴皮裤')
# B2=Baby("红毛衣",'驴皮裤')
# B3=Baby("红毛衣",'驴皮裤')
# print(B1)
# print(B2)
# print(B3)
class Baby:
__instance=None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance=super().__new__(cls)
return cls.__instance
def __init__(self,cloth,pants):
self.cloth=cloth
self.pants=pants
B1=Baby("红毛衣",'驴皮裤')
B2=Baby("绿毛衣",'驴皮裤')
print(B1.cloth)
print(B2.cloth)
# 绿毛衣 #第一次没有 把他填进去 第二次有了 ,直接改变
# 绿毛衣
_ str_
没有_ str_ 的时候 print(类名) 打印的是内存地址
使用 _ str_ 打印的是内容 不是冰冷的内存地址
class clas:
def __init__(self):
self.student=[]
def append(self,name):
self.student.append(name)
def __str__(self):
return str(self.student)
#return ','.join(self.student)
A=[]
print(A)
print("我们撒打算%s"%A)
A.append('大壮')
print(A)
print("我们撒打算%s"%A)
print(str(A))
#[]
我们撒打算[]
['大壮']
我们撒打算['大壮']
['大壮']
在打印一个对象的时候调用的是_ str_ 方法
在%s 拼接一个对象的时候调用的是_ str_ 方法
在 str 一个对象的时候调用的是_ str_ 方法
当我们使用打印一个对象 用%s 进行字符串拼接 或者 str(对象) 这个对象的 str 方法
如果找不到_ str_ 就调用 _ repr_
_ _repr __ 不仅是 _ _str__替代品,还有自己的功能
用%r 进行字符串拼接 或者用 repr(对象) 的时候总是调用_ _repr__方法
对代码有疑问欢迎交流
一个python爱好者 :
微信:at8685b

浙公网安备 33010602011771号