【问题标题】:How can I pass key-value to decorator in python?如何将键值传递给python中的装饰器?
【发布时间】:2020-06-17 04:07:44
【问题描述】:

我正在尝试验证字典参数。

import logging
import os
# decorator
def file_validator(f):
    def wrapped(*args):
        """
        Once there is passed values,
        file_path = os.path.join(path_info, file_info)
        if os.path.exists(file_path):
            logging.info('{} exists'.format(file_info))
        else:
            logging.info('{} does not exist'.format(file_info))
        """

# original function
@file_validator
def original_function(file_dict):
    # pass only specific element to file_validator decorator for checking
    # for example only "pathA": "/files", "fileA": "bar.csv"

sample_dict = {"pathA": "/files", "fileA": "bar.csv", "fileB": "hello.txt"}
original_function(sample_dict)

有没有办法使用装饰器检查这种方式?
编辑 这可能相当于我想要做的。

def file_validator(filepath, filename):
    file_path = os.path.join(filepath + filename)
    if os.path.exists(file_path):
        logging.info('{} exists'.format(filename))
    else:
        logging.info('{} does not exist'.format(filename))

def original_function(file_dict):
    file_validator(file_dict['pathA'], file_dict['fileA'])
    file_validator(file_dict['pathA'], file_dict['fileB'])

sample_dict = {"pathA": "/files", "fileA": "bar.csv", "fileB": "hello.txt"}
original_function(sample_dict)

【问题讨论】:

  • 请看stackoverflow.com/questions/5929107/decorators-with-parameters。如果需要帮助,请告诉我们
  • @HArdRese7 我编辑了,因为我认为我的问题不清楚。我也检查了那个链接,但我觉得它没有太大关系??
  • 您可以将您的 dict 作为输入传递给装饰器函数并实现您想要的。装饰器可用于修改函数行为,但不能用于修改传递给函数的参数。您可以使用这些类并实现相同的功能(如果您有兴趣,请查看 Django 的类级装饰器实现)

标签: python decorator


【解决方案1】:

似乎这样的事情应该可以解决问题:

import os
import logging

def file_validator(func):
    def wrapper(file_dict:dict):
        
        # Turn file_dict to two lists:
        #   paths = ["/files"]
        #   files = ["bar.csv", "hello.txt"]
        paths = [
            path 
            for name, path in file_dict.items() 
            if name.startswith("path")
        ]
        files = [
            file 
            for name, file in file_dict.items() 
            if name.startswith("file")
        ]

        # Loop through all the path & file combinations and check if they exist
        for path in paths:
            for file in files:
               
                full_path = os.path.join(path, file)
                if os.path.exists(full_path):
                    logging.info('{} exists'.format(file))
                else:
                    logging.info('{} does not exist'.format(file))

        # Run the actual function
        return func(file_dict)
    return wrapper

@file_validator
def original_function(file_dict):
    ...

files = {"pathA": "/files", "fileA": "bar.csv", "fileB": "hello.txt"}
original_function(files) 
# Note that fileB is not checked as it's missing "pathB" 
# but from the question it is unclear how this should be handled 

但是有一些代码味道。如果可能的话,我建议不要以这种方式存储您的路径和文件,因为这不容易操作并且容易出现错误。更好的做法是通过使用itertools.combinations 创建所有组合,将它们存储为完整路径列表,或者只使用两个列表:路径和文件。

【讨论】:

    【解决方案2】:

    logging.info 替换为 print 此处进行验证。

    import logging
    import os
    
    def file_validator(f):
        def wrapper(args):
            for path, file in args.items():
                file_path = os.path.join(path, file)
                if os.path.exists(file_path):
                    print('{} exists'.format(file_path))
                else:
                    print('{} does not exist'.format(file_path))
            f(args)
        return wrapper
    
    
    @file_validator
    def original_function(file_dict):
        print(file_dict)
    
    sample_dict = {"pathA": "\\files", "fileA": "bar.csv", "fileB": "hello.txt"}
    original_function(sample_dict)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-21
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2018-12-04
      • 1970-01-01
      相关资源
      最近更新 更多