flask上下文相关-LocalStack 对象维护栈

LocalStack 对象维护栈

模拟

import threading

"""
storage = {
   1232: {stack:[123,456]}
}
"""

class Local(object):
    def __init__(self):
        object.__setattr__(self, 'storage', {})

    def __setattr__(self, key, value):
        ident = threading.get_ident()  # 1233
        if ident in self.storage:
            self.storage[ident][key] = value
        else:
            self.storage[ident] = {key: value}

    def __getattr__(self, item):
        ident = threading.get_ident()
        if ident not in self.storage:
            return
        if item not in self.storage[ident]:
            return
        return self.storage[ident][item]


class LocalStack(object):

    def __init__(self):
        self._local = Local()


    def push(self, value):
        """
        将值放入栈
        :param value:
        :return:
        """
        re = self._local.stack
        if re:
            self._local.stack.append(value)
        else:
            self._local.stack = [value,]
        return re

    def pop(self,):
        """
        从栈中拿走值
        :return:
        """
        if not self._local.stack:
            return
        if len(self._local.stack) == 1:
            data = self._local.stack.pop()
            # 当stack中的元素为1时,执行pop操作后,要销毁stack,这里暂时没有做
            return data
        else:
            return self._local.stack.pop()


    def top(self):
        """
        查看栈顶的数据
        :return:
        """
        if not self._local.stack:
            return
        return self._local.stack[-1]



st = LocalStack()
st.push(123)
st.push(456)
a = st.top()
b = st.pop()
b = st.pop()
# # b = st.pop()
a = st.top()
print(b,a)

源码展示

LocalStack部分

class LocalStack(object):
    """This class works similar to a :class:`Local` but keeps a stack
    of objects instead.  This is best explained with an example::

        >>> ls = LocalStack()
        >>> ls.push(42)
        >>> ls.top
        42
        >>> ls.push(23)
        >>> ls.top
        23
        >>> ls.pop()
        23
        >>> ls.top
        42

    They can be force released by using a :class:`LocalManager` or with
    the :func:`release_local` function but the correct way is to pop the
    item from the stack after using.  When the stack is empty it will
    no longer be bound to the current context (and as such released).

    By calling the stack without arguments it returns a proxy that resolves to
    the topmost item on the stack.

    .. versionadded:: 0.6.1
    """

    def __init__(self):
        self._local = Local()

    def __release_local__(self):
        self._local.__release_local__()

    def _get__ident_func__(self):
        return self._local.__ident_func__

    def _set__ident_func__(self, value):
        object.__setattr__(self._local, "__ident_func__", value)

    __ident_func__ = property(_get__ident_func__, _set__ident_func__)
    del _get__ident_func__, _set__ident_func__

    def __call__(self):
        def _lookup():
            rv = self.top
            if rv is None:
                raise RuntimeError("object unbound")
            return rv

        return LocalProxy(_lookup)

    def push(self, obj):
        """Pushes a new item to the stack"""
        rv = getattr(self._local, "stack", None)
        if rv is None:
            self._local.stack = rv = []
        rv.append(obj)
        return rv

    def pop(self):
        """Removes the topmost item from the stack, will return the
        old value or `None` if the stack was already empty.
        """
        stack = getattr(self._local, "stack", None)
        if stack is None:
            return None
        elif len(stack) == 1:
            release_local(self._local)
            return stack[-1]
        else:
            return stack.pop()

    @property
    def top(self):
        """The topmost item on the stack.  If the stack is empty,
        `None` is returned.
        """
        try:
            return self._local.stack[-1]
        except (AttributeError, IndexError):
            return None

猜你喜欢

转载自www.cnblogs.com/jjzz1234/p/12037083.html
今日推荐