python中的装饰器

原理:开头总要先说几句废话

装饰器是一种对闭包的使用方式。通过查看它的 func_closure 属性可以看出函数闭包特性。
真正理解装饰器有这么几个东西一定要透彻理解:

  1. 变量作用域LEGB
  2. 函数是顶级对象

开始升级

level 1:有用没用,先搞它出来一个

1
2
3
4
5
6
7
8
9
def decorator(fn):
def inner(n):
return fn(n) + 1
return inner

# the "@" statement is same as f = decorator(f)
@decorator
def f(n):
return n + 1

level 2: 使用装饰器,帅气的输出信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def wrap_with_prints(fn):
# This will only happen when a function decorated
# with @wrap_with_prints is defined
print('print this when you decorate a function')
def wrapped():
# This will happen each time just before
# the decorated function is called
print('prepare to run %s' % fn.__name__)
# Here is where the wrapper calls the decorated function
fn()
# This will happen each time just after
# the decorated function is called
print('done running %s' % fn.__name__)

return wrapped

@wrap_with_prints
def func_to_decorate():
print('some be wrapped')

func_to_decorate()

level 3 : 哎呀被装饰的函数参数不一样我可怎么办呀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def log_calls(fn):
''' Wraps fn in a function named "inner" that writes
the arguments and return value to logfile.log '''
def inner(*args, **kwargs):
# Call the function with the received arguments and
# keyword arguments, storing the return value

out = fn(*args, **kwargs)

# Write a line with the function name, its
# arguments, and its return value to the log file
print('{} called with args {} and kwargs {}, returning {}\n'.format(fn.__name__, args, kwargs, out))

# Return the return value
return out
return inner

@log_calls
def add(a,b):
return a+b
add(1,2)

level 4:装饰一个还不够,要装饰两次才最好

装饰器可以链式使用,但是一定要注意使用顺序

1
2
3
4
5
6
7
8
9
10
11
12
def b(fn):
return lambda s: '<b>{}</b>'.format(fn(s))

def em(fn):
return lambda s: '<em>{}</em>'.format(fn(s))

@b
@em
def greet(name):
return('Hello, {}!'.format(name))

print(greet("zyt"))

level 5:装饰器也想要个属于人家自己的小参数嘛~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def add_log_out(log_level):
def wrapper(f):
def return_f(*real_para):
"""inner doc
"""
print("[{}]: {} with parameter {}".format(log_level, f.__name__, real_para))
return f(*real_para)

return return_f
return wrapper

# same as "add = add_log_out("INFO")(add)"
@add_log_out("INFO")
def add(a,b):
"""return a + b
"""
return a+b

print(add(1,2))
print(add.__name__)
print(add.__doc__)

level 6:男人有了钱会变坏,函数有了装饰器却不会

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from functools import wraps
def add_log_out(log_level):
def wrapper(f):
@wraps(f)
def return_f(*real_para):
"""inner doc
"""
print("[{}]: {} with parameter {}".format(log_level, f.__name__, real_para))
return f(*real_para)

return return_f
return wrapper

# same as "add = add_log_out("INFO")(add)"
@add_log_out("INFO")
def add(a,b):
"""return a + b
"""
return a+b

print(add(1,2))
print(add.__name__)
print(add.__doc__)

参考:

  1. Python Decorators Overview
  2. 简单 12 步理解 Python 装饰器

Leetcode刷题笔记——DFS

与回溯法的区别:
就目前做的 104 Max Depth of Binary Tree 和 690 Employee Importance 两道easy来看,DFS适用于求标量情况,写成从子节点向上规约的算法,代码极其简洁。而回溯法不受限于求标量,也可以枚举所有解等情况,这种时候回溯法更加适合,但是从代码上来看要较复杂一些,回溯法是一种自顶向下探索的方法。

涉及最短路径的时候,回溯法与BFS更有优势。

Read More

Leetcode刷题笔记——Backtracking

在程序设计中,有相当一类求一组解,或求全部解或求最优解的问题,例如读者熟悉的八皇后问题,不是根据某种特定的计算法则,而是利用试探和回溯的搜索技术求解。回溯法也是设计递归过程的一种重要方法,它的求解过程实质上是一个先序遍历一棵“状态树”的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历过程中。
《数据结构》(严蔚敏)

核心要点

  • 关键思想: 不满足条件就不进入分支
  • 关键变量: path,用path很简洁,但是一个影响思路的地方就是“回溯在哪里”这个问题变得模糊了,因为回溯出现在下层函数返回上层函数过程中,局部变量作为函数环境的自动恢复,如果把path设置为全局变量,那么就需要在进入函数前和返回函数后手动改变全局变量,那样的话思路就会清晰
  • 关键方法:在草稿纸上找一个测试用例画出递归树能够很好的理清思路

套路代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def function():
# initial some environment
# the environment can use global variable to save or just put it as function parameter

# def deeper(path, (environment)):
# return condition
for all possible sub situation:
# change environment

# try to go deeper
deeper(new_path, (environment))

# recover the enviroment

deeper(initial_path)
return

Read More

hexo使用体验

这次转换静态博客引擎,也不算是突发奇想,由于jekyll开始学的时候没有经验,现在维护的文件目录凌乱不堪,于是索性另起炉灶。在静态引擎的选择上,hexo和jekyll可以说是二分天下,然而由于jekyll是github page的官方生成引擎,总会来的更名正言顺一些。然而程序员的圈子向来难以一家独大,hexo以生成快速、中文文档、主题丰富吸引了很多忠实拥趸。我也是由于hexo的搭建快速,迁移方便而下定决心改换于此。

安装

基本的安装过程参考官方文档即可,安装过程中有几个小小甚至不算坑的坑。

Read More

本站总访问量