装饰器工厂参数是静态值,而不是变量的值

时间:2019-06-27 06:17:03

标签: python

所以我有

# my decorator factory
def execute_in(directory):  # <-- I want this to be a variable's value which can change
    def decorator(function):
        def wrapper(*args, **kwargs):
            os.chdir(directory)
            print(directory)  # currently is printing None which is my problem
            value = function(*args, **kwargs)
            os.chdir(home_dir)
            return value
        return wrapper
    return decorator

# a function that runs after assigning General.archive_dir a value
@execute_in(General.archive_dir)
def get_data():
  print(General.archive_dir)  # will print the correct directory name
  with open('data.csv', 'r') as f:
      rows = [row for row in csv.reader(f, delimiter=',')]
  return rows

我的问题是装饰器工厂使用的变量General.archive_dir的值是在程序启动时实例化的,当其值为None时。我希望它在调用装饰函数时使用General.archive_dir的值。我该怎么办?

如果这个问题不清楚,我深表歉意。如果可以的话,请让我知道如何在需要时进行澄清。

2 个答案:

答案 0 :(得分:2)

一种解决方案是使用@execute_in调用lambda

directory内的

wrapper将成为一个函数,该函数在调用时将返回当前值。

archive_dir = None

# decorator factory
def execute_in(directory_path_getter):
    def decorator(function):
        def wrapper(*args, **kwargs):
            print('from wrapper:', directory_path_getter())  # Notice the function call
            value = function(*args, **kwargs)
            return value
        return wrapper
    return decorator

@execute_in(lambda: archive_dir)
def get_data():
    ...

archive_dir = 'some directory'

print(get_data())

打印:

from wrapper: some directory
from get_data: some directory
['some data']

答案 1 :(得分:1)

如果严格不需要装饰器,则上下文管理器还可以完成临时更改目录的任务。

import os
from contextlib import contextmanager

@contextmanager
def execute_in(directory):
    orig_dir = os.getcwd()
    os.chdir(directory)

    try:
        yield
    finally:
        os.chdir(orig_dir)

使用上下文管理器可以在一种方法中多次更改目录,并且可以嵌套。

settings = {
    'archive_dir': './dir'
}

def get_data():
    print(os.getcwd())

    with execute_in(settings['archive_dir']):
        print('    ' + os.getcwd())

        with execute_in('bin'):
            print('        ' + os.getcwd())

        print('    ' + os.getcwd())

    print(os.getcwd())

运行时

>>> get_data()
/home/they4kman/.PyCharm2019.2/config/scratches
    /home/they4kman/.PyCharm2019.2/config/scratches/dir
        /home/they4kman/.PyCharm2019.2/config/scratches/dir/bin
    /home/they4kman/.PyCharm2019.2/config/scratches/dir
/home/they4kman/.PyCharm2019.2/config/scratches