在Python中定义一个函数(这是一个很大的问题)

时间:2017-09-22 20:12:18

标签: python

所以几天前我们做了这个练习,我们需要创建一个函数,它将两个列表作为输入并计算它们的平均值的差异。

听起来很简单,但有一些捕获:

  • 整个事情需要一行

  • 您绝对不能使用':'

他们鼓励我们使用' import',#39; help()'和' dir()'。

问题是,我知道如何只使它长一行,但不是':'真的很烦人。

我看到它的方式,我首先需要定义一个函数(没有代码),然后更改它的' func_code' ATTR。

关于我该怎么做的任何想法? 那些参数如何适应这个? 任何答案都表示赞赏!!!

编辑:感谢所有的答案和创造性的思想,说char(58)是解决方案,它真的很有创意,我还没有想到这个解决方案,但它不被允许,因为你是使用':'即使不是直接的。

3 个答案:

答案 0 :(得分:1)

:表示您无法使用lambda。这会留下高阶函数或eval欺骗。

eval('lambda a,b{}sum(a)/len(a)-sum(b)/len(b)'.format(chr(58)))

这符合法律条文,但违反了其精神。

不幸的是,如果没有函数组合函数,高阶函数就不能很好地工作。实现一个没有:的人很棘手。

答案 1 :(得分:1)

这里应该是一个相当独立的解决方案,使用pickle代码对象。我已经在Python 3.6中创建了它,并且特定的bytestring很可能是特定于版本的,但您可以使用下面的扩展代码轻松创建自己的版本。无论如何,这里是oneliner:

f = __import__('types').FunctionType(__import__('pickle').loads(b'\x80\x03cipykernel.codeutil\ncode_ctor\nq\x00(K\x02K\x00K\x02K\x04KCC t\x00|\x00\x83\x01t\x01|\x00\x83\x01\x1b\x00t\x00|\x01\x83\x01t\x01|\x01\x83\x01\x1b\x00\x18\x00S\x00q\x01N\x85q\x02X\x03\x00\x00\x00sumq\x03X\x03\x00\x00\x00lenq\x04\x86q\x05X\x01\x00\x00\x00aq\x06X\x01\x00\x00\x00bq\x07\x86q\x08X\x1e\x00\x00\x00<ipython-input-1-384cc87bd499>q\tX\x16\x00\x00\x00difference_of_averagesq\nK\x01C\x02\x00\x01q\x0b))tq\x0cRq\r.'), globals())

这是我在没有单行诡计的情况下所做的事情:

import types   # replace these import statements with calls to __import__ in the oneliner
import pickle

def difference_of_averages(a, b):
    return sum(a)/len(a) - sum(b)/len(b)

payload = pickle.dumps(difference_of_averages.__code__) # embed as a literal in the oneliner

f = types.FunctionType(pickle.loads(payload), globals())
嗯,在我手边的几个不同的解释器上尝试了这个,看起来我的pickle字符串包含了我创建它的IPython解释器中的一些废话。如果你使用我的字符串得到错误,我建议只是构建自己的(如果它包含任何垃圾,至少会与你的环境垃圾兼容)。

答案 2 :(得分:0)

不使用&#39;:&#39;很棘手,因为你通常用它来定义函数体,如下所示:

def average(number_list):
    return sum(number_list) / len(number_list)

但是,我知道一种方法来定义一个不需要为其正文编写块的函数:您可以将lambda函数(或者甚至已经定义的函数)分配给您想要的函数只需使用等号(=)即可定义。例如,如果要创建average()函数,可以编写:

average = lambda number_list: sum(number_list) / len(number_list)

average可能看起来像一个变量,但您可以将其用作函数。它只是调用lambda函数,该函数将number_list作为输入并返回number_list的平均值。你可以这样称呼它:

value = average([10, 11, 12])  # sets value to 11

现在,lambda函数只能有一行。但这对你来说并不是一个问题,因为你的任务要求你只使用一行。

你明白现在该做什么吗?你的练习需要你找到两个列表的平均值,所以你可以考虑使用一个带有两个输入的lambda函数(而不是只有一个,就像我上面给出的例子一样)。另外请记住,您需要返回差异,如果差异应始终为正,请考虑在代码中的某处使用Python的abs()函数。

编辑:好吧,gilch的回复让我意识到我无法使用lambda,因为即使他们使用:。显然你不能使用我的建议。不过,了解lambda函数仍然很好。

鼓励您使用import这一事实让我想知道您是否可以使用某个模块中已定义的函数来定义您自己的函数。有点像这样:

import math; average = math.difference_of_averages

然而,这取决于你能够找到一个完全符合你想要的(可能是标准的)功能。 (我已经简要检查了mathnumpy模块,但还没找到任何匹配的模块。)

也许这意味着你可以创建一个模块并随意定义它。该模块属于自己的世界,所以它并不局限于你的练习规则。

然后,也许不是。

所以除非你想偷偷溜进去#34; :语句中的eval(如gilch建议的那样),如下所示:

average = eval('lambda number_list' + chr(58) + ' sum(number_list) / len(number_list)')

我无法避免使用: