第二十七天

反射

知道一个变量的字符串数据类型的名字,想要直接使用

反射对象的实例变量/反射对象的实例变量

反射类 的 静态变量/绑定方法/其他方法/

模块中的所有变量

# 被导入的文件叫模块
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__方法

posted @ 2020-03-19 17:12  小丁变优秀  阅读(95)  评论(1)    收藏  举报