• 010---内置方法


    内置方法

    isinstance(obj,cls) 和 issubclass(sub,super)

    • isinstance:判断obj是否是cls的对象
    • issubclass:判断sub是否是super的子类
    class A:
        pass
    
    
    class B:
        pass
    
    
    class C(A, B):
        pass
    
    
    a = A()
    b = B()
    c = C()
    
    print(isinstance(a, A))
    print(isinstance(b, B))
    print(isinstance(c, C))
    print(isinstance(1, int))
    print(issubclass(C, (A, B)))
    

    反射

    • 什么是反射:根据字符串映射对象中的属性或方法
    • hasattr(obj, 'name'):判断obj对象中是否有一个name字符串对应的属性或方法
    • getattr(obj, 'name', default):检测对象中是否有name字符串的属性或者方法。属性存在就直接返回属性的值,方法存在则返回该方法的内存地址,加括号可调用。不存在如果没设置默认值。则报错,否则返回设置的默认值。
    • setattr(obj, key, value):设置obj.key = value
    • delattr(obj,'name'):删除对象中的name字符串的属性或方法。不存在则报错。
    • 简单使用示例
    # 定义:通过字符串映射到对象属性和方法
    
    class People:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def talk(self):
            return '%s 在说话' % self.name
    
    
    obj = People('egon', 18)
    
    print('obj是否有name属性:', hasattr(obj, 'name'))
    print('obj是否有talk方法:', hasattr(obj, 'talk'))
    
    print('不存在给出默认值:', getattr(obj, 'namexxx', 'default'))
    print('存在返回方法的内存地址:', getattr(obj, 'talk', None))
    print('调用该方法:', getattr(obj, 'talk', None)())
    print('映射属性:', getattr(obj, 'name'))
    
    print('设置obj.ex = male:', setattr(obj, 'sex', 'male'))
    print('查看是否设置成功:', obj.sex)
    print('删除obj中的age属性:', delattr(obj, 'age'))
    print('查看对象的名称空间,是否删除成功:', obj.__dict__)
    
    
    import sys
    
    test = '查看模块是否有某个属性'
    
    def func():
        return '查看模块是否有某个方法'
    
    class s1:
        pass
    
    
    this = sys.modules[__name__]
    
    print(hasattr(this, 's1'))
    print(hasattr(this, 'test'))
    
    print(getattr(this, 'test'))
    print(getattr(this, 'func')())
    
    • 为什么要使用反射?
      • 实现可插机制
      • 动态导入模块
      import importlib
      module1 = 'a'
      # from test import module1
      #用上面的方法导入包会报错,因为import module1不会自动解析成import test;那如何才能import字符串格式的模块名呢?这就是下面动态导入的方法。
      
      module = 'test.a'
      aa = importlib.import_module(module)
      print(aa.C().name)
      #这样就导入了lib包下的aa模块,直接用aa.C()创建一个类C的对象。
      #动态导入模块的作用:根据用户输入的或者从其他地方获取到的字符串来导入需要的模块。
      

    __setattr__、__getattr__、__delattr__

    class Person:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __setattr__(self, key, value):
            """
            给对象赋值时,触发此函数
            :param key:
            :param value:
            :return:
            """
            print(key, value)
            # 误区:self.key = value 这样会造成无限递归。仔细想想。
            self.__dict__[key] = value
    
        def __getattr__(self, item):
            """
            查找属性不存在的值的时候才会触发此函数
            :param item:
            :return:
            """
            return '你查找的属性:%s 不存在' % item
    
        def __delattr__(self, item):
            """
            删除属性时触发此函数
            :param item:
            :return:
            """
    
            self.__dict__.pop(item, None)
    
    
    p = Person('江子牙', 22)
    
    #########__setattr__#########
    p.sex = '男'
    print('执行__setattr__:', p.__dict__)
    
    #########__getattr__#########
    sex = p.sex
    print('不会触发__getattr__:', sex)
    print('原本对象查找不存在的值会报错,但是重写了__getattr__,所以不会报错:', p.weight)
    
    #########__delattr__#########
    del p.se
    print('执行__delattr__:', p.__dict__)
    

    __getattribute__

    • __getattr__比较
    class Person:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __getattribute__(self, item):
            """
            获取属性的时候触发此函数,但是不管属性存不存在,都会执行它
            :param item:
            :return:
            """
            print('执行__getattribute__:', item)
    
            # 两者同时存在,则不会执行__getattr__。除非它抛出异常:raise AttributeError
            # raise AttributeError
            return item
    
        def __getattr__(self, item):
            """
            获取不存在的属性的时候触发此函数
            :param item:
            :return:
            """
            print('执行__getattr__', item)
    
            return item
    
    
    p = Person('江子牙', 21)
    
    print(p.name)
    

    描述符

    • 描述符(__get__、__set__、__del__)是什么:本质就是一个新式类。

    __str__、__repr__

    • __str__:函数或者printh函数-->obj.str()
    • __repr__:交互式解释器-->obj.repr()
    • 注意:这两个是双胞胎,没有定义__str__才使用__repr__。两者必须都返回字符串,否则抛出异常。

    slots

    • slots:是一个类变量,变量值可以是列表、元祖、字典或者可迭代对象。也可以是一个字符串。(意味着所有实例只有一个数据属性)
    • 访问属性,本是用__dict__.(类的字典是共享的,实例的属性是独立的)
    • 为什么要用它:字典会占用大量的内存,如果你有一个属性很少的类。但是有很多实例,为了节省内存可以用__slots__来取代__dict__。
    • 缺点:一旦使用__slots__之后,就不能再给实例添加新的属性,只能用__slots__定义的那些属性名。也不支持多继承的特性。
    class Bar:
        __slots__ = ['name', 'age']
    
    
    b1 = Bar()
    b2 = Bar()
    b1.name = '江子牙'
    b2.name = '王青'
    print(b1.__slots__)
    print(b2.__slots__)
    # b1.sex = '男'       报错,不能添加新的属性
    # print(b1.__dict__)  不再有__dict__了,统一归slots管理,节省内存
    

    __next__、 __iter__实现迭代器协议

    class Foo:
        """
        实现range(start,end)不加步长
        """
    
        def __init__(self, start, end, ):
            self.start = start
            self.end = end
    
        def __iter__(self):
            return self
    
        def __next__(self):
            n = self.start
            if n > self.end - 1:
                raise StopIteration
            self.start += 1
            return n
    
    
    f = Foo(1, 4)
    for i in f:
        print(i)
        
        
    class Foo:
        """
        实现range(start,end,step)加步长
        """
    
        def __init__(self, start, end, step=None):
            self.start = start
            self.end = end
            self.step = step
    
        def __iter__(self):
            return self
    
        def __next__(self):
            n = self.start
            if n > self.end - 1:
                raise StopIteration
            if self.step:
                self.start += self.step
            else:
                self.start += 1
            return n
    
    
    f = Foo(1, 10)
    for i in f:
        print(i)
    

    __doc__

    • 类描述信息
    class A:
        """
        呵呵,用于描述
        """
        pass
    print(A.__doc__)
    

    __module__、__class__

    • __module__:表示当前操作的对象在哪个模块
    • __class__:表示当前操作的对象的类是什么
    class A:
        """
        呵呵,用于描述
        """
        pass
    a = A()
    print(a.__module__)
    print(a.__class__)
    

    __del__

    • 析构方法:当对象在内存中被释放时,自动除法执行。
    # 代码执行完成之后,就会触发__del__
    class A:
    
        def __init__(self, name):
            self.name = name
    
        def __del__(self):
            print('对象的属性%s还在' % self.name)
            print('这里是析构方法')
            print('即将删除')
    
    a = A('jw')
    
    print('----------')
    
    # print(a.name)
    
    • 应用场景:当程序结束时。只会回收自己内存空间。即用户态内存。而操作系统的资源没有被回收,这就需要__del__。

    __call__

    • 对象后面加括号,触发执行
    • 说明:构造方法的执行是由创建对象触发的,即:对象 = 类()。而对于__call__的执行是由对象加括号触发的。即对象.() or 类()()
    class A:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('对象()')
    
    a = A()
    a()
    A()()
    
  • 相关阅读:
    代码、复制[置顶] 跑起来,第一个sshby小雨
    返回、参数了解Javascript函数:parseInt()by小雨
    代码、复制Javascript执行效率小结by小雨
    图片、JQuery学习笔记(图片的展开和伸缩)by小雨
    登录、项目Spring mvc Session拦截器by小雨
    社区、标签jsp中获取状态怎么写?by小雨
    升级、地方LKDBHelper 使用FMDB 对数据库的自动操作by小雨
    广播、应用Android BroadcastReceiver(一)by小雨
    调试、手机手游开发知识(三)--NDK联机调试by小雨
    设置、数值【Cocos2DX 】初窥门径(11)CCUserDefault:保存数据by小雨
  • 原文地址:https://www.cnblogs.com/xjmlove/p/10324922.html
Copyright © 2020-2023  润新知