gpt4 book ai didi

python - 使用装饰器时出错 : decorator() takes 1 positional argument but 2 were given

转载 作者:太空宇宙 更新时间:2023-11-03 21:02:45 25 4
gpt4 key购买 nike

我正在阅读并关注Pro Python书,我使用书中相同的代码创建了这两个装饰器annotation_decoratortypesafe,但是当我尝试运行此代码时,我收到:

TypeError: decorator() takes 1 positional argument but 2 were given

代码与书上的相同,我不明白为什么这会起作用,你们能发现哪里出了问题吗?我在这里托管了 PoC,以防您想测试:https://repl.it/repls/GlassNotedPayware

import functools
import inspect
from itertools import chain


def annotation_decorator(process):
"""
Creates a decorator that processes annotations for each argument passed
into its target function, raising an exception if there's a problem.
"""
@functools.wraps(process)
def decorator(func):
spec = inspect.getfullargspec(func)
annotations = spec.annotations

defaults = spec.defaults or ()
defaults_zip = zip(spec.args[-len(defaults):], defaults)
kwonlydefaults = spec.kwonlydefaults or {}

for name, value in chain(defaults_zip, kwonlydefaults.items()):
if name in annotations:
process(value, annotations[name])

@functools.wraps(func)
def wrapper(*args, **kwargs):
# Populate a dictionary of explicit arguments passed positionally
explicit_args = dict(zip(spec.args, args))
new_args = []
new_kwargs = {}
keyword_args = kwargs.copy()

# Deal with explicit arguments passed positionally
for name, arg in explicit_args:
if name in annotations:
new_args.append(process(arg, annotations[name]))

# Add all explicit arguments passed by keyword
for name in chain(spec.args, spec.kwonlyargs):
if name in kwargs:
new_kwargs[name] = process(keyword_args.pop(name),
annotations[name])

# Deal with variable positional arguments
if spec.varargs and spec.varargs in annotations:
annotation = annotations[spec.varargs]
for arg in args[len(spec.args):]:
new_args.append(process(arg, annotation))

# Deal with variable keyword arguments
if spec.varkw and spec.varkw in annotations:
annotation = annotations[spec.varkw]
for name, arg in keyword_args.items():
new_kwargs[name] = process(arg, annotation)

r = func(*new_args, **new_kwargs)

if 'return' in annotations:
r = process(r, annotations['return'])

return r

return wrapper

return decorator


@annotation_decorator
def typesafe(value, annotation):
"""
Verify that the function is called with the right argument types and
that it returns a value of the right type, according to its annotations
"""
if not isinstance(value, annotation):
raise TypeError("Expected %s, got %s." % (annotation.__name__,
type(value).__name__))

return value


@annotation_decorator
def coerce_arguments(value, annotation):
return annotation(value)


@typesafe(str, str)
def combine(a, b):
return a + b


combine('spam', 'alot')

最佳答案

我根据@chepner 评论修改了两件事:

我没有在 combine 函数上使用 typesafe 装饰器,而是使用 annotation_decorator 传递 typesafe 作为参数进行简单装饰,并且还为函数的变量添加函数注释。

@annotation_decorator(process=typesafe)
def combine(a: str, b: str):
return a + b

关于python - 使用装饰器时出错 : decorator() takes 1 positional argument but 2 were given,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55619394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com