抽象基类
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() # 清理内存
网友评论