zoukankan      html  css  js  c++  java
  • 反射

    一、静态方法(staticmethod)和类方法(classmethod)

    类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性)

    静态方法:让类里的方法直接被类调用,就像正常调用函数一样

    类方法和静态方法的相同点:都可以直接被类调用,不需要实例化

    类方法和静态方法的不同点:

      类方法必须有一个cls参数表示这个类,可以使用类属性

      静态方法不需要参数

    绑定方法:分为普通方法和类方法

         普通方法:默认有一个self对象传进来,并且只能被对象调用-------绑定到对象

          类方法:默认有一个cls对象传进来,并且可以被类和对象(不推荐)调用-----绑定到类

    非绑定方法:静态方法:没有设置默认参数,并且可以被类和对象(不推荐)调用-----非绑定

    复制代码
    class Student:
        f = open('student', encoding='utf-8')
        def __init__(self):
            pass
        @classmethod #类方法 :有个默认参数cls,并且可以直接使用类名去
                     #调用,还可以与类属性交互(也就是可以使用类属性)
        def show_student_info_class(cls):
            # f = open('student', encoding='utf-8')
            for line in cls.f:
                name,sex = line.strip().split(',')
                print(name,sex)
        @staticmethod  #静态方法:可以直接使用类名去调用,就像正常的函数调用一样
        def show_student_info_static(): #不用传self
            f = open('student',encoding='utf-8')
            for line in f:
                name,sex = line.strip().split(',')
                print(name,sex)
    # egon = Student()
    # egon.show_student_info_static()  #也可以这样调,但是还是推荐用类名去调
    # egon.show_student_info_class()
    
    Student.show_student_info_class()#类名.方法名()
    print('-------------------')
    Student.show_student_info_static()#类名.方法名()
    
    staticmethod和classmethod
    复制代码

    一、isinstance 和 issubclass

    isinstance(obj,cls):检查obj是不是cls的对象(传两个参数,一个是对象,一个是类)

    issubclass(sub,super):检查sub是不是super的子类(传两个参数,一个是子类,一个是父类)

    复制代码
    class Foo:
        pass
    class Son(Foo):
        pass
    s = Son()
    print(isinstance(s,Son))  #判断s是不是Son的对象
    print(type(s) is Son)
    print(isinstance(s,Foo))  #判断s是不是Foo的对象  不精准
    print(type(s) is Foo)  #type比较精准
    
    print(issubclass(Son,Foo)) #判断Son是不是Foo的子类
    print(issubclass(Son,object))
    print(issubclass(Foo,object))
    print(issubclass(int,object))
    复制代码

    二、反射

    反射:可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),python中一切皆对象,都可以使用反射。

    反射有四种方法:

    hasattr:hasattr(object,name)判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False

    getattr:获取对象的属性或者方法,如果存在则打印出来。hasattr和getattr配套使用

        需要注意的是,如果返回的是对象的方法,返回出来的是对象的内存地址,如果需要运行这个方法,可以在后面添加一对()

    setattr:给对象的属性赋值,若属性不存在,先创建后赋值

    delattr:删除该对象指定的一个属性

    复制代码
    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 51
        def func(self):
            print('hello')
    egg = Foo()
    setattr(egg,'sex','男')
    print(egg.sex)
    # 2.
    def show_name(self):
        print(self.name+'sb')
    setattr(egg,'sh_name',show_name)
    egg.sh_name(egg)
    show_name(egg)
    
    复制代码
    delattr(egg,'name')
    print(egg.name)

    1.对象应用反射

    复制代码

    class Foo:
    def __init__(self):
    self.name = 'egon'
    self.age = 51
    def func(self):
    print('hello')
    egg = Foo()
    print(hasattr(egg,'name')) #先判断name在egg里面存在不存在
    print(getattr(egg,'name')) #如果为True它才去得到
    print(hasattr(egg,'func'))
    print(getattr(egg,'func')) #得到的是地址
    # getattr(egg,'func')() #在这里加括号才能得到,因为func是方法
    if hasattr(egg,'func'):
    getattr(egg,'func')()
    else:
    print('没找到')

    复制代码

    2.类应用反射

    复制代码

    class Foo:
    f = 123
    @classmethod
    def class_method_dome(cls):
    print('class_method_dome')

    @staticmethod
    def static_method_dome():
    print('static_method_dome')
    print(hasattr(Foo,'class_method_dome'))
    method = getattr(Foo,'class_method_dome')
    method()
    print('------------')
    print(hasattr(Foo,'static_method_dome'))
    method1 = getattr(Foo,'static_method_dome')
    method1()

    复制代码

    3.模块应用反射

     模块的应用又分为导入其他模块反射和在本模块中反射

    复制代码

    # 1.导入其他模块引用
    import mymodule
    print(hasattr(mymodule,'test'))
    getattr(mymodule,'test')()

    # # 这里的getattr(mymodule,'test')()这一句相当于
    # p = getattr(mymodule,'test')
    # p()

    复制代码
    复制代码

    # 2.在本模块中应用反射
    def demo1():
    print('wwww')
    import sys
    # print(sys.modules)
    module_obj = sys.modules[__name__] #相当于'__main__'
    print(module_obj)
    print(hasattr(module_obj,'demo1'))
    getattr(module_obj,'demo1')()

    复制代码
    复制代码
    # 举例
    def 注册():
        print('regiester')
    def 登录():
        print('login')
    def 购物():
        pass
    print('注册,登录,购物')
    ret = input('请输入你要做的操作:')
    import sys
    my_module = sys.modules[__name__]  #利用sys模块导入一个自己的模块
    if hasattr(my_module,ret):
        getattr(my_module,ret)()
    
    导入自己的模块的一个简单小例子
    复制代码

    反射补充:

    db.mysql

    class MySQlHelper(object):
        print('MySQlHelper1111111')
        def fetchone(self):
            print('你好')

    db.pool

    class PoolHelper(object):
        print('PoolHelper')

    settings.py

    复制代码
    DB_PATH = 'db.mysql.MySQlHelper'
    
    #吧字符串切割
    module_name,cls_name = DB_PATH.rsplit('.',maxsplit=1)
    # print(module_name,cls_name)  #db.mysql    MySQlHelper
    #导入模块
    # from db.mysql import MySQlHelper
    import importlib
    moudel_obj = importlib.import_module(module_name)
    print(moudel_obj,type(moudel_obj))
    #导入模块中的类
    cls = getattr(moudel_obj,cls_name)
    print(cls)
    #对类进行实例化
    obj = cls()
    obj.fetchone()
    # getattr()
    复制代码

    三、内置方法

    1.__str__和__repr__

    改变对象的字符串显示

    复制代码
    class Foo:
        def __init__(self,name):
            self.name = name
        def __repr__(self):
            return 'obj in str'  #这里只能是return
        # def __str__(self):
        #     return '%s obj in str'%self.name
    f = Foo('egon')
    print(f)  #优先执行__str__里面的内容
    # 那么你是不是据地__repr__没用呢?
    # print('%s'%f)  #执行的是__str__里面的返回值
    # print('%r'%f)  #执行的是__repr__里面的返回值
    print('==============')
    print(str(f))  #当执行str(f)时,会去找__str__这个方法,如果找不到的时候,__repr__这个方法就给替补了
    print(repr(f))
    #1.当打印一个对象的时候,如果实现了__str__方法,打印__str__中的返回值
    # 2.当__str__没有被实现的时候,就会调用__repr__方法
    # 3.但是当你用字符串格式化的时候,%s和%r会分别调用__str__和__repr__方法
    # 4.不管是在字符串格式化的时候还是在打印对象的时候,
    # __repr__方法都可以作为__str__方法的替补,但反之则不行
    # 5.用于友好的表示对象。如果__str__和__repr__方法你只能实现一个:先实现__repr__
    
     __str__和__repr__
    复制代码

     2.__del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    复制代码
    class Foo:
        def __del__(self):
            print('执行我啦')
    
    f= Foo()
    print(123)
    print(123)
    print(123)
    print(123)
    复制代码

    3.item系列

    分别有__getitem__      ,__setitem__    ,__delitem__

    复制代码
    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 73
            self.l=[1,2,3]
        def __getitem__(self, item):  #得到
            # return  self.l[item]
            # return self.__dict__[item]
            # print(Foo.__dict__)
            return 123
        def __setitem__(self, key, value):  #修改
            print(key,value)
            self.__dict__[key] = value
        def __delitem__(self, key):  #删除
            del self.__dict__[key]
    f = Foo()
    print(f['qqq'])  #不管里面放的啥值,它都会得到返回值的内容,调用的是__getitem__方法
    f['name']='alex' #修改egon的值为alex,调用 __setitem__方法
    # del f['name'] #删除name,就会报错了,说明在调用__delitem__方法调用成功了,就已经删了,就会报错了
    print(f.name) 
    f1 = Foo()
    print(f == f1)
    # print(f.name)
    # print(f[0])  #一开始不能这样取值,但是提供了一个__getitem__方法,这样就可以用了
    # print(f[1])
    # print(f[2])
    
    三个方法的使用
    复制代码

    4.__new__(创建)

    复制代码
    # 4.__new__方法
    # 单例模式:是一种设计模式
    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                orig = super(Singleton, cls)
                cls._instance = orig.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    print(one,two)   #他们两个的地址一样
    
    one.name = 'alex'
    print(two.name) 
    
    单例模式
    复制代码
    复制代码
    # class A:
    #     def __init__(self):  #有一个方法在帮你创造self
    #         print('in init function')
    #         self.x = 1
    #
    #     def __new__(cls, *args, **kwargs):
    #         print('in new function')
    #         return object.__new__(A, *args, **kwargs)
    # a = A()
    # b = A()
    # c = A()
    # d = A()
    # print(a,b,c,d)
    
    __new__
    复制代码

    5.__call__

    对象后面加括号,触发执行

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
    2     def __call__(self, *args, **kwargs):
    3         print(123)
    4 # f = Foo()
    5 # f() #如果不写上面的__call__方法,就不会调用。如果加上,就正确了
    6 Foo()() #也可以这样表示

    6.__hash__

    复制代码
    class Foo:
        def __hash__(self):
            print('aaaaaaaaaa')
            return hash(self.name)
            # print('aaas')
    f = Foo()
    f.name = 'egon'
    print(hash(f))  #hash方法是可以重写的
    
    __hash__
    复制代码

    7.__eq__

    复制代码
    class A:
        def __eq__(self, other):
            return True
    a = A()
    b = A()
    print(a==b) #不加方法的时候返回的是False,加了个__eq__方法就返回了个True
    # '=='内部就调用了__eq__方法
    print(a is b)
    
    __eq__
    复制代码

     一道面试题

    复制代码
    from collections import namedtuple
    Card = namedtuple('Card',['rank','suit'])  #两个属性:一个是数,一个是花色(每一个card的对象就是一张纸牌)
    class FranchDeck: #纸牌数据类型
        ranks = [str(n) for n in range(2,11)] + list('JQKA')
        suits = ['红心','方板','梅花','黑桃']
    
        def __init__(self):
            self._cards = [Card(rank,suit) for rank in FranchDeck.ranks #先循环这个,在循环下面的那个循环
                                            for suit in FranchDeck.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, item):
            return self._cards[item]
    
        def __setitem__(self, key, value):
            self._cards[key] = value
    
    deck = FranchDeck()
    # print(deck[0])
    # print(deck[0])
    # print(deck[0])
    # print(deck[0])
    from random import choice
    print(choice(deck))
    print(choice(deck))
    
    from random import shuffle
    shuffle(deck)
    print(deck[:5])
    
    纸牌游戏
  • 相关阅读:
    char nvarchar varchar
    第32月第8天 打包 Framework 时使用 CocoaPods 引入第三方库的方法
    第31月第25天 xcode debug 限制uitextfiled输入
    第31月第22天 draw
    第31月第19天 NV12
    第31月第17天 resolveInstanceMethod
    第31月第15天 -fembed-bitcode
    第31月第10天 tableview头部空白 Other Linker Flags rtmp
    第31月 第9天 责任链AppDelegate
    第30月第18天 autolayout代码
  • 原文地址:https://www.cnblogs.com/liurenli/p/10028637.html
Copyright © 2011-2022 走看看