面向对象进阶(二)
一、item系列:getitem、_setitem__和__delitem_
二、类的特殊变量:_slots_
三、迭代器协议:_iter__和__next_
四、_module__和__class_
五、类的描述信息:_doc_
六、析构方法:_del_
七、_enter__和__exit_
八、call
九、元类
item系列:
- 把对象操作属性模拟成字典的格式
class Foo:
def __init__(self, name):
self.name =name
def __getitem__(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
self.__dict__.pop(key)
f = Foo('egon')
print(f['name'])
f['age'] = 18
print(f.__dict__)
del f['age']
print(f.__dict__)
二、slots
- 属于类的变量,类型可以是列表、元组、可迭代对象字符串
- 在类中声明好__slots__变量后,可以直接通过对象调用
- 同时,对象也无法添加新的变量
class Foo():
__slots__ = ['a','b','c']
f = Foo()
f.a = 1
f.b = 2
f.c = 3
print(f.a,f.b,f.c)
print(f.__dict__)
三、迭代器协议:iter__和__next
迭代器的定义:
- 只要对象本身有__iter__方法,那对象就是可迭代的;
- 调用iter()或者__iter__方法可以将列表、元组等变成迭代器;
- 调用next()或者__next__方法可以将返回迭代器中的每一个元素;如果对象具有__iter__方法,说明该对象是可迭代对象
以下定义类时,通过在类中增加__iter__和__next__方法,实例化的对象就是可迭代的:
class Foo:
def __init__(self, start):
self.start = start
def __iter__(self):
return self
def __next__(self):
if self.start >10:
raise StopIteration
n = self.start
self.start += 1
return n
f = Foo(0)
print(next(f))
print(next(f))
for i in f:
print(i)
举例:使用__iter__和__next__实现range()方法:
class my_range:
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.start > self.end:
raise StopIteration
n = self.start
self.start += 1
return n
for i in my_range(0,3):
print(i)
四、module__和__class
module 表示当前操作的对象属于哪个模块
class 表示当前操作的对象属于哪个类
五、doc
doc 类的描述信息,而且无法被继承
六、析构方法:del
- 当对象在内存中被释放时,自动触发本方法
- 属于解释器在函数内部垃圾回收时自动执行的方法
举例:根据之前使用授权方式(自定义数据类型方式之一),自定义的open()方法,可以应用析构方法__del__进行优化,当调用的方法结束后自动关闭文件
class Open:
def __init__(self, file_path, mode = 'r', encoding = 'utf8'):
self.f = open(file_path, mode = mode, encoding = encoding)
def write(self, value):
self.f.write(value)
def __del__(self):
self.f.close()
print('---del')
f = Open('a.txt','w')
f.write('abgc')
def f #此处不调用def f也可以,因为会自动调用__del__
七、enter__和__exit
- 上下文管理协议:就是在文件操作经常用到with open() as f中的with语句
- 如果对象要兼容with语句,需要在对象的类中声明__enter__和__exit__方法
- 其中,在实例化对象前出现with时,对象的__enter__方法被调用,并将返回值赋值给as后的变量(文件句柄)
- 其中,with中的代码执行完毕或者代码抛异常时执行__exit__方法
- __exit__中的三个参数分别代表异常类型、异常值和追述信息,当with代码块缩进的代码出现问题,抛出异常,则with代码块中后面的代码无法被执行
- __exit__中的参数可以设置抛出异常内容,并返回True,相当于自行处理异常内容,不影响with代码中后面的代码执行
举例:自定义的open()方法,也可以使用__enter__和__exit__方法来实现上下文管理协议,获取文件句柄通过__enter__,当with代码执行完毕后调用__exit__关闭文件
class Open:
def __init__(self, file_path, mode = 'r', encoding = 'utf8'):
self.f = open(file_path, mode=mode, encoding=encoding)
def __enter__(self):
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with Open('a.txt','r') as a:
for i in a:
print(i)
八、call
对象加括号,触发执行。
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('This is call')
f = Foo()
f() #对象加括号执行,结果:This is call
九、元类
- 类是元类的对象,可以利用元类来控制类的行为
#type称为元类,是所有类的类,利用type模拟class关键字的创建过程
def run(self):
pass
class_name = 'Spam'
class_base = (object,)
class_dict = {
'x': 1,
'run':run
}
bar = type(class_name,class_base,class_dict)
print(bar)
print(type(bar))
print(bar.__dict__)
#class封装了以上类的创建过程
class spam:
pass
print(spam)
print(type(spam))
print(spam.__dict__)
#利用type创建一个空类cls赋值给对象aaa
aaa = type('cls',(),{})
print(aaa)
print(type(aaa))
print(aaa.__dict__)