使用装饰器和嵌套函数

时间:2016-07-15 00:03:24

标签: python decorator python-decorators

我需要多次调用多参数函数,而除了一个参数之外的所有函数都是固定的。我在考虑使用装饰器:

# V1 - with @decorator
def dec_adder(num):
    def wrap(fun):
        def wrapped_fun(n1):
            return fun(n1, second_num=num)
        return wrapped_fun
    return wrap

@dec_adder(2)
def adder(first_num, second_num):
    return first_num + second_num

print adder(5)
>>> 7

但这似乎令人困惑,因为它似乎只调用一个2参数函数,adder只有一个参数。

另一种方法是使用嵌套函数定义,该函数定义使用父函数中的局部变量:

# V2 - without @decorator
def add_wrapper(num):
    def wrapped_adder(num_2):
        return num + num_2
    return wrapped_adder

adder = add_wrapper(2)
print adder(5)
>>> 7

但是我在使用这种方法时犹豫不决,因为在我的实际实现中,包装函数非常复杂。我的直觉是它应该有一个独立的定义。

请原谅我,如果这涉及到意见领域,但是要么考虑更好的设计和/或更多的Pythonic?我还应该考虑其他方法吗?

2 个答案:

答案 0 :(得分:2)

在这种情况下,

image应该可以很好地运作:

import java.awt.EventQueue;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

class RecipeTableModel extends AbstractTableModel {

    private final String[] columnNames = {"Number", "Name", "Difficulty",
        "Preparation", "Prep Time", "Quantity", "Ingredients"};
    private final RecipeDB recipeDB = new RecipeDB();

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    @Override
    public int getRowCount() {
        return recipeDB.getRecipeDBSize();
    }

    @Override
    public Object getValueAt(int row, int col) {
        return "(" + row + ", " + col + ")";
    }

    @Override
    public String getColumnName(int column) {
        return columnNames[column];
    }

    private static class RecipeDB {

        public ArrayList<Recipe> recipeArraylist = new ArrayList<Recipe>();

        public void addRecipe(Recipe recipe) {
            recipeArraylist.add(recipe);
        }

        public int getRecipeDBSize() {
            return recipeArraylist.size();
        }

        public Recipe getRecipe(int i) {
            return recipeArraylist.get(i);
        }

        public ArrayList getDBArrayList() {
            return recipeArraylist;
        }
    }

    private static class Recipe {}

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            RecipeTableModel model = new RecipeTableModel();
            for (int i = 0; i < 42; i++) {
                model.recipeDB.addRecipe(new Recipe());
            }
            JFrame f = new JFrame("Test");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new JScrollPane(new JTable(model)));
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

它的'docstring:

  

partial(func,* args,** keywords) - 具有部分应用程序的新函数    给定的参数和关键字。

- 所以,您也可以设置关键字参数。

PS

可悲的是,内置的from functools import partial def adder(n1, n2): return n1 + n2 adder_2 = partial(adder, 2) adder_2(5) 不适合这种情况:它总结了一个可迭代的(事实上,sum),因此sum(iterable[, start]) -> value不起作用。

答案 1 :(得分:2)

另一种可能的解决方案 - 您可以使用functools和参数化装饰器:

from functools import wraps

def decorator(num):
    def decor(f):
        @wraps(f)
        def wrapper(n,*args,**kwargs):
            return f(n+num,*args,**kwargs)
        return wrapper
    return decor


@decorator(num=2) # number to add to the parameter
def test(n,*args,**kwargs):
    print n


test(10)  # base amount - prints 12