美文网首页
Python类和对象(高级编程一,二)

Python类和对象(高级编程一,二)

作者: 冷煖自知 | 来源:发表于2020-01-02 12:56 被阅读0次

    抽象基类

    import abc
    
    class Person(metaclass=abc.ABCMeta): # 只能被继承,不能实例化,实例化会报错
        @abc.abstractmethod # 被修饰的方法必须重写
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
      
    

    TIP:为了解决Python2&3的兼容问题,需要引入six模块,该模块中有一个针对类的装饰器 @six.add_metaclass(MetaClass) 可以为两个版本的Python类方便地添加metaclass

    import abc
    import six
    
    
    @six.add_metaclass(abc.ABCMeta)
    class Person(object):
        @abc.abstractmethod
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
    

    对象比较(isinstance和type)

    type()不会认为子类是一种父类类型
    isinstance()会认为子类是一种父类类型
    isinstance可以判断子类实例对象是属于父类的;而type会判断子类实例对象和父类类型不一样
    type只接收一个参数,不但可以判断变量是否属于某个类型,而且可以得到参数变量未知的所属的类型;而isinstance只能判断是否属于某个已知类型,不能直接得到变量未知的所属的类型

    # coding=UTF-8
    >>> a = 4
    >>> isinstance (a,int)
    True
    >>> isinstance (a,str)
    False
    >>> isinstance (a,(str,int,list))#与元组类型之一相同
    True
    >>> isinstance(a,(str,list,float))#与元组类型都不相同
    False
    
    # coding=UTF-8
    class father(object):
        pass
    class son(father):
        pass
    >>>a=father()
    >>>b=son()
    >>>isinstance(a,father)
    True
    >>>type(a)==father
    True
    >>>isinstance(b,father)#isinstance得到子类实例是属于父类的
    True
    >>>type(b)==father#type对于子类实例判断不属于父类
     False
    
    # coding=UTF-8
    class A(object):
        pass
    >>>a=A()
    #type判断变量是否属于某个类型
    >>>type(a)==A
    True
    #type得到变量类型
    >>>type(a)
     __main__.A
    #isinstance只能判断变量是否属于某个类型
    >>>isinstance(a,A)
    True
    

    类属性和实例属性以及查找顺序

    Python2.2之前的算法:金典类
    Python2.2版本之后,引入了BFS(广度优先搜索)
    在Python2.3之后,Python采用了C3算法
    C3算法
    可通过类调用mro()获取查找顺序


    自省机制

    dir()

    dir() 函数可能是 Python 自省机制中最著名的部分了。它返回传递给它的任何对象的属性名称经过排序的列表。如果不指定对象,则 dir() 返回当前作用域中的名称。

    type()

    type() 函数有助于我们确定对象是字符串还是整数,或是其它类型的对象。它通过返回类型对象来做到这一点,可以将这个类型对象与 types 模块中定义的类型相比较

    hasattr()

    对象拥有属性,并且 dir() 函数会返回这些属性的列表。但是,有时我们只想测试一个或多个属性是否存在。如果对象具有我们正在考虑的属性,那么通常希望只检索该属性。这个任务可以由 hasattr() 和 getattr() 函数来完成.

    isinstance()

    可以使用 isinstance() 函数测试对象,以确定它是否是某个特定类型或定制类的实例


    派生内置不可变类型并修改其实例化行为

    class IntTuple(tuple):
        def __new__(cls, *args, **kwargs):
            f = (i for i in args if isinstance(i, int) and (i > 0))
            return super().__new__(cls, f)
    

    创建大量实例节省内存

    在python新式类中,可以定义一个变量slots,它的作用是阻止在实例化类时为实例分配dict,默认情况下每个类都会有一个dict,通过dict访问,这个dict维护了这个实例的所有属性。
    由于每次实例化一个类都要分配一个新的dict,因此存在空间的浪费,因此有了slots
    slots是一个元组,包括了当前能访问到的属性。
    当定义了slots后,slots中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明,
    类的实例只能拥有slots中定义的变量,不能再增加新的变量。注意:定义了slots后,就不再有dict

    class Person(object):
        __slots__ = ('name', 'age')
    
        def __init__(self):
            self.name = "None"
            self.age = 10
    

    TIP:使用slots要注意,slots定义的属性仅对当前类起作用,对继承的子类是不起作用的


    Python中的with语句

    with open('image.png','r') as f:
      f.read()
    
    contextlib简化上下文管理器
    class OpenContext(object):
        def __init__(self, filename, mode):
            self.fp = open(filename, mode)
    
        def __enter__(self):
            return self.fp
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.fp.close()
    
    if __name__ == '__main__':
        with OpenContext('abc.txt', 'w') as file:
            file.write("hello world")
    

    可以使用@contextmanager修饰类

    from contextlib import contextmanager
    
    @contextmanager
    class OpenContext(object):
        def __init__(self, filename, mode):
            fp = open(filename, mode)
            print("file open")
            try:
                yield fp
            finally:
                fp.close()
    

    创建可管理的对象属性

    可使用property管理属性

    class Person:
        def __init__(self):
            self.__age = 10
    
        def age(self):
            return self.__age
    
        def set_age(self, age):
            if not isinstance(age, int):
                raise TypeError("TypeError")
            self.__age = age
    
        def del_age(self):
            self.__age = None
    
        age = property(fget=age, fset=set_age, fdel=del_age)
    
    if __name__ == '__main__':
        p = Person()
        p.age = 33
        print(p.age)
    

    让类支持比较操作

    from functools import total_ordering
    
    @total_ordering
    class Rect(object):
        def __init__(self, w, h):
            self.w = w
            self.h = h
    
        def area(self):
            return self.w * self.h
    
        def __lt__(self, other): # 重写小于方法,可以自动实现大于方法
            return self.area() < other.area()
    
        def __eq__(self, other): # 等于方法
            return self.area() == other.area()
    

    在环状数据结构中管理内存

    使用weakref修饰后引用计数不增加

    import weakref
    
    a = A()
    a2 = weakref.ref(a)
    

    Python 垃圾回收机制

    获取内存占用方法
    import os
    import psutil
    
    # 显示当前 python 程序占用的内存大小
    def show_memory_info(hint):
        pid = os.getpid()
        p = psutil.Process(pid)
        
        info = p.memory_full_info()
        memory = info.uss / 1024. / 1024
        print('{} memory used: {} MB'.format(hint, memory))
    
    循环引用解决

    获取引用关系

    import objgraph
    
    a = [1, 2, 3]
    b = [4, 5, 6]
    
    a.append(b)
    b.append(a)
    
    objgraph.show_refs([a])
    

    objgraph.show_refs(d, filename=’sample-graph.png’)
    dot转图片

    清除没有引用的对象

    import gc
    
    gc.collect() # 清理内存
    

    相关文章

      网友评论

          本文标题:Python类和对象(高级编程一,二)

          本文链接:https://www.haomeiwen.com/subject/kxanoctx.html