Python 重构代码/整合函数(例如,嵌套循环顺序)

Python 重构代码/整合函数(例如,嵌套循环顺序),python,for-loop,refactoring,dry,Python,For Loop,Refactoring,Dry,只是一点背景:我正在制作一个程序,用户输入一个框架文本、两个数字(下限和上限)和一个单词列表。输出是对骨架文本的一系列修改 样本输入: text = "Player # likes @." (replace # with inputted integers and @ with words in list) lower = 1 upper = 3 list = "apples, bananas, oranges" 用户可以选择首先迭代数字: Player 1 likes apples. Pla

只是一点背景:我正在制作一个程序,用户输入一个框架文本、两个数字(下限和上限)和一个单词列表。输出是对骨架文本的一系列修改

样本输入:

text = "Player # likes @." (replace # with inputted integers and @ with words in list)
lower = 1
upper = 3
list = "apples, bananas, oranges"
用户可以选择首先迭代数字:

Player 1 likes apples.
Player 2 likes apples.
Player 3 likes apples.
或者先说:

Player 1 likes apples.
Player 1 likes bananas.
Player 1 likes oranges.
我选择通过基于数字键(用户输入的整数)或单词键(来自输入列表中的单词)创建不同类型的字典,然后迭代字典中的值来拆分这两种输出方法

以下是创建字典的两种类型:

def numkey(dict): # {1: ['Player 1 likes apples', 'Player 1 likes...' ] }

    text, lower, upper, list = input_sort(dict)
    d = {}

    for num in range(lower,upper+1):
        l = []
        for i in list:
            l.append(text.replace('#', str(num)).replace('@', i))
        d[num] = l
    return d

def wordkey(dict): # {'apples': ['Player 1 likes apples', 'Player 2 likes apples'..] }

    text, lower, upper, list = input_sort(dict)
    d = {}

    for i in list:
        l = []
        for num in range(lower,upper+1):
            l.append(text.replace('#', str(num)).replace('@', i))
        d[i] = l
    return d
我有两个单独的函数来创建不同类型的词典,这很好,但是我看到这两个函数之间有很多重复。是否有任何方法可以创建一个dictionary函数并向其传递不同的值,从而改变嵌套for循环的顺序,从而创建我正在寻找的特定{key:value}对


我不知道该怎么做。是否有任何与函数式编程或其他范例相关的东西可以对此有所帮助?这个问题有点抽象,比任何东西都更注重风格/设计。

我认为在这种情况下,与其将两个过程强制为一个函数,不如将每个函数缩短得多:

def numkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {x: [text.replace('#',str(x)).replace('@',item) 
            for item in list.split(', ')] for x in xrange(lower,upper+1)}
    return d

def wordkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {item: [text.replace('#',str(x)).replace('@',item) 
            for x in xrange(lower,upper+1)] for item in list.split(', ')}
    return d

理论上,你可以使用
make_dict(dict,outer,internal)
或类似的东西重构dict创建,但我认为对于如此短的代码位,这就不那么清晰了,特别是考虑到你必须以某种方式预处理int。

我认为在这种情况下,与其将两个进程强制合并为一个函数,不如将每个函数缩短:

def numkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {x: [text.replace('#',str(x)).replace('@',item) 
            for item in list.split(', ')] for x in xrange(lower,upper+1)}
    return d

def wordkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {item: [text.replace('#',str(x)).replace('@',item) 
            for x in xrange(lower,upper+1)] for item in list.split(', ')}
    return d

理论上,您可以使用
make_dict(dict,outer,internal)
或类似的方法重构dict创建,但我认为对于如此短的代码位,这一点就不那么清晰了,特别是考虑到您需要以某种方式预处理int。

您不需要字典来生成输出。您可以使用以下内容:

import itertools

numbers = range(lower, upper + 1)
words = "a, b, c".split(", ")

data = (numbers, words) if numbers_first else (words, numbers)
for n, w in itertools.product(*data):
    if not numbers_first: n, w = w, n
    print("Player %d likes %s." % (n, w))
为了避免循环中出现
if
,您可以动态生成格式字符串,例如:

template = "Player # likes @."
subs = ("{n}", "{w}") if numbers_first else ("{w}", "{n}")
format = make_format(template, subs) # escape {}, replace # and @

# ...
for n, w in product(*data):
    print(format.format(n=n, w=w))

您不需要字典来生成输出。您可以使用以下内容:

import itertools

numbers = range(lower, upper + 1)
words = "a, b, c".split(", ")

data = (numbers, words) if numbers_first else (words, numbers)
for n, w in itertools.product(*data):
    if not numbers_first: n, w = w, n
    print("Player %d likes %s." % (n, w))
为了避免循环中出现
if
,您可以动态生成格式字符串,例如:

template = "Player # likes @."
subs = ("{n}", "{w}") if numbers_first else ("{w}", "{n}")
format = make_format(template, subs) # escape {}, replace # and @

# ...
for n, w in product(*data):
    print(format.format(n=n, w=w))

这里有一个更通用的方法:

from itertools import product

def generate(skeleton, replacements):
    values = (product([k], v) for k, v in replacements.items())
    for p in product(*values):
        s = skeleton
        for a, b in p:
            s = s.replace(a, str(b))
        yield s
replacements
应为字典
{placeholder:list of values}
,例如:

gen = generate("Player # likes @.", {'#': range(1,3), '@': ['apples', 'bananas']})    
for phrase in gen:
    print phrase
印刷品

Player 1 likes apples.
Player 2 likes apples.
Player 1 likes bananas.
Player 2 likes bananas.
如果需要其中一个值为“静态”,只需提供一个元素列表:

gen = generate("Player # likes @.", {'#': [1], '@': ['apples', 'bananas']})    
请注意,这适用于任意数量的占位符:

gen = generate("Player # likes @ and can $", {
    '#': range(1,3), 
    '@': ['apples', 'bananas'],
    '$': ['swim', 'run', 'jump']
})    

这里有一个更通用的方法:

from itertools import product

def generate(skeleton, replacements):
    values = (product([k], v) for k, v in replacements.items())
    for p in product(*values):
        s = skeleton
        for a, b in p:
            s = s.replace(a, str(b))
        yield s
replacements
应为字典
{placeholder:list of values}
,例如:

gen = generate("Player # likes @.", {'#': range(1,3), '@': ['apples', 'bananas']})    
for phrase in gen:
    print phrase
印刷品

Player 1 likes apples.
Player 2 likes apples.
Player 1 likes bananas.
Player 2 likes bananas.
如果需要其中一个值为“静态”,只需提供一个元素列表:

gen = generate("Player # likes @.", {'#': [1], '@': ['apples', 'bananas']})    
请注意,这适用于任意数量的占位符:

gen = generate("Player # likes @ and can $", {
    '#': range(1,3), 
    '@': ['apples', 'bananas'],
    '$': ['swim', 'run', 'jump']
})    

请注意,对于OP来说,
numbers\u first
是您要添加到方法中的参数,即
def output\u置换(numbers\u first=True):
@mVChr:参数是:数字、单词、模板、数字。\u first。对于OP来说,
numbers\u first
是您要添加到方法中的参数,即
def output\u置换(numbers\u first=True):
@mVChr:参数为:数字、单词、模板、数字\u first。