Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何实施";“装饰师”;a中的功能;“类”;对象_Python_Class_Object_Stdout_Decorator - Fatal编程技术网

Python 如何实施";“装饰师”;a中的功能;“类”;对象

Python 如何实施";“装饰师”;a中的功能;“类”;对象,python,class,object,stdout,decorator,Python,Class,Object,Stdout,Decorator,我正在尝试构建一个禁止stdout和stderr的类。我将其用作with语句但我希望扩展该功能,使其也可以用作修饰符,用于禁止函数的输出。是否可以将所有内容完全包含在类中,或者包装器需要是类之外的函数 我试图遵循这些资源,但很难适应我的情况: 作为一名装饰师,我也在努力实现这一功能: @Suppress(show_stdout=True) def f(x, y): print(x, file=sys.stdout) print(y, file=sys.stderr)

我正在尝试构建一个禁止stdout和stderr的类。我将其用作
with语句
但我希望扩展该功能,使其也可以用作修饰符,用于禁止函数的输出。是否可以将所有内容完全包含在类中,或者包装器需要是类之外的函数

我试图遵循这些资源,但很难适应我的情况:

作为一名装饰师,我也在努力实现这一功能:

@Suppress(show_stdout=True)
def f(x, y):
    print(x, file=sys.stdout)
    print(y, file=sys.stderr)
    return x*y
a = f(1,2)
# 1
# a = 2
我有一个类似的装饰师在为
matplotlib
样式的包装器工作(尽管非常难看)。但是,这必须使用外部函数,并且不在类内

# # Decorators
# def stylize(style="seaborn-white"):
#     def decorator(func):
#         @functools.wraps(func)
#         def wrapper(*args, **kwargs):
#             with plt.style.context(style):
#                 return func(*args, **kwargs)
#         return wrapper
#     return decorator
# # Wrappers
# def subplots_wrapper(style="seaborn-white", *args, **kwargs):
#     @stylize(style)
#     def inner_wrapper(*args, **kwargs):
#         return plt.subplots(*args, **kwargs)
#     return inner_wrapper(*args, **kwargs)

如果您只使用带self的
而不使用参数,则此功能有效:

   def __call__(self, function):

        @functools.wraps(function)
        def decorated(*args, **kwargs):
            with self:
                return function(*args, **kwargs)
        return decorated

您可以通过组合
contextlib
中的各种片段来定义它。简而言之,它使用
ExitStack
将请求的重定向上下文管理器组合到单个上下文管理器中,并使用
ContextDecorator
将生成的上下文管理器也用作decorator

from contextlib import ExitStack, ContextDecorator, redirect_stdout, redirect_stderr
import sys
from os import devnull


class Suppress(ContextDecorator, ExitStack):
    def __init__(self, show_stdout=False, show_stderr=False, **kwargs):
        super().__init__(**kwargs)
        self.redirections = []
        if show_stdout:
            self.redirections.append(redirect_stdout)
        if show_stderr:
            self.redirections.append(redirect_stderr)

    def __enter__(self):
        rv = super().__enter__()

        if self.redirections:
            f = rv.enter_context(open(devnull, "w"))
            for r in self.redirections:
                rv.enter_context(r(f))
        return rv
\uuuu init\uuuu
存储列表中所需的类
重定向\u stdout
重定向\u stderr


\uuuu输入\uuuu
,如果请求了任何重定向,则打开相应的接收器并进行相应的重定向。作为一个退出堆栈,
Suppress
将负责确保重定向结束并且接收器将关闭。

您不能只定义
\u调用()
在类上,并将您的decorator代码放在那里?有一个
contextlib.ContextDecorator
您可能希望从中继承。
contextlib
还提供
redirect\u stdout
redirect\u stderr
管理器。@MarkMeyer我已经更新了调用方法,但现在得到:
TypeError:decorator()接受1个位置参数,但给出2个
这很复杂,但很短。看我的答案。如此接近…但如此遥远。非常感谢。
from contextlib import ExitStack, ContextDecorator, redirect_stdout, redirect_stderr
import sys
from os import devnull


class Suppress(ContextDecorator, ExitStack):
    def __init__(self, show_stdout=False, show_stderr=False, **kwargs):
        super().__init__(**kwargs)
        self.redirections = []
        if show_stdout:
            self.redirections.append(redirect_stdout)
        if show_stderr:
            self.redirections.append(redirect_stderr)

    def __enter__(self):
        rv = super().__enter__()

        if self.redirections:
            f = rv.enter_context(open(devnull, "w"))
            for r in self.redirections:
                rv.enter_context(r(f))
        return rv