可能重复:
了解Python装饰器
Python装饰器做什么?在向方法添加装饰器时,我在哪里可以看到正在运行的代码?
例如,当我@login_required在方法的顶部添加时,是否有任何代码替换该行?这行怎么检查用户会话?
我有一份我难以理解的家庭作业.我正在尝试编写一个程序,在第n个数字上输出斐波纳契数列.这是我到目前为止所拥有的:
def fib():
n = int(input("Please Enter a number: "))
if n == 1:
return(1)
elif n == 0:
return(0)
else:
return (n-1) + (n-2)
mylist = range[0:n]
print(mylist)
Run Code Online (Sandbox Code Playgroud)
我想我可以使用单独的函数,但我无法弄清楚如何传递计算斐波纳契数列的参数.然后下一步是打印出该数字的数字序列.
我在python中有大量的自动生成的类,它们实际上代表了部分通信协议的枚举,它们看起来像这样
# definitions.py
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
class AlpacaType(ParamEnum):
Fuzzy = 0
ReallyMean = 1
# etc etc etc
Run Code Online (Sandbox Code Playgroud)
以这种方式定义事物使得自动发生器和人类都可以轻松修改.ParamEnum类提供来自传入网络数据等的所有功能,获取/设置,比较,转换和创建.
但是,这些类需要一些额外的元数据.我不希望添加这个到每个类别中的源定义,虽然,因为它使得它的可读性和将打破自动发生器
目前我正在这样做
# param_enum.py
class ParamEnum(object):
def __init__(self):
self.__class__._metadata = get_class_metadata(self.__class__)
Run Code Online (Sandbox Code Playgroud)
然而,这对我来说有点低效,因为每次我们实例化其中一个枚举(经常发生)时都会发生这种情况,而不仅仅是定义(元数据不会改变,所以它只需要设置一次)
我尝试将其添加到定义文件的底部,但也遇到了问题.
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
for var in locals(): # or globals?
add_metadata(var)
#doesn't work because it is in the same file, modifying dict while iteratng
Run Code Online (Sandbox Code Playgroud)
在定义类时,是否有一种方法在python中覆盖/添加功能,可以继承到子类?理想情况下,我喜欢这样的东西
class ParamEnum(object):
def __when_class_defined__(cls):
add_metadata(cls)
Run Code Online (Sandbox Code Playgroud) 以下函数旨在用作存储已计算值的结果的装饰器.如果之前已经计算过该参数,该函数将返回存储在cache字典中的值:
def cached(f):
f.cache = {}
def _cachedf(*args):
if args not in f.cache:
f.cache[args] = f(*args)
return f.cache[args]
return _cachedf
Run Code Online (Sandbox Code Playgroud)
我意识到(错误地)cache不需要是函数对象的属性.事实上,以下代码也适用:
def cached(f):
cache = {} # <---- not an attribute this time!
def _cachedf(*args):
if args not in cache:
cache[args] = f(*args)
return cache[args]
return _cachedf
Run Code Online (Sandbox Code Playgroud)
我很难理解cache对象如何在多个调用中持久化.我尝试多次调用多个缓存函数,但找不到任何冲突或问题.
任何人都可以帮助我理解cache即使在_cachedf函数返回后变量仍然存在?
查看Flask网站上的默认"Hello world"脚本:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Run Code Online (Sandbox Code Playgroud)
我对编程很新,所以我不明白这个脚本hello()是如何工作的 - 这个函数不会在任何地方调用,所以Flask只显示第一个找到的函数的输出吗?如果我想在页面上显示两个或三个函数的输出怎么办?
我认为自己拥有GoF设计模式的中级知识.但是,在将这些模式分类为结构和行为模式时,我感到困惑.我对创作模式没有任何困惑.
来自维基百科 - 装饰模式 - 在面向对象的编程中,装饰模式是一种设计模式,允许将行为静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为.
从上面的定义可以清楚地看出它是关于行为的
谢谢.
我不确定这是可能的,但有没有办法写出类似的东西
@group_required('group_id')
def myview(request, group_id):
.....
Run Code Online (Sandbox Code Playgroud)
我在哪里查看参数group_id的值,并将此视图的访问权限仅限于此组中的人员?
我知道可以创建一个装饰器来检查某个特定组的成员资格
@group_required('admin')
def myview(request):
....
Run Code Online (Sandbox Code Playgroud)
但是我想要一个只能由某个组内的人访问的视图,这个视图由网址决定.
所以举个例子
/group/1
/group/2
Run Code Online (Sandbox Code Playgroud)
每个人都应该拥有权限,以便只有#X组的成员才能看到该页面.我可以在视图中轻松编写此功能
group = get group
if user not in group
raise 404
Run Code Online (Sandbox Code Playgroud)
但这种逻辑在全世界都在重复.装饰者似乎是一种很有前途的方式,但似乎范围是倒退的.还有另一种处理此类权限的首选方法吗?
谢谢!
def decorator(fn):
def wrapper(*args, **kwargs):
print 'With sour cream and chives!',
return fn(*args, **kwargs)
return wrapper
class Potato(object):
def __call__(self):
print 'Potato @ {} called'.format(id(self))
spud = Potato()
fancy_spud = decorator(Potato())
Run Code Online (Sandbox Code Playgroud)
使用此代码,我们有两个可调用类的实例,一个是装饰的,一个是普通的:
>>> spud()
Potato @ 140408136280592 called
>>> fancy_spud()
With sour cream and chives! Potato @ 140408134310864 called
Run Code Online (Sandbox Code Playgroud)
我想知道是否支持@decorator在一个实例上使用可调用的语法 - 而不是装饰适用于每个实例的类/方法.根据这个流行的答案,@syntax只是糖:
function = decorator(function)
Run Code Online (Sandbox Code Playgroud)
但这是一种过度简化吗?用我所有的半吊子尝试,似乎只有当语法发生前的工作def,class,空格或@another_decorator.
@decorator
baked = Potato()
Run Code Online (Sandbox Code Playgroud)
那是一个SyntaxError.
baked = Potato()
@decorator
baked
Run Code Online (Sandbox Code Playgroud)
还有SyntaxError …
考虑示例:
def func_b(a):
print a
def func_a():
a = [-1]
for i in xrange(0, 2):
a[0] = i
func_b(a)
Run Code Online (Sandbox Code Playgroud)
并尝试测试 func_a 和模拟 func_b 的测试函数:
import mock
from mock import call
def test_a():
from dataTransform.test import func_a
with mock.patch('dataTransform.test.func_b', autospec=True) as func_b_mock:
func_a()
func_b_mock.assert_has_calls([call(0), call(1)])
Run Code Online (Sandbox Code Playgroud)
func_a 执行后,我尝试测试 func_a 是否对 func_b 进行了正确的调用,但由于在 for 循环中我最终改变了列表,我得到:
AssertionError: Calls not found.
Expected: [call(0), call(1)]
Actual: [call([1]), call([1])]
Run Code Online (Sandbox Code Playgroud) 我在 pytest 中遇到了一个非常神秘的错误,在添加了“@pytest.mark.parametrize”装饰器之后,测试开始抛出以下错误:
ValueError: <function ... at ...> uses no argument 'parameters'
Run Code Online (Sandbox Code Playgroud)
我在这里找到了错误的来源
这是我的函数签名的样子(简化):
@patch('dog')
@pytest.mark.parametrize('foo,bar', test_data)
def test_update_activity_details_trainer_and_gear(self, foo, bar, dog):
Run Code Online (Sandbox Code Playgroud) python ×8
decorator ×4
django ×2
conceptual ×1
fibonacci ×1
flask ×1
inheritance ×1
internals ×1
memoization ×1
mocking ×1
permissions ×1
pytest ×1