python尾递归优化


参考 这里

class TailRecurseException(BaseException):
    def __init__(self, args, kwargs):
        self.args = args
        self.kwargs = kwargs


def tail_call_optimized(g):
    """
    This function decorates a function with tail call
    optimization. It does this by throwing an exception
    if it is it's own grandparent, and catching such
    exceptions to fake the tail call optimization.

    This function fails if the decorated
    function recurses in a non-tail context.
    """

    def func(*args, **kwargs):
        f = sys._getframe()
        # 为什么是grandparent, 函数默认的第一层递归是父调用,
        # 对于尾递归, 不希望产生新的函数调用(即:祖父调用),
        # 所以这里抛出异常, 拿到参数, 退出被修饰函数的递归调用栈!(后面有动图分析)
        if f.f_back and f.f_back.f_back \
            and f.f_back.f_back.f_code == f.f_code:
            # 抛出异常
            raise TailRecurseException(args, kwargs)
        else:
            while 1:
                try:
                    return g(*args, **kwargs)
                except TailRecurseException as e:
                    # 捕获异常, 拿到参数, 退出被修饰函数的递归调用栈
                    args = e.args
                    kwargs = e.kwargs

    func.__doc__ = g.__doc__
    return func

测试

@tail_call_optimized
def factorial(n, acc=1):
    "calculate a factorial"
    from pudb import set_trace
    set_trace()
    if n == 0:
        return acc
    return factorial(n - 1, n + acc)

print factorial(10000)

There are comments.

  • 使用tornado实时输出日志


    import tornado
    from tornado.web import Application
    from tornado.web import RequestHandler
    from tornado.websocket import WebSocketHandler
    import os
    import json
    
    template = '''<!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8"/>
        <title>Document</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://cdn.bootcss.com/jquery …
  • python运行超时设置


    import signal
    
    class TimeoutError(Exception):
        pass
    
    def timeout(seconds=10, error_message="Timer expired"):
        def _timeout(func):
            def _handle_timeout(signum, frame):
                raise TimeoutError(error_message)
    
            def wrapper(*args, **kwargs):
                signal.signal(signal.SIGALRM, _handle_timeout)
                signal.alarm(seconds)
                try:
                    result = func(*args, **kwargs)
                finally:
                    signal.alarm(0)
                return result
    
            return wrapper
    
        return …
  • 时间format输出格式参考


    date --help

    %%一个文字的 %
    %a当前locale 的星期名缩写(例如: 日,代表星期日)
    %A当前locale 的星期名全称 (如:星期日)
    %b当前locale 的月名缩写 (如:一,代表一月)
    %B当前locale 的月名全称 (如:一月)
    %c当前locale 的日期和时间 (如:2005年3月3日 星期四 23:05:25)
    %C世纪;比如 %Y,通常为省略当前年份的后两位数字(例如:20)
    %d按月计的日期(例如:01)
    %D按月计的日期;等于%m …
  • tornado中session实现


    tornado中默认没有session的实现,虽然默认的 set_secure_cookie 已经足够安全了,但更安全的应该是客户端保存session_id,服务端保存对应的信息

    注:保存在redis中的经测试是可以的,保存在内存中的貌似还不行

    给出源码:

    from uuid import uuid4
    from redis import StrictRedis
    from functools import wraps
    from datetime import datetime, timedelta
    from pytz import timezone
    
    
    def singleton(cls):
        instances = {}
    
        @wraps(cls)
        def getinstance(*args, **kw):
            if cls not in instances:
                instances[cls] = cls …