#反射
class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

p1 = Person('tom',25)
ret = getattr(p1,'name') #获取对象p1的属性name的值
print(ret) #tom
setattr(p1,'name','jerry') #设置p1对象name属性的值为jerry
ret = getattr(p1,'name') #获取对象p1的属性name的值
ret1 = getattr(p1,'age') #获取对象p1的属性age的值
print(ret) #jerry
print(ret1) #25
print(hasattr(p1,'name')) #True 判断对象p1是否有属性‘name’
delattr(p1,'age') #删除对象p1的属性age
ret2 = getattr(p1,'age')
print(ret2) #AttributeError: 'Person' object has no attribute 'age'  #删除以后,获取报错
# #除了反射属性,还可以反射方法
class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print('func')

p1 = Person('tom',25)
ret = getattr(p1,'func')
print(ret()) #func
#反射应用
import a
print(a.Alipay)
print(a.Wehcat)
ret1 = getattr(a,'Alipay') #ret1是个Alipay类
ret2 = getattr(a,'Wehcat') #ret2 是个Wehcat类
print(ret1) #<class 'a.Alipay'>
print(ret2) #<class 'a.Wehcat'>
ret3 = ret1()#可以用ret1 来生
ret3.func() #Alipay func
#反射应用2,支付接口
import sys
def pay(name,price,kind): #这个就是接口
    class_name = getattr(sys.modules['__main__'],kind) #根据kind类型获取到本文件相应的类名(地址)
    obj = class_name(name,price) #类实例化
    obj.pay() #类方法调用

class Payment(object):
    def __init__(self,name,price):
        self.name = name
        self.price = price
class Alipay(Payment): #支付宝支付
    def pay(self):
        print(f'{self.name} 用支付宝支付了{self.price}元')
class Wechat(Payment): #支付宝支付
    def pay(self):
        print(f'{self.name} 用微信支付了{self.price}元')
class QQpay(Payment): #支付宝支付
    def pay(self):
        print(f'{self.name} 用QQ支付了{self.price}元')

pay('tom',255,'QQpay') #tom 用QQ支付了255元
pay('tom',300,'Wechat') #tom 用微信支付了300元
pay('jerry',25,'Alipay') #jerry 用支付宝支付了25元
#hasattr和getattr 经常搭配使用
#callable可以判断一个对象是否可调用
#练习2 反射
class User:
    def __init__(self,name,pwd,sex):
        self.name = name
        self.pwd = pwd
        self.sex = sex
    def eat(self):print(f'{self.name} eat')
    def sleep(self):print(f'{self.name} sleep')
#用户输入用户名密码性别 实例化对象,
#用户任意输入内容,1如果是属性名,打印属性值 2、如果是方法名,调用方法 3、如果啥都不是,不操作
name = input('Entry your name:')
pwd = input('Entry your pwd:')
sex = input('Entry your sex:')
u1 = User(name,pwd,sex)
while 1:
    content = input('Entry your content:')
    if hasattr(u1,content):
        if callable(getattr(u1,content)):
            getattr(u1,content)()
        else:print(getattr(u1,content))
    elif content.upper() == 'Q':break
    else:continue
#进阶
#两个装饰器 @classmethod @staticmethod 【重要】
#内置的方法  __new__  __call__ __len__ __eq__ __str__ __repr__ __enter__ __exit__ __del__
#classmethod 把一个对象绑定的方法修改成【类方法】
#比如有一个类,类里有一个静态变量,我要外部修改静态变量,可以写成:
class A:
    __var = 10 #静态变量 __var
    def __init__(self):pass
    def change_var(self,new_var): #更改__var,这个方法里的self没有用上
        A.__var = new_var
    def get_var(self): #打印
        print(A.__var)
a = A()
a.change_var(3)
a.get_var() #3
#变更一下
class A:
    __var = 10 #静态变量 __var
    def __init__(self):pass
    @classmethod  #设置装饰器 classmethod
    def change_var(cls,new_var): #更改__var方法,这里传进来的是一个类,不管类名怎么变化,cls永远获取这个类名
        cls.__var = new_var
    def get_var(self): #打印
        print(A.__var)

A.change_var(3) #这里直接用类名调用
A().get_var() #3
A().change_var(4) #还可以用对象调用
A().get_var()
#1、在方法中仍然可以引用类中的静态变量
#2、可以不用实例化对象,可以直接用类名在外部调用这个方法
#3、什么时候使用classmethod ,当定义了一个带self参数的方法,但是没有使用self,并且,在方法中使用到了当前的类名。
#classmethod应用  写一个方法,返回date对象
import time
class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
    @classmethod #classmethod装饰器
    def today(cls): #这个方法可以直接用类名Date 调用
        t = time.localtime()
        date1 = cls(t.tm_year,t.tm_mon,t.tm_mday) #对象的实例化工作在类内的方法里做的
        return date1 #返回一个Date类的对象

print(Date.today().year) #2020 直接调用
#@staticmethod  被装饰的方法会成为一个静态方法,比较少见
class User:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    @staticmethod
    def login(): #这个函数内没有用到self 和 cls 参数
        print('login') #login函数本来是类外的一个函数,被放到了User类内
User.login()
#本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数加一个@staticmethod装饰器即可
#总结:在类中可以定义的内容
#静态变量 是所有的对象共享的变量 由对象和类调用 但是不能重新赋值
#绑定方法 是带self参数的方法 由对象调用
#类方法  是自带cls的方法,由对象和类调用
#静态方法 是普通函数 由对象和类调用
#property属性 是一个伪装成属性的方法 由对象调用,不加括号
posted on 2020-08-04 18:03  94小渣渣  阅读(94)  评论(0编辑  收藏  举报