zoukankan      html  css  js  c++  java
  • python之路--面向对象之反射

    isinstance和issubclass

    isinstance(对象,类)判断一个对象是不是这个类的对象

    class Foo:pass
    
    class Son(Foo):pass
    
    s = Son()
    # 判断一个对象是不是这个类的对象,传两个参数(对象,类)
    print(isinstance(s,Son))
    print(isinstance(s,Foo))
    print(type(s) is Son)
    print(type(s) is Foo)

    issubclass(子类,父类)判断一个类是不是另一类的子类

    class Foo:pass
    
    class Son(Foo):pass
    
    # 判断一个类是不是另一个类的子类,传两个参数(子类,父类)
    print(issubclass(Son,Foo))
    print(issubclass(Son,Foo))
    print(issubclass(Son,object))
    print(issubclass(Foo,object))
    print(issubclass(int,object))

    staticmethod和classmethod

    相同点

    都可以直接被类调用,不需要实例化

    不同点

    1. 类方法必须一个cls参数表示这个类
    2. 静态方法不需要,静态方法不能直接使用

    绑定方法

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

    非绑定方法

    • 静态方法:没有默认参数,并且可以被类和对象调用(不推荐) --非绑定
    class Student:
        title = 'hello world'
        def __int__(self):pass
    
        @staticmethod  # 静态方法 :让类的方法正常被调用,就像正常的函数一样
        def show_student_info():
            print('小明 男')
        @classmethod   # 类方法:默认参数cls,可以直接用类名调用,可以和类属性交互
        def hello(cls):
            print(cls.title)
    
    Student.show_student_info()
    s = Student()
    s.show_student_info()
    s.hello()

    反射

    什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

    python面向对象中的反射

    python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中一切皆对象(都可以使用反射)

    实现反射的4个函数

    常用
    • hasattr
    • getattr
    不常用
    • setattr
    • delattr

    对象反射

    # 对象反射
    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 73
        def func(self):
            print(123)
    
    # 反射 可以用字符串的方式去访问对象的属性、调用对象的方法
    egg = Foo()
    
    print(hasattr(egg,'name'))      # 判断属性时候,存在与否都返回布尔值
    print(getattr(egg,'name'))      # 得到该属性的值
    print(getattr(egg,'func'))      # 判断方法时,存在返回内存地址,不存在报错
    func = getattr(egg,'func')      # 把内存地址重新赋值给变量func
    func()                          # 加括号直接调用
    
    setattr(egg,'sex','nv')
    print(egg.sex)
    setattr(egg,'show_name',lambda self:self.name + 'sb')
    print(egg.show_name(egg))
    delattr(egg,'name')
    print(egg.name)

    类反射

    class Foo:
        f = 456
    
        @classmethod
        def class_method_demo(cls):
            print('class_method_demo')
    
        @staticmethod
        def static_method_demo():
            print('static_method_demo')
    if hasattr(Foo,'f'):
        print(getattr(Foo,'f'))
    print(hasattr(Foo,'class_method_demo'))
    method = getattr(Foo,'class_method_demo')
    method()
    print(hasattr(Foo,'static_method_demo'))
    method2 = getattr(Foo,'static_method_demo')
    method2()

    模块反射

    # 在其他模块应用反射
    import my_module
    print(hasattr(my_module,'test'))
    getattr(my_module,'test')()
    
    def demo1():
        print('demo1')
    
    
    # 在本模块中应用反射
    import sys
    module_obj = sys.modules[__name__]
    print(hasattr(module_obj,'demo1'))
    模块反射关联文件(同级目录下的my_module)
    def test():
        print('test')

    内置方法

    • __str__和__repr__

    1. 当打印一个对象的时候,如果实现了__str__,打印其中的返回值
    2. 当__str__没有被实现的时候,就会调用__repr__
    3. 当用字符串格式化的时候%s和%r会分别帝欧用对应的__str__和__repr__
    4. 不管是在字符串格式化的时候还是在打印对象的时候,__repr__都可以作为__str__的替补,反之不是
    5. 如果__str__和__repr__方法你只能实现一个,先实现__repr__
    6. 必须要有return return的对象必须是字符串
    class Foo:
        def __init__(self,name):
            self.name = name
        def __str__(self):
            return 'obj info in str'
    
        def __repr__(self):
            return 'obj info in repr'
    
    f = Foo('8192bit')
    print('%s'%f)
    print('%r'%f)
    print(repr(f))      # 等于f.__repr__()
    print(str(f))
    • __format__

    # 自定制 __format__
    format_dict = {
        "nat": '{obj.name}-{obj.address}-{obj.type}',
        "nta": '{obj.name}:{obj.address}:{obj.type}',
        "tan": '{obj.name}/{obj.address}/{obj.type}',
    }
    class School:
        def __init__(self,name,address,type):
            self.name = name
            self.address = address
            self.type = type
        def __str__(self):
            return "school_name:%s,school_address:%s"%(self.name,self.address)
        def __repr__(self):
            return "school(%s,%s)"%(self.name,self.type)
    
        def __format__(self, format_spec):
            if not format_spec or format_spec not in format_dict:
                format_spec = "nat"
            return format_dict[format_spec].format(obj=self)
    
    
    s = School('oldboy','北京','私立')
    print('%s'%s)
    print('%r'%s)
    print(format(s,'nat'))
    print(format(s,'nta'))
    print(format(s,'tan'))
    print(format(s,'nataaaaaaaaaa'))
    • __del__

      析构方法,当对象在内存被释放时,自动触发执行。
      注:此方法一般无需定义,以为Python是一门高级语言,程序员在使用时无序关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
    class Foo:
        def __del__(self):
            print('执行我啦')
    
    f= Foo()
    print(123)
    print(123)
    print(123)
    del f       # 默认最后执行,本次为指定执行
    print(123)
    print(123)
    • item 系列(__getitem__,__setitem__,__delitem__)

    class Foo:
        def __init__(self):
            self.name = '8192bit'
            self.age = 18
    
        def __getitem__(self, item):
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            del self.__dict__[key]
    
    f = Foo()
    print(f['name'])
    f['sex'] = 'nv'
    print(f['sex'])
    del f['sex']
    
    • __new__

    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A,*args,**kwargs)
    a = A()
    print(a.x)

    实现单例模式

    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    three = Singleton()
    go = Singleton()
    print(one,two)
    
    one.name = 'alex'
    print(two.name)
    • __call__

      对象名后面加括号,触发执行。
      注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()()
    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__
    • __len__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))
    • __hash__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __hash__(self):
            return hash(str(self.a)+str(self.b))
    a = A()
    print(hash(a))
    • __eq__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            if  self.a == obj.a and self.b == obj.b:
                return True
    a = A()
    b = A()
    print(a == b)

    纸牌游戏

    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
    
        def __call__(self, *args, **kwargs):
            return self._cards
    
    deck = FranchDeck()
    # print(deck[0])    # 按顺序取牌
    # print(deck[3])
    # print(deck[2])
    # print(deck[1])
    # from random import choice # 随机拿牌
    # print(choice(deck))
    # print(choice(deck))
    
    from random import shuffle  # 洗牌
    shuffle(deck)
    print(deck())
    shuffle(deck)
    print(deck())

    面试题

    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __hash__(self):
            return hash(self.name+self.sex)
    
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:return True
    
    p_lst = []
    for i in range(84):
        p_lst.append(Person('egon',i,'male'))
    
    print(p_lst)
    print(set(p_lst))

    感谢

    感谢eval美女倾囊相授





  • 相关阅读:
    剑指OFFER----面试题37. 序列化二叉树
    剑指OFFER----面试题36. 二叉搜索树与双向链表
    剑指OFFER----面试题35. 复杂链表的复制
    6.深拷贝与浅拷贝
    DevExpress ASP.NET v19.1版本亮点:发布全新的Gantt控件
    MFC界面库BCGControlBar v30.1新功能详解:Dialogs和Forms
    Kendo UI for jQuery使用教程:支持Web浏览器
    DevExpress Windows 10 v19.1新版亮点:UWP控件新功能全面解析
    Java 11必掌握的8大特性,完美代码信手拈来
    Kendo UI for jQuery使用教程:入门指南
  • 原文地址:https://www.cnblogs.com/8192bit/p/7382004.html
Copyright © 2011-2022 走看看