基于输入标志返回不同变量的优雅方式

时间:2013-10-14 02:52:01

标签: python return

我有一个打开文本文件的函数,解析一堆数据并在数组中返回数值结果。现在我还想让这个函数动态地做一些可选的计算,并在需要时返回这些值。

对于单个标志,这是相当干净的,例如:

def read_data(file_name, calc_a=False):
    # do normal parsing and store data in 'xyz'
    if calc_a:
        # calc some other stuff and store in 'a'
        return xyz, a
    else:
        return xyz

现在,如果我想拥有多个可选标志,很快就会变得混乱,例如:

def read_data(file_name, calc_a=False, calc_b=False):
    # do normal parsing and store data in 'xyz'
    if calc_a:
        # calc some other stuff and store in 'a'
    if calc_b:
        # calc some other stuff and store in 'b'

    if calc_a and calc_b:
        return xyz, a, b
    elif calc_a:
        return xyz, a
    elif calc_b:
        return xyz, b
    else:
        return xyz

有没有更清洁的方法来处理这种情况?

5 个答案:

答案 0 :(得分:1)

我通常会这样做:

ret = (xyz,)
if calc_a:
    ret += (abc,)
if calc_b:
    ret += (def,)

return ret[0] if len(ret) == 1 else ret

如果您使用大量变量进行此操作,请考虑使用namedtuple或dict返回子集以方便使用。对于namedtuple,它看起来像:

fields = ['regular_ans']
ret = [xyz]

if calc_a:
    fields.append('a')
    ret.append(abc)
if calc_b:
    fields.append('b')
    ret.append(def)

if len(ret) == 1:
    return ret[0]
return namedtuple('ResultType', fields)(*ret)

答案 1 :(得分:1)

def read_data(file_name, *extras):
    # Read the data from file_name, organizing in a dict,
    # using the key names that your caller will pass into the function.
    # In this example, we have the main data that will always be
    # returned, plus optional data stored under keys a, b, c, d.
    data = dict(_main = 'MAIN', a = 'AA', b = 'BB', c = 'CC', d = 'DD')

    # Return a tuple, list, or even dict of that data.
    ks = sorted(data.keys())
    return tuple(data[k] for k in ks if k in extras or k == '_main')

# Caller requests the optional data they want.
# This example shows the caller passing a list of optional data keys.
# You could also have them pass keyword args instead.
wanted = 'a b d'.split()
print read_data('data_file', *wanted)  # ('MAIN', 'AA', 'BB', 'DD')

答案 2 :(得分:0)

可能还有什么东西沿着论证解包?

http://hangar.runway7.net/python/packing-unpacking-arguments

答案 3 :(得分:0)

现在对于一些完全过度的事情......

import operator

pMap = {
  (False, False): ('foo',),
  (False, True): ('foo', 'bar'),
  (True, False): ('foo', 'bar'),
  (True, True): ('foo', 'bar', 'baz')
}

def func(var, pred1=False, pred2=False):
  # calculations go here
  return operator.itemgetter(*pMap[bool(pred1), bool(pred2)])(dict(foo=1, bar=2, baz=3))

print func(None)
print func(None, pred2=True)
print func(None, True, True)

答案 4 :(得分:0)

我可能会使用带有可链接方法的类。

class DataReader(object):
  abc = None
  deef = None
  def __init__(self, file_name):
    self.xyz = self.normal_parsing(file_name)
  def calc_a(self):
    self.abc = some_calculation(self.xyz)
    return self
  def calc_b(self):
    self.deef = othr_calculation(self.xyz)
    return self

然后你可以做类似的事情:

dr = DataReader("watfile").calc_a().calc_b()
# Now you have access to dr.xyz, dr.abc and dr.deef.
# If you don't run all the methods, some of those would be None

(说实话,我可能不会这样做。我可能会重新解决问题,以便我的函数返回有用的值。但我不知道你的约束。)