3、黑魔法杂货铺

装饰器

# 验证session的装饰器, 在web框架中可以重复使用
def authForm(func):
    def wrapper(request, *args, **kwargs):
        if request.session.get['username']:
            return func(request, *args, **kwargs)
        else:
            return render(request, 'login.html')

    return wrapper

# 为函数执行前和函数执行后增加功能的装饰器
def filter(before_func, after_func):
    def outer(main_func):
        def wrapper(request, *args, **kwargs):
            before_result = before_func(request, *args, **kwargs)
            if before_func != None:
                return before_result

            main_result = main_func(request, *args, **kwargs)
            if main_result != None:
                return main_result

            after_result = after_func(request, *args, **kwargs)
            if after_result != None:
                return after_result

        return wrapper()

    return outer()

#==========两个实用的Python的装饰器实例=========#
# 第一式:超时函数
'''这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,
这个功能在编写外部API调用 、网络爬虫、数据库查询的时候特别有用。timeout装饰器的代码如下:'''
# 下面会用到signal, functools两个库, 定义一个Exception,后面超时抛出
class TimeoutError(Exception):
    pass

def timeout(seconds, error_message = 'Function call timed out'):

    def decorated(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 functools.wraps(func)(wrapper)
    return decorated

# 使用:限定下面的slowfunc函数如果在5s内不返回就强制抛TimeoutError Exception结束
@timeout(5)
def slowfunc(sleep_time):
    time.sleep(sleep_time)  #这个函数就是休眠sleep_time秒

slowfunc(3)     #sleep 3秒,正常返回没有异常
slowfunc(10)    #被终止

# 第二式:Trace函数
'''有时候出于演示目的或者调试目的,我们需要程序运行的时候打印出每一步的运行顺序和调用逻辑。
类似写bash的时候的bash -x调试功能,然后Python解释器并没有内置这个十分有用的功能。
Trace装饰器的代码如下:'''
def trace(f):

    def globaltrace(frame, why, arg):
        if why == "call":
            return localtrace
        return None

    def localtrace(frame, why, arg):
        if why == "line":
            # record the file name and line number of every trace
            filename = frame.f_code.co_filename
            lineno = frame.f_lineno
            bname = os.path.basename(filename)
            print("{}({}): {}".format(bname,lineno,linecache.getline(filename, lineno)),)
        return localtrace

    def _f(*args, **kwds):
        sys.settrace(globaltrace)
        result = f(*args, **kwds)
        sys.settrace(None)
        return result

    return _f

# 使用:
@trace
def xxx():
    print(1)
    print(22)
    print(333)
decorator

闭包

def make_addr(adden):
    def addr(args):
        return args + adden
    return addr

m1 = make_addr(23)
m2 = make_addr(44)

>>> print(m1(100))
123
>>> print(m2(100))
144
closure

反射

class Student(object):

    @property
    def birth(self):
        return self._birthday

    @birth.setter
    def birth(self, birthday):
        self._birthday = birthday

s = Student()
s.birth = 29
print(s.birth)


# 下面这个例子更加清楚简洁的使用了__getattr__和__setattr__
# JsonDict继承dict类,重写dict类__getattr__和__setattr__方法
class JsonDict(dict):

    def __init__(self, **kw):
        super().__init__(**kw)

    def __getattr__(self, attr):
        try:
            return self[attr]
        except KeyError:
            raise AttributeError(r"'JsonDict' object has no attribute '%s'" % attr)

    # 可以重写dict,使之通过"."调用
    def __setattr__(self, attr, value):
        self[attr] = value

j = JsonDict(name='python', age='28')
print(j)
print(j.name)
print(j.age)

"""现在很多网站都搞REST API,比如新浪微博、豆瓣啥的,调用API的URL类似:
http://api.server/user/friends
http://api.server/user/timeline/list
如果要写SDK,给每个URL对应的API都写一个方法,那得累死,而且,API一旦改动,SDK也要改。
利用完全动态的__getattr__,我们可以写出一个链式调用:"""

class Chain(object):

    def __init__(self, path=''):
        self._path = path

    # 所有Chain.xx的方法都能通过,可以使用raise AttributeError可以限制传入的参数
    def __getattr__(self, path):
        return Chain('%s/%s' % (self._path, path))

    def __str__(self):
        return self._path

    __repr__ = __str__

    def test(self):
        pass


# 测试结果如下:
"""
>>> Chain().status.user.timeline.list
'/status/user/timeline/list'
>>> Chain(http://api.server).status.user.timeline.list
'http://api.server/status/user/timeline/list'
"""

c = Chain()
print(hasattr(c, 'best'))
print(getattr(c, 'best'))
reflex
原文地址:https://www.cnblogs.com/raykuan/p/6130015.html