8

other

somemethod

在python中,还有很多除了前面提过的描述符协议,迭代协议等还有很多有意思的东西。

enterexit

上下文管理协议一般是用来处理像文件读取,socket,线程进程管理等等。上下文管理协议的通用语法和可能的实现方式

with context_manager :
    # block code

with context_manager as context:
    # block code

with A() as a, B() as b:
    # block code

as a class 的上下文管理器

任何一个实现上下文管理协议的对象都可以成为上下文管理器,上下文管理协议主要有两个方法 __enter____exit__

  • __enter__(self): 当进入与这个对象相关的作用域的时候,with声明将会将该方法返回的值绑定到as声明当中,如果有的话
  • __exit__(self, exc_type, exc_value, traceback) : 当该对象的运行已经完成后,那么将执行退出操作,如果正常退出的话,那么三个参数将会为None, 如果有异常被抛出,那么这个方法将会压制异常的传递。
#python3.5
from socket import socket, AF_INET, SOCK_STREAM

class LazyConnection(object):
    def __init__(self, address, family=AF_INET, type=SOCK_STREAM):
        self.address = address
        self.family = family
        self.type = type
        self.connections = []

    def __enter__(self):
        sock = socket(self, family, self.type)
        sock.connect(self.address)
        self.connections.append(sock)
        return sock

    def __exit__(self, exc_ty, exc_val, tb):
        self.connections.pop().close()

from functools import partial
conn = LazyConnection(('www.python.org', 80))
with conn as s1:
    s1.send(b'GET /index.html HTTP/1.0\r\n')
    s1.send(b'Host: www.python.org\r\n')
    s1.send(b'\r\n')
    resp = b''.join(iter(partial(s1.recv, 8192), b''))
    print(resp)
    with conn as s2    
        s2.send(b'GET /index.html HTTP/1.0\r\n')
        s2.send(b'Host: www.python.org\r\n')
        s2.send(b'\r\n')
        resp = b''.join(iter(partial(s2.recv, 8192), b''))
        print(resp)

在一个作用域内的变量是可以传递的,当离开这个作用域的时候,变量因为协议的关系也就释放了。

as a function 的上下文管理器

不得不说,作为一个上下文协议的实现载体,class是很灵活的,但是对于大多数情况而言,太规范了,标准库提供了contextlib来帮助使用上下文管理。其中最有用的部分当属于contextmanager装饰器。它允许你在一个函数中提供上文中的两个方法,由yield声明分离两部分。

#python3.5
from contextlib import contextmanager
@contextmanager
def context_illustration():
    print('entering context')
    try:
        yield
    except Exception as e:
        print('leaving context')
        print('with an error (%s)' % e)
        raise
    else:
        print('leaving context')
        print('with no error')        

new

该方法是一个静态方法,用来创建类实例的。因为它是一个例外,所以不用staticmethod装饰器来处理。这个方法是先于__init__初始化方法的。这个方法需要返回一个实例,可以是任何的类实例。

#python3.5
class Instance:
    in_cre = 0
    def __new__(cls, *args, **kwargs):
        print('__new__ called with ', cls, args, kwargs)
        instance = super().__new__(cls)
        instance.number = cls.in_cre
        cls.in_cre += 1
        return instance

    def __init__(self, attribute):
        print('__init__() called with:', self, attribute)
        self.attribute = attribute

repr

这个函数是用来提供比较易于人阅读的描述

class Repr(object):
    def __init__(self, num):
        self.num = num

    def __repr__(self):
        return '{repr class : }'.format(self.num)
funny-js