面向对象进阶(二)

一、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__)

举例:创建元类Mymeta,Foo继承Mymeta,元类中对继承Mymeta的类是否写注释__doc__做了限制:

3FC53F9435B60B5B700F7F61CA77B8

posted @ 2017-04-25 17:34  六神酱  阅读(166)  评论(0编辑  收藏  举报