• Python类的内置方法


    一、类的type

    class A:pass
    
    print(type(A))              # <class 'type'>
    print(type(object))         # <class 'type'>
    print(type(type))           # <class 'type'>

    ① 所有的对象的type都是创造这个对象类

    ② 所有没有指定metaclass的类的type都是type

    ③ 指定了metaclass,这个类的type就是指定的metaclass的值

    ④ 类也是被创造出来的,type是创造类的机制,即元类是创造类的机制

    所有的对象的type都是创造这个对象类

    class A:pass
    
    a = A()
    print(type(a) is A)         # True

    所有没有指定metaclass的类的type都是type

    class A():pass
    print(type(A))              # <class 'type'>

     指定了metaclass,这个类的type就是指定的metaclass的值

    from abc import ABCMeta
    class A(metaclass=ABCMeta):pass
    print(type(A))                      # <class 'abc.ABCMeta'>

    类也是被创造出来的,type是创造类的机制,即元类是创造类的机制

    print(type(type) is type(object))       # True,type和object的type都是 <class 'type'>
    print(isinstance(type,object))          # True,type和object都属于<class 'type'>
    print(isinstance(object,type))          # True,type和object都属于<class 'type'>
    
    print(issubclass(type,object))          # True,type是object的子类
    print(issubclass(object,type))          # False

    二、__new__  构造方法

    __new__ :构造方法,类实例化对象第一步创建了一个对象空间,这个对象空间是由__new__来创建的,继承object的__new__方法

    __init__:初始化方法

    类实例化对象的时候,先执行的 __new__,再执行__init__。

    类实例化对象的内存机制:

    实例化对象先执行__new__方法,但是类里没有__new__的方法,到父类object中去找到__new__方法并执行,开辟了属于对象的空间,这时才开始执行__init__方法,把self参数传进去才是刚才创造的空间。

    整个过程把类比作模板,创造对象比作捏泥像,__new__方法是捏出来泥像,__init__是给泥像装饰。

    class A:
        def __init__(self):                     # 初始化方法
            print('执行初始化方法')
        def __new__(cls, *args, **kwargs):      # 构造方法
            print('执行构造方法')
            return object.__new__(cls)
    
    a = A()
    
    '''
    执行构造方法
    执行初始化方法
    '''

    三、单例模式

    关于设计模式:

    常用有23种设计模式,源于Java,为了规范java的开发。

    python一种是推崇设计模式,另一种是贬低设计模式。

    单例模式:一个类无论实例化多少次,都只有一个对象,只开辟一个空间,这种就是单例模式。

    单例模式下,创造的对象的属性是最后一个对象的属性,一直再赋值。

    class City:
        __initialize = 0                            # 静态属性
        def __init__(self,city):
            self.city = city
    
        def __new__(cls, *args, **kwargs):
            if not cls.__initialize:
                cls.__initialize = object.__new__(cls)      # 把对象空间地址赋值静态属性
            return cls.__initialize
    
    gz = City('广州')
    sz = City('深圳')
    print(gz,sz)
    print(gz.city,sz.city)
    
    '''
    <__main__.City object at 0x0000022B2DCBC6A0> <__main__.City object at 0x0000022B2DCBC6A0>
    深圳 深圳
    '''

    四、__del__ 析构方法

    ① 析构方法是销毁对象时会调用__del__方法,执行del就会触发__del__的方法

    ② 在删除这个类创建的对象的时候会先触发这个方法,再删除对象,主要是做清理的工作,需要手动归还资源给操作系统,比如:关闭文件,关闭网络的连接,关闭数据库的连接等。

    ③ 无论是手动删除对象还是程序结束自动删除对象,本质上都是执行del 对象,只要调用del 对象,就会触发__del__方法

    ④ 构造方法和析构方法是一对的

    class A:
        def __init__(self,name):                # 初始化方法
            self.name = name
            print(self.name)
            print('执行初始化方法1')
        def __new__(cls, *args, **kwargs):      # 构造方法
            print('执行构造方法!')
            return object.__new__(cls)
        def __del__(self):                      # 析构方法
            print('执行析构方法!')
    
    
    a = A('苹果')
    print('-----分割线-----')
    
    '''
    执行构造方法!
    苹果
    执行初始化方法1
    -----分割线-----
    执行析构方法!
    '''

    总结:初始化对象先执行__new__方法,再执行__init__方法,然后把self传进去,执行__init__的内容,当整个程序执行完自动删除对象,触发了__del__方法,执行__del__方法的内容。

    五、__len__ 方法

    ① 所有使用len()的数据类型都有__len__的方法,使用len()的数据类型:str,list,dict,tuple,set

    ② 只要在类中定义__len__方法,并且方法内return整数,就能使用len(对象)

    ③ 若要统计对象的长度,定义__len__的方法比较好

    class Fruits:
        def __init__(self,name):
            self.name = name
            self.fruit_lis = []
    
        def __len__(self):
            return len(self.fruit_lis)
    
    durian = Fruits('榴莲')
    durian.fruit_lis.append('苹果')
    durian.fruit_lis.append('番茄')
    durian.fruit_lis.append('西瓜')
    durian.fruit_lis.append('雪梨')
    durian.fruit_lis.append('香蕉')
    ret = len(durian)
    print(ret)                               # 5

    六、__eq__ 方法

    ① __eq__方法判断对象是否相等,但是object类的__eq__方法是通过对象的内存地址判断是否相等

    ② __eq__方法 有时会配合__hash__方法使用,判断对象里的对象属性是否相等

    ③ obj.__eq__(obj2) 相当于 obj == obj2

    class City:
        def __init__(self,city):
            self.city = city
    
    
        def __eq__(self, other):
            return self.__dict__ == other.__dict__
    
    c1 = City('广州')
    c2 = City('广州')
    print(c1.__eq__(c2))          # 调用类的__eq__方法
    print(c1 == c2)               # 调用类的__eq__方法
    print(c1,c2)                  # 对象空间的地址
    
    '''
    True
    True
    <__main__.C

    七、__hash__ 方法

    默认的__hash__()继承自对象本身,返回一个基于对象的内部ID值。

    相同的hash值:这意味着两个对象可能是相等的。该hash值为我们提供了一个快速检查对象相等的可能性。如果hash值是不同的,两个对象不可能是相等的,他们也不可能是相同的对象。至关重要的是,内部ID和默认__hash__()方法间有一种强联系。

    等号比较:这意味着hash值也一定相等。这是==操作符的定义。对象可能是相同的对象。

    相同的IDD:这意味着他们是同一个对象。进行了等号比较且有相同的hash值。这是is操作符的定义。

    然而,反过来是不正确的。对象可以有相同的hash值但比较是不相等的。在创建集合或字典时导致一些预计的处理开销是正当的。我们不能确切的从更大的数据结构创建不同的64位hash值。将有不相等的对象被简化为一致相等的hash值。

    特点:

    ① 每次执行的哈希值都会变化

    ② 在一次执行哈希的过程中,对同一个值的hash结果总是不变的

    字典寻址快的原因是运用了哈希算法,比二分查找快。

    字典在内存中的存储方式:

      每存储在内存的数据都有一个内存地址,字典会对键key进行哈希hash(key),把值放在hash的对应地址,所以字典的键是可哈希的

    hash算法的特点:

    ① 对于相同的值在一次程序的运行中是不会变化的

    ② 对于不同的值在一次程序的运行中总是不同的

    set的去重机制:

    ① 对每一个元素进行hash,计算出一个内存地址

    ② 到这个内存地址上查看,如果这块内存中没有值,将这个元素存到对应的内存地址上

    ③ 到这个内存地址上查看,如果这块内存中有值,判断这两个值是否相等。如果相等就舍弃后面的值,如果不相等就二次寻址,再找一个新的空间来存储这个值

    自定义__hash__和__eq__方法

    class Fruits:
        def __init__(self,name):
            self.name = name
    
        def __hash__(self):
            return hash(self.name)
    
        def __eq__(self, other):
            return self.__dict__ == other.__dict__
    
    fruits_lis = ['apple','orange','banana']
    obj_lis = []
    for i in range(9):
        name = Fruits(fruits_lis[i%3])
        obj_lis.append(name)
    print(obj_lis)
    print('-'*100)
    ret = set(obj_lis)
    print(ret)
    
    '''
    [<__main__.Fruits object at 0x000001A5EF92C6D8>, <__main__.Fruits object at 0x000001A5EF9373C8>, <__main__.Fruits object at 0x000001A5EF9370F0>, <__main__.Fruits object at 0x000001A5EF937400>, <__main__.Fruits object at 0x000001A5EF937470>, <__main__.Fruits object at 0x000001A5EF937518>, <__main__.Fruits object at 0x000001A5EF937550>, <__main__.Fruits object at 0x000001A5EF937588>, <__main__.Fruits object at 0x000001A5EF9375C0>]
    ----------------------------------------------------------------------------------------------------
    {<__main__.Fruits object at 0x000001A5EF9370F0>, <__main__.Fruits object at 0x000001A5EF92C6D8>, <__main__.Fruits object at 0x000001A5EF9373C8>}
    
    '''
  • 相关阅读:
    《第一行代码》阅读笔记(十四)——ViewPager
    《第一行代码》阅读笔记(十三)——碎片的最佳案例
    《第一行代码》阅读笔记(十二)——探究碎片
    《第一行代码》阅读笔记(十一)——编写界面的最佳案例
    《第一行代码》阅读笔记(十)——RecyclerView
    《第一行代码》阅读笔记(九)——ListView
    《第一行代码》阅读笔记(八)——自定义控件
    《第一行代码》阅读笔记(七)——Android经典四种布局
    《第一行代码》阅读笔记(六)——AndroidUI控件(初级)
    后台管理系统左侧菜单栏显示隐藏
  • 原文地址:https://www.cnblogs.com/st-st/p/9581244.html
Copyright © 2020-2023  润新知