标签归档:function

迭代对应于Python中列表的字典键值

问题:迭代对应于Python中列表的字典键值

使用Python 2.7。我有一本字典,其中以球队名称为关键,对每支球队得分并允许的奔跑次数作为值列表:

NL_East = {'Phillies': [645, 469], 'Braves': [599, 548], 'Mets': [653, 672]}

我希望能够将字典提供给函数并遍历每个团队(键)。

这是我正在使用的代码。现在,我只能逐队参加。我将如何遍历每个团队并为每个团队打印预期的win_percentage?

def Pythag(league):
    runs_scored = float(league['Phillies'][0])
    runs_allowed = float(league['Phillies'][1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print win_percentage

谢谢你的帮助。

Working in Python 2.7. I have a dictionary with team names as the keys and the amount of runs scored and allowed for each team as the value list:

NL_East = {'Phillies': [645, 469], 'Braves': [599, 548], 'Mets': [653, 672]}

I would like to be able to feed the dictionary into a function and iterate over each team (the keys).

Here’s the code I’m using. Right now, I can only go team by team. How would I iterate over each team and print the expected win_percentage for each team?

def Pythag(league):
    runs_scored = float(league['Phillies'][0])
    runs_allowed = float(league['Phillies'][1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print win_percentage

Thanks for any help.


回答 0

您有几种选择可以遍历字典。

如果迭代字典本身(for team in league),则将迭代字典的键。当使用for循环进行循环时,无论您是在dict(league)本身上循环还是在以下情况下,行为都是相同的league.keys()

for team in league.keys():
    runs_scored, runs_allowed = map(float, league[team])

您还可以通过迭代遍历键和值一次league.items()

for team, runs in league.items():
    runs_scored, runs_allowed = map(float, runs)

您甚至可以在迭代时执行元组拆包:

for team, (runs_scored, runs_allowed) in league.items():
    runs_scored = float(runs_scored)
    runs_allowed = float(runs_allowed)

You have several options for iterating over a dictionary.

If you iterate over the dictionary itself (for team in league), you will be iterating over the keys of the dictionary. When looping with a for loop, the behavior will be the same whether you loop over the dict (league) itself, or league.keys():

for team in league.keys():
    runs_scored, runs_allowed = map(float, league[team])

You can also iterate over both the keys and the values at once by iterating over league.items():

for team, runs in league.items():
    runs_scored, runs_allowed = map(float, runs)

You can even perform your tuple unpacking while iterating:

for team, (runs_scored, runs_allowed) in league.items():
    runs_scored = float(runs_scored)
    runs_allowed = float(runs_allowed)

回答 1

您也可以很容易地遍历字典:

for team, scores in NL_East.iteritems():
    runs_scored = float(scores[0])
    runs_allowed = float(scores[1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print '%s: %.1f%%' % (team, win_percentage)

You can very easily iterate over dictionaries, too:

for team, scores in NL_East.iteritems():
    runs_scored = float(scores[0])
    runs_allowed = float(scores[1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print '%s: %.1f%%' % (team, win_percentage)

回答 2

字典具有一个称为的内置函数iterkeys()

尝试:

for team in league.iterkeys():
    runs_scored = float(league[team][0])
    runs_allowed = float(league[team][1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print win_percentage

Dictionaries have a built in function called iterkeys().

Try:

for team in league.iterkeys():
    runs_scored = float(league[team][0])
    runs_allowed = float(league[team][1])
    win_percentage = round((runs_scored**2)/((runs_scored**2)+(runs_allowed**2))*1000)
    print win_percentage

回答 3

字典对象允许您迭代其项目。此外,通过模式匹配和__future__可以使事情稍微简化。

最后,您可以将逻辑从打印中分离出来,以使事情在以后的重构/调试中更加容易。

from __future__ import division

def Pythag(league):
    def win_percentages():
        for team, (runs_scored, runs_allowed) in league.iteritems():
            win_percentage = round((runs_scored**2) / ((runs_scored**2)+(runs_allowed**2))*1000)
            yield win_percentage

    for win_percentage in win_percentages():
        print win_percentage

Dictionary objects allow you to iterate over their items. Also, with pattern matching and the division from __future__ you can do simplify things a bit.

Finally, you can separate your logic from your printing to make things a bit easier to refactor/debug later.

from __future__ import division

def Pythag(league):
    def win_percentages():
        for team, (runs_scored, runs_allowed) in league.iteritems():
            win_percentage = round((runs_scored**2) / ((runs_scored**2)+(runs_allowed**2))*1000)
            yield win_percentage

    for win_percentage in win_percentages():
        print win_percentage

回答 4

列表理解可以缩短内容…

win_percentages = [m**2.0 / (m**2.0 + n**2.0) * 100 for m, n in [a[i] for i in NL_East]]

List comprehension can shorten things…

win_percentages = [m**2.0 / (m**2.0 + n**2.0) * 100 for m, n in [a[i] for i in NL_East]]

在NumPy数组的每个单元中高效评估函数

问题:在NumPy数组的每个单元中高效评估函数

给定一个NumPy数组A,将相同的函数f应用于每个单元的最快/最有效的方法是什么?

  1. 假设我们将分配给A(I,J)F(A(I,J))

  2. 函数f没有二进制输出,因此mask(ing)操作将无济于事。

“显而易见的”双循环迭代(通过每个单元)是否是最佳解决方案?

Given a NumPy array A, what is the fastest/most efficient way to apply the same function, f, to every cell?

  1. Suppose that we will assign to A(i,j) the f(A(i,j)).

  2. The function, f, doesn’t have a binary output, thus the mask(ing) operations won’t help.

Is the “obvious” double loop iteration (through every cell) the optimal solution?


回答 0

您可以对函数进行矢量化处理,然后在每次需要时将其直接应用于Numpy数组:

import numpy as np

def f(x):
    return x * x + 3 * x - 2 if x > 0 else x * 5 + 8

f = np.vectorize(f)  # or use a different name if you want to keep the original f

result_array = f(A)  # if A is your Numpy array

向量化时最好直接指定一个显式输出类型:

f = np.vectorize(f, otypes=[np.float])

You could just vectorize the function and then apply it directly to a Numpy array each time you need it:

import numpy as np

def f(x):
    return x * x + 3 * x - 2 if x > 0 else x * 5 + 8

f = np.vectorize(f)  # or use a different name if you want to keep the original f

result_array = f(A)  # if A is your Numpy array

It’s probably better to specify an explicit output type directly when vectorizing:

f = np.vectorize(f, otypes=[np.float])

回答 1

一个类似的问题是:将NumPy数组映射到适当的位置。如果可以为f()找到一个ufunc,则应使用out参数。

A similar question is: Mapping a NumPy array in place. If you can find a ufunc for your f(), then you should use the out parameter.


回答 2

如果您使用数字和f(A(i,j)) = f(A(j,i)),则可以使用scipy.spatial.distance.cdist将f定义为A(i)和之间的距离A(j)

If you are working with numbers and f(A(i,j)) = f(A(j,i)), you could use scipy.spatial.distance.cdist defining f as a distance between A(i) and A(j).


回答 3

我相信我找到了更好的解决方案。将函数更改为python通用函数的想法(请参阅文档),可以在后台进行并行计算。

一个人可以用ufuncC 编写自己的自定义脚本,这肯定会更有效,也可以通过调用np.frompyfunc内置工厂方法来编写。经过测试,此方法比np.vectorize

f = lambda x, y: x * y
f_arr = np.frompyfunc(f, 2, 1)
vf = np.vectorize(f)
arr = np.linspace(0, 1, 10000)

%timeit f_arr(arr, arr) # 307ms
%timeit f_arr(arr, arr) # 450ms

我还测试了较大的样本,并且改进成比例。有关其他方法的性能比较,请参阅这篇文章

I believe I have found a better solution. The idea to change the function to python universal function (see documentation), which can exercise parallel computation under the hood.

One can write his own customised ufunc in C, which surely is more efficient, or by invoking np.frompyfunc, which is built-in factory method. After testing, this is more efficient than np.vectorize:

f = lambda x, y: x * y
f_arr = np.frompyfunc(f, 2, 1)
vf = np.vectorize(f)
arr = np.linspace(0, 1, 10000)

%timeit f_arr(arr, arr) # 307ms
%timeit f_arr(arr, arr) # 450ms

I have also tested larger samples, and the improvement is proportional. For comparison of performances of other methods, see this post


回答 4

当2d数组(或nd数组)为C或F连续时,将函数映射到2d数组的任务实际上与将函数映射到1d数组的任务相同-我们只是必须以这种方式查看它,例如通过np.ravel(A,'K')

例如,这里讨论了1d阵列的可能解决方案。

但是,当2d数组的内存不连续时,情况会稍微复杂一些,因为如果轴处理顺序错误,则希望避免可能发生的高速缓存未命中。

Numpy已经有机器以最佳顺序加工轴。使用这种机械的一种可能性是np.vectorize。但是,numpy的文档np.vectorize指出“主要是为了方便而不是为了性能而提供”-慢速python函数保持慢速python函数以及所有相关的开销!另一个问题是其巨大的内存消耗-例如,参见此SO-post

当想要具有C函数的性能但要使用numpy的机器时,一个好的解决方案是使用numba创建ufunc,例如:

# runtime generated C-function as ufunc
import numba as nb
@nb.vectorize(target="cpu")
def nb_vf(x):
    return x+2*x*x+4*x*x*x

它很容易击败,np.vectorize但是当执行相同的功能作为numpy-array乘法/加法时,即

# numpy-functionality
def f(x):
    return x+2*x*x+4*x*x*x

# python-function as ufunc
import numpy as np
vf=np.vectorize(f)
vf.__name__="vf"

有关时间测量代码,请参见此答案的附录:

Numba的版本(绿色)比python函数(即np.vectorize)快约100倍,这并不奇怪。但这也比numpy功能快约10倍,因为numbas版本不需要中间数组,因此可以更有效地使用缓存。


尽管numba的ufunc方法是可用性和性能之间的良好折衷,但它仍然不是我们能做的最好的选择。然而,没有灵丹妙药或最适合任何任务的方法-人们必须了解什么是局限性以及如何减轻它们。

例如,对于超越函数(例如expsincos)numba不提供超过任何优点numpy的的np.exp(有没有创建临时数组-高速化的主要来源)。但是,我的Anaconda安装使用Intel的VML来处理大于8192的矢量-如果内存不连续,则无法执行。因此,最好将元素复制到连续内存中,以便能够使用英特尔的VML:

import numba as nb
@nb.vectorize(target="cpu")
def nb_vexp(x):
    return np.exp(x)

def np_copy_exp(x):
    copy = np.ravel(x, 'K')
    return np.exp(copy).reshape(x.shape) 

为了公平起见,我关闭了VML的并行化功能(请参见附录中的代码):

可以看到,一旦VML开始运行,复制的开销就远远超过了补偿。但是,一旦数据对于L3高速缓存而言变得太大,则优势就变得微不足道了,因为任务再次变得与内存带宽绑定。

在另一方面,numba可以使用英特尔的SVML为好,在解释这个帖子

from llvmlite import binding
# set before import
binding.set_option('SVML', '-vector-library=SVML')

import numba as nb

@nb.vectorize(target="cpu")
def nb_vexp_svml(x):
    return np.exp(x)

并使用具有并行化功能的VML生成:

numba的版本开销较小,但是对于某些大小,VML甚至比SVML都要高,尽管有额外的复制开销-这并不奇怪,因为numba的ufunc没有并行化。


清单:

A.多项式函数的比较:

import perfplot
perfplot.show(
    setup=lambda n: np.random.rand(n,n)[::2,::2],
    n_range=[2**k for k in range(0,12)],
    kernels=[
        f,
        vf, 
        nb_vf
        ],
    logx=True,
    logy=True,
    xlabel='len(x)'
    ) 

B.比较exp

import perfplot
import numexpr as ne # using ne is the easiest way to set vml_num_threads
ne.set_vml_num_threads(1)
perfplot.show(
    setup=lambda n: np.random.rand(n,n)[::2,::2],
    n_range=[2**k for k in range(0,12)],
    kernels=[
        nb_vexp, 
        np.exp,
        np_copy_exp,
        ],
    logx=True,
    logy=True,
    xlabel='len(x)',
    )

When the 2d-array (or nd-array) is C- or F-contiguous, then this task of mapping a function onto a 2d-array is practically the same as the task of mapping a function onto a 1d-array – we just have to view it that way, e.g. via np.ravel(A,'K').

Possible solution for 1d-array have been discussed for example here.

However, when the memory of the 2d-array isn’t contiguous, then the situation a little bit more complicated, because one would like to avoid possible cache misses if axis are handled in wrong order.

Numpy has already a machinery in place to process axes in the best possible order. One possibility to use this machinery is np.vectorize. However, numpy’s documentation on np.vectorize states that it is “provided primarily for convenience, not for performance” – a slow python function stays a slow python function with the whole associated overhead! Another issue is its huge memory-consumption – see for example this SO-post.

When one wants to have a performance of a C-function but to use numpy’s machinery, a good solution is to use numba for creation of ufuncs, for example:

# runtime generated C-function as ufunc
import numba as nb
@nb.vectorize(target="cpu")
def nb_vf(x):
    return x+2*x*x+4*x*x*x

It easily beats np.vectorize but also when the same function would be performed as numpy-array multiplication/addition, i.e.

# numpy-functionality
def f(x):
    return x+2*x*x+4*x*x*x

# python-function as ufunc
import numpy as np
vf=np.vectorize(f)
vf.__name__="vf"

See appendix of this answer for time-measurement-code:

Numba’s version (green) is about 100 times faster than the python-function (i.e. np.vectorize), which is not surprising. But it is also about 10 times faster than the numpy-functionality, because numbas version doesn’t need intermediate arrays and thus uses cache more efficiently.


While numba’s ufunc approach is a good trade-off between usability and performance, it is still not the best we can do. Yet there is no silver bullet or an approach best for any task – one has to understand what are the limitation and how they can be mitigated.

For example, for transcendental functions (e.g. exp, sin, cos) numba doesn’t provide any advantages over numpy’s np.exp (there are no temporary arrays created – the main source of the speed-up). However, my Anaconda installation utilizes Intel’s VML for vectors bigger than 8192 – it just cannot do it if memory is not contiguous. So it might be better to copy the elements to a contiguous memory in order to be able to use Intel’s VML:

import numba as nb
@nb.vectorize(target="cpu")
def nb_vexp(x):
    return np.exp(x)

def np_copy_exp(x):
    copy = np.ravel(x, 'K')
    return np.exp(copy).reshape(x.shape) 

For the fairness of the comparison, I have switched off VML’s parallelization (see code in the appendix):

As one can see, once VML kicks in, the overhead of copying is more than compensated. Yet once data becomes too big for L3 cache, the advantage is minimal as task becomes once again memory-bandwidth-bound.

On the other hand, numba could use Intel’s SVML as well, as explained in this post:

from llvmlite import binding
# set before import
binding.set_option('SVML', '-vector-library=SVML')

import numba as nb

@nb.vectorize(target="cpu")
def nb_vexp_svml(x):
    return np.exp(x)

and using VML with parallelization yields:

numba’s version has less overhead, but for some sizes VML beats SVML even despite of the additional copying overhead – which isn’t a bit surprise as numba’s ufuncs aren’t parallelized.


Listings:

A. comparison of polynomial function:

import perfplot
perfplot.show(
    setup=lambda n: np.random.rand(n,n)[::2,::2],
    n_range=[2**k for k in range(0,12)],
    kernels=[
        f,
        vf, 
        nb_vf
        ],
    logx=True,
    logy=True,
    xlabel='len(x)'
    ) 

B. comparison of exp:

import perfplot
import numexpr as ne # using ne is the easiest way to set vml_num_threads
ne.set_vml_num_threads(1)
perfplot.show(
    setup=lambda n: np.random.rand(n,n)[::2,::2],
    n_range=[2**k for k in range(0,12)],
    kernels=[
        nb_vexp, 
        np.exp,
        np_copy_exp,
        ],
    logx=True,
    logy=True,
    xlabel='len(x)',
    )

回答 5

以上所有答案比较起来都不错,但是如果您需要使用自定义函数进行映射,并且拥有numpy.ndarray,则需要保留数组的形状。

我只比较了两个,但它将保留的形状ndarray。我已将具有100万个条目的数组用于比较。在这里我使用平方函数。我正在介绍n维数组的一般情况。对于二维,只需制作iter2D。

import numpy, time

def A(e):
    return e * e

def timeit():
    y = numpy.arange(1000000)
    now = time.time()
    numpy.array([A(x) for x in y.reshape(-1)]).reshape(y.shape)        
    print(time.time() - now)
    now = time.time()
    numpy.fromiter((A(x) for x in y.reshape(-1)), y.dtype).reshape(y.shape)
    print(time.time() - now)
    now = time.time()
    numpy.square(y)  
    print(time.time() - now)

输出量

>>> timeit()
1.162431240081787    # list comprehension and then building numpy array
1.0775556564331055   # from numpy.fromiter
0.002948284149169922 # using inbuilt function

在这里你可以清楚地看到 numpy.fromiter用户平方函数,可以使用任何选择。如果你的功能是依赖于i, j 那就是数组的索引,迭代上数组的大小一样for ind in range(arr.size),用numpy.unravel_index得到i, j, ..基于阵列的您1D指数和形状numpy.unravel_index

这个答案是受到我对其他问题的回答的启发 这里

All above answers compares well, but if you need to use custom function for mapping, and you have numpy.ndarray, and you need to retain the shape of array.

I have compare just two, but it will retain the shape of ndarray. I have used the array with 1 million entries for comparison. Here I use square function. I am presenting the general case for n dimensional array. For two dimensional just make iter for 2D.

import numpy, time

def A(e):
    return e * e

def timeit():
    y = numpy.arange(1000000)
    now = time.time()
    numpy.array([A(x) for x in y.reshape(-1)]).reshape(y.shape)        
    print(time.time() - now)
    now = time.time()
    numpy.fromiter((A(x) for x in y.reshape(-1)), y.dtype).reshape(y.shape)
    print(time.time() - now)
    now = time.time()
    numpy.square(y)  
    print(time.time() - now)

Output

>>> timeit()
1.162431240081787    # list comprehension and then building numpy array
1.0775556564331055   # from numpy.fromiter
0.002948284149169922 # using inbuilt function

here you can clearly see numpy.fromiter user square function, use any of your choice. If you function is dependent on i, j that is indices of array, iterate on size of array like for ind in range(arr.size), use numpy.unravel_index to get i, j, .. based on your 1D index and shape of array numpy.unravel_index

This answers is inspired by my answer on other question here


在Python中,什么时候应该使用函数而不是方法?

问题:在Python中,什么时候应该使用函数而不是方法?

Python的Zen指出,只有一种方法可以做事情-但我经常遇到决定何时使用函数以及何时使用方法的问题。

让我们举一个简单的例子-ChessBoard对象。假设我们需要某种方式使董事会上所有合法的King举动均可用。我们是否编写ChessBoard.get_king_moves()或get_king_moves(chess_board)?

这是我看过的一些相关问题:

我得到的答案基本上没有定论:

为什么Python使用方法来实现某些功能(例如list.index()),却使用其他方法(例如len(list))呢?

主要原因是历史。函数用于那些对一组类型通用的操作,即使对于根本没有方法的对象(例如元组),这些操作也可以使用。使用Python的功能特性(map(),apply()等)时,具有可以轻松应用于对象的不定形集合的函数也很方便。

实际上,将len(),max(),min()实现为内置函数实际上比将它们实现为每种类型的方法要少。人们可能会质疑个别情况,但这是Python的一部分,现在进行这样的基本更改为时已晚。必须保留功能以避免大量代码损坏。

尽管很有趣,但是上面并没有真正说明采用哪种策略。

这是原因之一-使用自定义方法,开发人员可以自由选择其他方法名称,例如getLength(),length(),getlength()或其他名称。Python强制执行严格的命名,以便可以使用通用函数len()。

稍微有趣一点。我认为函数在某种意义上是接口的Pythonic版本。

最后,来自Guido本人

谈论能力/接口使我想到了一些“流氓”特殊方法名称。在《语言参考》中,它说:“类可以通过定义具有特殊名称的方法来实现某些由特殊语法调用的操作(例如算术运算或下标和切片)。” 但是,所有这些带有特殊名称的方法(例如__len__或)__unicode__似乎都是为内置函数的利益提供的,而不是为了支持语法。大概在基于接口的Python中,这些方法将在ABC上变成常规命名的方法,因此 __len__将成为

class container:
  ...
  def len(self):
    raise NotImplemented

虽然,再想一想,我不明白为什么所有的句法运算都不会仅仅在特定的ABC上调用适当的通常命名的方法。“ <”举例来说,大概会调用“ object.lessthan”(或者是“ comparable.lessthan“)。因此,另一个好处是能够使Python摆脱这种乱七八糟的名字,对我而言这似乎是HCI的改进

嗯 我不确定我是否同意(图:-)。

我首先要解释“ Python基本原理”的两个方面。

首先,出于HCI的原因,我选择了len(x)而不是x.len()(def __len__()后来出现了)。实际上,两个HCI相互交织在一起:

(a)对于某些运算,前缀表示法比后缀读得更好-前缀(和infix!)操作在数学中具有悠久的传统,喜欢在视觉上帮助数学家思考问题的表示法。比较与我们改写像公式简单x*(a+b)x*a + x*b使用原始OO符号做同样的事情的笨拙。

(b)当我读到说的代码时,len(x)知道那是在问某物的长度。这告诉我两件事:结果是整数,参数是某种容器。相反,当我阅读本文时x.len(),我必须已经知道这x是一种实现接口或从具有standard的类继承的容器len()。当未实现映射的类具有get()keys() 方法,或者不是文件的某些具有方法时,我们有时会感到困惑write()

用另一种方式说同样的事情,我将’len’视为内置 操作。我不想失去那个。我不能肯定地说出您是否是那样的意思,但是“ def len(self):…”当然听起来像您想将其降级为普通方法。我对此坚决为-1。

我答应解释的Python基本原理的第二点是为什么我选择了特殊的外观__special__而不是仅仅 选择外观的原因special。我期待类可能要覆盖的许多操作,一些标准(例如__add____getitem__),某些不是那么标准(例如,泡菜__reduce__很长一段时间都不支持C代码)。我不希望这些特殊操作使用普通的方法名称,因为那样的话,预先存在的类或用户没有为所有特殊方法存储百科全书的用户编写的类可能会意外地定义它们并非要实现的操作,可能会造成灾难性的后果。伊万·科斯蒂奇(IvanKrstić)在他的信息中对此进行了更为简洁的解释,在我将所有这些内容写完之后,这些信息才得以体现。

—Guido van Rossum(主页:http ://www.python.org/~guido/ )

我对此的理解是,在某些情况下,前缀表示法更有意义(即,从语言的角度来看,Duck.quack比quack(Duck)更有意义。)而且,该函数还允许使用“接口”。

在这种情况下,我的猜测是仅基于Guido的第一点实现get_king_moves。但这仍然存在很多悬而未决的问题,例如使用类似的push和pop方法实现堆栈和队列类-它们应该是函数还是方法?(在这里我会猜测功能,因为我真的很想发信号通知推送界面)

TLDR:有人可以解释决定何时使用函数还是方法的策略是什么?

The Zen of Python states that there should only be one way to do things- yet frequently I run into the problem of deciding when to use a function versus when to use a method.

Let’s take a trivial example- a ChessBoard object. Let’s say we need some way to get all the legal King moves available on the board. Do we write ChessBoard.get_king_moves() or get_king_moves(chess_board)?

Here are some related questions I looked at:

The answers I got were largely inconclusive:

Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))?

The major reason is history. Functions were used for those operations that were generic for a group of types and which were intended to work even for objects that didn’t have methods at all (e.g. tuples). It is also convenient to have a function that can readily be applied to an amorphous collection of objects when you use the functional features of Python (map(), apply() et al).

In fact, implementing len(), max(), min() as a built-in function is actually less code than implementing them as methods for each type. One can quibble about individual cases but it’s a part of Python, and it’s too late to make such fundamental changes now. The functions have to remain to avoid massive code breakage.

While interesting, the above doesn’t really say much as to what strategy to adopt.

This is one of the reasons – with custom methods, developers would be free to choose a different method name, like getLength(), length(), getlength() or whatsoever. Python enforces strict naming so that the common function len() can be used.

Slightly more interesting. My take is that functions are in a sense, the Pythonic version of interfaces.

Lastly, from Guido himself:

Talking about the Abilities/Interfaces made me think about some of our “rogue” special method names. In the Language Reference, it says, “A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names.” But there are all these methods with special names like __len__ or __unicode__ which seem to be provided for the benefit of built-in functions, rather than for support of syntax. Presumably in an interface-based Python, these methods would turn into regularly-named methods on an ABC, so that __len__ would become

class container:
  ...
  def len(self):
    raise NotImplemented

Though, thinking about it some more, I don’t see why all syntactic operations wouldn’t just invoke the appropriate normally-named method on a specific ABC. “<“, for instance, would presumably invoke “object.lessthan” (or perhaps “comparable.lessthan“). So another benefit would be the ability to wean Python away from this mangled-name oddness, which seems to me an HCI improvement.

Hm. I’m not sure I agree (figure that :-).

There are two bits of “Python rationale” that I’d like to explain first.

First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:

(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.

(b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.

Saying the same thing in another way, I see ‘len’ as a built-in operation. I’d hate to lose that. I can’t say for sure whether you meant that or not, but ‘def len(self): …’ certainly sounds like you want to demote it to an ordinary method. I’m strongly -1 on that.

The second bit of Python rationale I promised to explain is the reason why I chose special methods to look __special__ and not merely special. I was anticipating lots of operations that classes might want to override, some standard (e.g. __add__ or __getitem__), some not so standard (e.g. pickle’s __reduce__ for a long time had no support in C code at all). I didn’t want these special operations to use ordinary method names, because then pre-existing classes, or classes written by users without an encyclopedic memory for all the special methods, would be liable to accidentally define operations they didn’t mean to implement, with possibly disastrous consequences. Ivan Krstić explained this more concise in his message, which arrived after I’d written all this up.

— –Guido van Rossum (home page: http://www.python.org/~guido/)

My understanding of this is that in certain cases, prefix notation just makes more sense (ie, Duck.quack makes more sense than quack(Duck) from a linguistic standpoint.) and again, the functions allow for “interfaces”.

In such a case, my guess would be to implement get_king_moves based solely on Guido’s first point. But that still leaves a lot of open questions regarding say, implementing a stack and queue class with similar push and pop methods- should they be functions or methods? (here I would guess functions, because I really want to signal a push-pop interface)

TLDR: Can someone explain what the strategy for deciding when to use functions vs. methods should be?


回答 0

我的一般规则是- 是在对象上执行还是由对象执行操作?

如果是由对象完成的,则应该是成员操作。如果它也可以应用于其他事物,或者由对象的其他事物完成,那么它应该是一个函数(或其他事物的成员)。

引入编程时,传统上(尽管实现不正确)以现实世界中的对象(例如汽车)来描述对象。您提到了一只鸭子,所以让我们开始吧。

class duck: 
    def __init__(self):pass
    def eat(self, o): pass 
    def crap(self) : pass
    def die(self)
    ....

在“对象是真实事物”类比的上下文中,为对象可以执行的任何操作添加类方法是“正确的”。所以说我想杀死一只鸭子,是否要在鸭子上添加.kill()?不,据我所知,动物不会自杀。因此,如果我想杀死一只鸭子,我应该这样做:

def kill(o):
    if isinstance(o, duck):
        o.die()
    elif isinstance(o, dog):
        print "WHY????"
        o.die()
    elif isinstance(o, nyancat):
        raise Exception("NYAN "*9001)
    else:
       print "can't kill it."

远离这种类比,为什么我们要使用方法和类?因为我们要包含数据并希望以某种方式构造我们的代码,以便将来可以重用和扩展它。这使我们想到了面向对象设计非常重要的封装概念。

封装原理实际上就是它的含义:作为设计人员,您应该隐藏有关实现和类内部的所有内容,对于任何用户或其他开发人员而言,都不一定要访问它。因为我们处理类的实例,所以这简化为“ 对该实例至关重要的操作”。如果操作不是实例特定的,则它不应是成员函数。

TL; DR:@Bryan说了什么。如果它在实例上运行并且需要访问类实例内部的数据,则它应该是成员函数。

My general rule is this – is the operation performed on the object or by the object?

if it is done by the object, it should be a member operation. If it could apply to other things too, or is done by something else to the object then it should be a function (or perhaps a member of something else).

When introducing programming, it is traditional (albeit implementation incorrect) to describe objects in terms of real-world objects such as cars. You mention a duck, so let’s go with that.

class duck: 
    def __init__(self):pass
    def eat(self, o): pass 
    def crap(self) : pass
    def die(self)
    ....

In the context of the “objects are real things” analogy, it is “correct” to add a class method for anything which the object can do. So say I want to kill off a duck, do I add a .kill() to the duck? No… as far as I know animals do not commit suicide. Therefore if I want to kill a duck I should do this:

def kill(o):
    if isinstance(o, duck):
        o.die()
    elif isinstance(o, dog):
        print "WHY????"
        o.die()
    elif isinstance(o, nyancat):
        raise Exception("NYAN "*9001)
    else:
       print "can't kill it."

Moving away from this analogy, why do we use methods and classes? Because we want to contain data and hopefully structure our code in a manner such that it will be reusable and extensible in the future. This brings us to the notion of encapsulation which is so dear to OO design.

The encapsulation principal is really what this comes down to: as a designer you should hide everything about the implementation and class internals which it is not absolutely necessarily for any user or other developer to access. Because we deal with instances of classes, this reduces to “what operations are crucial on this instance“. If an operation is not instance specific, then it should not be a member function.

TL;DR: what @Bryan said. If it operates on an instance and needs to access data which is internal to the class instance, it should be a member function.


回答 1

在需要以下情况时,请使用类:

1)从实现细节中隔离调用代码-利用抽象封装

2)当您想替代其他对象时-利用多态性

3)当您想为相似的对象重用代码时-利用继承

将函数用于对许多不同的对象类型有意义的调用-例如,内置的lenrepr函数适用于多种对象。

话虽如此,选择有时取决于口味。考虑一下最适合常规通话的方式和可读性。例如,这将是更好的(x.sin()**2 + y.cos()**2).sqrt()还是sqrt(sin(x)**2 + cos(y)**2)

Use a class when you want to:

1) Isolate calling code from implementation details — taking advantage of abstraction and encapsulation.

2) When you want to be substitutable for other objects — taking advantage of polymorphism.

3) When you want to reuse code for similar objects — taking advantage of inheritance.

Use a function for calls that make sense across many different object types — for example, the builtin len and repr functions apply to many kinds of objects.

That being said, the choice sometimes comes down to a matter of taste. Think in terms of what is most convenient and readable for typical calls. For example, which would be better (x.sin()**2 + y.cos()**2).sqrt() or sqrt(sin(x)**2 + cos(y)**2)?


回答 2

这是一条简单的经验法则:如果代码作用于对象的单个实例,请使用一种方法。甚至更好:除非有充分的理由将其编写为函数,否则请使用一种方法。

在您的特定示例中,您希望它看起来像这样:

chessboard = Chessboard()
...
chessboard.get_king_moves()

不要过度考虑。始终使用方法,直到您对自己说“将此方法定义为没有意义”为止,在这种情况下,您可以创建函数。

Here’s a simple rule of thumb: if the code acts upon a single instance of an object, use a method. Even better: use a method unless there is a compelling reason to write it as a function.

In your specific example, you want it to look like this:

chessboard = Chessboard()
...
chessboard.get_king_moves()

Don’t over think it. Always use methods until the point comes where you say to yourself “it doesn’t make sense to make this a method”, in which case you can make a function.


回答 3

我通常认为一个物体像一个人。

属性是人物的姓名,身高,鞋子的大小等。

方法功能是人可以执行的操作。

如果该操作只能由任何其他人完成,而又不需要该特定人独有的任何东西(并且无需更改该特定人的任何东西),那么它就是一个函数,应该这样编写。

如果某项操作正在对该人进行操作(例如进餐,散步等),或者需要该人独特的操作(例如跳舞,写书等),则应采用一种方法

当然,将其转换为您正在使用的特定对象并不总是一件容易的事,但是我发现这是思考它的好方法。

I usually think of an object like a person.

Attributes are the person’s name, height, shoe size, etc.

Methods and functions are operations that the person can perform.

If the operation could be done by just any ol’ person, without requiring anything unique to this one specific person (and without changing anything on this one specific person), then it’s a function and should be written as such.

If an operation is acting upon the person (e.g. eating, walking, …) or requires something unique to this person to get involved (like dancing, writing a book, …), then it should be a method.

Of course, it is not always trivial to translate this into the specific object you’re working with, but I find it is a good way to think of it.


回答 4

通常,我使用类来为某件事实现一组逻辑功能,以便在程序的其余部分中,我可以对事物进行推理,而不必担心构成其实现的所有小问题。

凡是是那核心抽象的一部分“你可以用做什么事情 ”通常应该是一个方法。这通常包括可以改变一切的事情,作为内部数据状态通常被认为是私人,而不是“你可以用做什么逻辑思想的一部分的事情 ”。

当您进行更高级别的操作时,特别是如果它们涉及多个事物,我发现它们通常最自然地表示为函数,前提是它们可以从事物的公共抽象中构建而无需特殊的内部访问(除非它们re方法)。这具有很大的优势,当我决定完全重写我工作方式的内部结构(无需更改接口)时,我只有一小部分核心方法可以重写,然后使用这些方法编写所有外部函数将工作。我发现坚持认为与类X有关的所有操作都是类X上的方法会导致类过于复杂。

这取决于我正在编写的代码。对于某些程序,我将它们建模为对象的集合,这些对象的相互作用引起了程序的行为。在这里,最重要的功能紧密耦合到单个对象,因此是在方法中实现的,其中包含实用功能。对于其他程序,最重要的东西是一组操作数据的函数,而类仅用于实现由这些函数操纵的自然“鸭子类型”。

Generally I use classes to implement a logical set of capabilities for some thing, so that in the rest of my program I can reason about the thing, not having to worry about all the little concerns that make up its implementation.

Anything that’s part of that core abstraction of “what you can do with a thing” should usually be a method. This generally includes everything that can alter a thing, as the internal data state is usually considered private and not part of the logical idea of “what you can do with a thing“.

When you come to higher level operations, especially if they involve multiple things, I find they are usually most naturally expressed as functions, if they can be built out of the public abstraction of a thing without needing special access to the internals (unless they’re methods of some other object). This has the big advantage that when I decide to completely rewrite the internals of how my thing works (without changing the interface), I just have a small core set of methods to rewrite, and then all the external functions written in terms of those methods will Just Work. I find that insisting that all operations to do with class X are methods on class X leads to over-complicated classes.

It depends on the code I’m writing though. For some programs I model them as a collection of objects whose interactions give rise to the behavior of the program; here most important functionality is closely coupled to a single object, and so is implemented in methods, with a scattering of utility functions. For other programs the most important stuff is a set of functions that manipulate data, and classes are in use only to implement the natural “duck types” that are manipulated by the functions.


回答 5

您可能会说,“面对模棱两可,拒绝猜测的诱惑”。

但是,这甚至不是猜测。您绝对可以确保两种方法的结果相同,因为它们可以解决您的问题。

我相信,采用多种方式实现目标只是一件好事。与其他用户一样,我要谦虚地告诉您,就语言而言,采用“味道更好” /感觉更直观的方法。

You may say that, “in the face of ambiguity, refuse the temptation to guess”.

However, it’s not even a guess. You’re absolutely sure that the outcomes of both approaches are the same in that they solve your problem.

I believe it is only a good thing to have multiple ways to accomplishing goals. I’d humbly tell you, as other users did already, to employ whichever “tastes better” / feels more intuitive, in terms of language.


Python函数作为函数参数吗?

问题:Python函数作为函数参数吗?

Python函数可以作为另一个函数的参数吗?

说:

def myfunc(anotherfunc, extraArgs):
    # run anotherfunc and also pass the values from extraArgs to it
    pass

所以这基本上是两个问题:

  1. 可以吗?
  2. 如果是的话,如何在其他函数中使用该函数?我需要使用exec(),eval()还是类似的东西?从来不需要与他们搞混。

顺便说一句,extraArgs是anotherfunc参数的列表/元组。

Can a Python function be an argument of another function?

Say:

def myfunc(anotherfunc, extraArgs):
    # run anotherfunc and also pass the values from extraArgs to it
    pass

So this is basically two questions:

  1. Is it allowed at all?
  2. And if it is, how do I use the function inside the other function? Would I need to use exec(), eval() or something like that? Never needed to mess with them.

BTW, extraArgs is a list/tuple of anotherfunc’s arguments.


回答 0

Python函数可以作为另一个函数的参数吗?

是。

def myfunc(anotherfunc, extraArgs):
    anotherfunc(*extraArgs)

更具体地说…带有各种参数…

>>> def x(a,b):
...     print "param 1 %s param 2 %s"%(a,b)
...
>>> def y(z,t):
...     z(*t)
...
>>> y(x,("hello","manuel"))
param 1 hello param 2 manuel
>>>

Can a Python function be an argument of another function?

Yes.

def myfunc(anotherfunc, extraArgs):
    anotherfunc(*extraArgs)

To be more specific … with various arguments …

>>> def x(a,b):
...     print "param 1 %s param 2 %s"%(a,b)
...
>>> def y(z,t):
...     z(*t)
...
>>> y(x,("hello","manuel"))
param 1 hello param 2 manuel
>>>

回答 1

这是使用*args(以及可选)的另一种方法**kwargs

def a(x, y):
  print x, y

def b(other, function, *args, **kwargs):
  function(*args, **kwargs)
  print other

b('world', a, 'hello', 'dude')

输出量

hello dude
world

需要注意的是function*args**kwargs必须按照这个顺序和必须的函数调用该函数的最后的参数。

Here’s another way using *args (and also optionally), **kwargs:

def a(x, y):
  print x, y

def b(other, function, *args, **kwargs):
  function(*args, **kwargs)
  print other

b('world', a, 'hello', 'dude')

Output

hello dude
world

Note that function, *args, **kwargs have to be in that order and have to be the last arguments to the function calling the function.


回答 2

Python中的函数是一流的对象。但是您的函数定义有点偏离

def myfunc(anotherfunc, extraArgs, extraKwArgs):
  return anotherfunc(*extraArgs, **extraKwArgs)

Functions in Python are first-class objects. But your function definition is a bit off.

def myfunc(anotherfunc, extraArgs, extraKwArgs):
  return anotherfunc(*extraArgs, **extraKwArgs)

回答 3

当然,这就是python在第一个参数为函数的情况下实现以下方法的原因:

  • map(function,iterable,…)-将函数应用于iterable的每个项目并返回结果列表。
  • filter(function,iterable)-从这些iterable的元素构造一个列表,对于这些元素,函数将返回true。
  • reduce(function,iterable [,initializer])-将两个参数的函数从左到右累计应用于iterable的项,以将iterable减少为单个值。
  • Lambdas

Sure, that is why python implements the following methods where the first parameter is a function:

  • map(function, iterable, …) – Apply function to every item of iterable and return a list of the results.
  • filter(function, iterable) – Construct a list from those elements of iterable for which function returns true.
  • reduce(function, iterable[,initializer]) – Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value.
  • lambdas

回答 4

  1. 是的,允许。
  2. 您可以像使用其他函数一样使用该函数: anotherfunc(*extraArgs)
  1. Yes, it’s allowed.
  2. You use the function as you would any other: anotherfunc(*extraArgs)

回答 5

  1. 是。通过在输入参数中包含函数调用,可以一次调用两个(或多个)函数。

例如:

def anotherfunc(inputarg1, inputarg2):
    pass
def myfunc(func = anotherfunc):
    print func

调用myfunc时,请执行以下操作:

myfunc(anotherfunc(inputarg1, inputarg2))

这将打印anotherfunc的返回值。

希望这可以帮助!

  1. Yes. By including the function call in your input argument/s, you can call two (or more) functions at once.

For example:

def anotherfunc(inputarg1, inputarg2):
    pass
def myfunc(func = anotherfunc):
    print func

When you call myfunc, you do this:

myfunc(anotherfunc(inputarg1, inputarg2))

This will print the return value of anotherfunc.

Hope this helps!


回答 6

函数内部的函数:我们也可以将函数用作参数。

换句话说,我们可以说函数的输出也是对象的引用,请参阅下文,内部函数的输出如何引用外部函数,如下所示。

def out_func(a):

  def in_func(b):
       print(a + b + b + 3)
  return in_func

obj = out_func(1)
print(obj(5))

结果将是.. 14

希望这可以帮助。

Function inside function: we can use the function as parameter too..

In other words, we can say an output of a function is also a reference for an object, see below how the output of inner function is referencing to the outside function like below..

def out_func(a):

  def in_func(b):
       print(a + b + b + 3)
  return in_func

obj = out_func(1)
print(obj(5))

the result will be.. 14

Hope this helps.


回答 7

def x(a):
    print(a)
    return a

def y(a):
    return a

y(x(1))
def x(a):
    print(a)
    return a

def y(a):
    return a

y(x(1))

回答 8

def x(a):
    print(a)
    return a

def y(func_to_run, a):
    return func_to_run(a)

y(x, 1)

我认为这将是一个更适当的示例。现在我想知道的是,是否有一种方法可以编码要在提交给另一个函数的参数中使用的函数。我相信在C ++中,但是在Python中我不确定。

def x(a):
    print(a)
    return a

def y(func_to_run, a):
    return func_to_run(a)

y(x, 1)

That I think would be a more proper sample. Now what I wonder is if there is a way to code the function to use within the argument submission to another function. I believe there is in C++, but in Python I am not sure.


回答 9

装饰器在Python中非常强大,因为它允许程序员将函数作为参数传递,也可以在另一个函数中定义函数。

def decorator(func):
      def insideFunction():
        print("This is inside function before execution")
        func()
      return insideFunction

def func():
    print("I am argument function")

func_obj = decorator(func) 
func_obj()

输出量

  • 这是执行之前的内部函数
  • 我是参数函数

Decorators are very powerful in Python since it allows programmers to pass function as argument and can also define function inside another function.

def decorator(func):
      def insideFunction():
        print("This is inside function before execution")
        func()
      return insideFunction

def func():
    print("I am argument function")

func_obj = decorator(func) 
func_obj()

Output

  • This is inside function before execution
  • I am argument function

在Python中通过引用传递整数

问题:在Python中通过引用传递整数

如何在Python中通过引用传递整数?

我想修改传递给函数的变量的值。我读过Python中的所有内容都是按值传递的,但是必须有一个简单的技巧。例如,在Java中,你可以通过引用类型的IntegerLong等等。

  1. 如何通过引用将整数传递给函数?
  2. 最佳做法是什么?

How can I pass an integer by reference in Python?

I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.

  1. How can I pass an integer into a function by reference?
  2. What are the best practices?

回答 0

在Python中,这种方式不太有效。Python将引用传递给对象。在函数内部,您有一个对象-您可以随意更改该对象(如果可能)。但是,整数是不可变的。一种解决方法是在可以更改的容器中传递整数:

def change(x):
    x[0] = 3

x = [1]
change(x)
print x

这充其量是丑陋的/笨拙的,但是您不会在Python中做得更好。原因是因为在Python中,赋值(=)接受右侧对象结果的任何对象,并将其绑定到左侧对象*(或将其传递给适当的函数)。

了解了这一点,我们可以看到为什么无法更改函数内部不可变对象的值的原因-您不能更改其任何属性,因为它是不可变的,并且您不能仅给新的“变量”赋值值,因为您实际上是在创建一个新对象(与旧对象不同),并为其赋予旧对象在本地命名空间中的名称。

通常,解决方法是简单地返回所需的对象:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

*在上述第一个示例中,3实际上传递给x.__setitem__

It doesn’t quite work that way in Python. Python passes references to objects. Inside your function you have an object — You’re free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:

def change(x):
    x[0] = 3

x = [1]
change(x)
print x

This is ugly/clumsy at best, but you’re not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).

Understanding this, we can see why there is no way to change the value of an immutable object inside a function — you can’t change any of its attributes because it’s immutable, and you can’t just assign the “variable” a new value because then you’re actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.

Usually the workaround is to simply return the object that you want:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

*In the first example case above, 3 actually gets passed to x.__setitem__.


回答 1

您需要通过引用传递的大多数情况是,您需要将多个值返回给调用方。“最佳实践”是使用多个返回值,这在Python中比在Java等语言中要容易得多。

这是一个简单的例子:

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A “best practice” is to use multiple return values, which is much easier to do in Python than in languages like Java.

Here’s a simple example:

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

回答 2

不完全直接传递值,而是像传递值一样使用它。

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

注意事项:

  • nonlocal 在python 3中引入
  • 如果封闭范围是全局范围,请使用global代替nonlocal

Not exactly passing a value directly, but using it as if it was passed.

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

Caveats:

  • nonlocal was introduced in python 3
  • If the enclosing scope is the global one, use global instead of nonlocal.

回答 3

确实,最佳做法是退后一步,然后询问您是否真的需要这样做。为什么要修改传递给函数的变量的值?

如果您需要快速破解,最快的方法是传递一个list整数,并粘贴[0]如mgilson的答案所示,在每次使用时使用。

如果您需要做一些更重要的事情,请写一个 class具有int作为属性的,以便您可以对其进行设置。当然,这会迫使您为类和属性命名,如果您什么都没想到,请返回并再次阅读该句子几次,然后使用list

更一般而言,如果您尝试将某些Java习惯用法直接移植到Python,那么您做错了。即使有直接对应的内容(如static/ @staticmethod),您仍然不想在大多数Python程序中使用它,只是因为您要在Java中使用它。

Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you’re passing in to the function?

If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson’s answer demonstrates.

If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can’t think of anything, go back and read the sentence again a few times, and then use the list.

More generally, if you’re trying to port some Java idiom directly to Python, you’re doing it wrong. Even when there is something directly corresponding (as with static/@staticmethod), you still don’t want to use it in most Python programs just because you’d use it in Java.


回答 4

在Python中,每个值都是引用(指向对象的指针),就像Java中的非基本体一样。另外,像Java一样,Python仅按值传递。因此,从语义上讲,它们几乎是相同的。

既然您在问题中提到Java,那么我想看看您如何实现Java的目标。如果您可以用Java展示它,那么我可以向您展示如何用Python完全等效地展示它。

In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.

Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.


回答 5

numpy的单元素数组是可变的,但对于大多数用途,它可以被就好像它是一个数值蟒变量进行评价。因此,它比单元素列表更方便使用按引用编号的容器。

    import numpy as np
    def triple_var_by_ref(x):
        x[0]=x[0]*3
    a=np.array([2])
    triple_var_by_ref(a)
    print(a+1)

输出:

3

A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it’s a more convenient by-reference number container than a single-element list.

    import numpy as np
    def triple_var_by_ref(x):
        x[0]=x[0]*3
    a=np.array([2])
    triple_var_by_ref(a)
    print(a+1)

output:

3

回答 6

class PassByReference:
    def Change(self, var):
        self.a = var
        print(self.a)
s=PassByReference()
s.Change(5)     
class PassByReference:
    def Change(self, var):
        self.a = var
        print(self.a)
s=PassByReference()
s.Change(5)     

回答 7

也许这不是pythonic的方式,但是您可以这样做

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

Maybe it’s not pythonic way, but you can do this

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

回答 8

可能比length-1列表技巧更能自我记录的是旧的空类型技巧:

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)

Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)

回答 9

在Python中,所有内容均按值传递,但如果要修改某些状态,则可以更改传递给方法的列表或对象内的整数值。

In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that’s passed to a method.


回答 10

正确的答案是使用一个类,然后将值放入该类中,这使您可以完全按需传递引用。

class Thing:
  def __init__(self,a):
    self.a = a
def dosomething(ref)
  ref.a += 1

t = Thing(3)
dosomething(t)
print("T is now",t.a)

The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.

class Thing:
  def __init__(self,a):
    self.a = a
def dosomething(ref)
  ref.a += 1

t = Thing(3)
dosomething(t)
print("T is now",t.a)


在Python中强制命名参数

问题:在Python中强制命名参数

在Python中,您可能有一个函数定义:

def info(object, spacing=10, collapse=1)

可以通过以下任何一种方式调用:

info(odbchelper)                    
info(odbchelper, 12)                
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

多亏了Python允许任意顺序的参数(只要它们被命名)。

我们遇到的问题是,随着一些更大的函数的增长,人们可能会在spacing和之间添加参数collapse,这意味着错误的值可能会传递给未命名的参数。此外,有时不清楚需要输入什么。我们正在寻找一种方法来强迫人们命名某些参数-不仅是编码标准,还是理想的标志或pydev插件?

因此,在上述4个示例中,由于所有参数均已命名,因此只有最后一个示例可以通过检查。

奇怪的是,我们只会为某些功能打开它,但是有关如何实现此功能的任何建议-甚至可能的话,我们将不胜感激。

In Python you may have a function definition:

def info(object, spacing=10, collapse=1)

which could be called in any of the following ways:

info(odbchelper)                    
info(odbchelper, 12)                
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

thanks to Python’s allowing of any-order arguments, so long as they’re named.

The problem we’re having is as some of our larger functions grow, people might be adding parameters between spacing and collapse, meaning that the wrong values may be going to parameters that aren’t named. In addition sometimes it’s not always clear as to what needs to go in. We’re after a way to force people to name certain parameters – not just a coding standard, but ideally a flag or pydev plugin?

so that in the above 4 examples, only the last would pass the check as all the parameters are named.

Odds are we’ll only turn it on for certain functions, but any suggestions as to how to implement this – or if it’s even possible would be appreciated.


回答 0

在Python 3中-是,您可以*在参数列表中指定。

文档

“ *”或“ * identifier”之后的参数仅是关键字参数,并且只能使用关键字参数传递。

>>> def foo(pos, *, forcenamed):
...   print(pos, forcenamed)
... 
>>> foo(pos=10, forcenamed=20)
10 20
>>> foo(10, forcenamed=20)
10 20
>>> foo(10, 20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 positional argument (2 given)

也可以结合使用**kwargs

def foo(pos, *, forcenamed, **kwargs):

In Python 3 – Yes, you can specify * in the argument list.

From docs:

Parameters after “*” or “*identifier” are keyword-only parameters and may only be passed used keyword arguments.

>>> def foo(pos, *, forcenamed):
...   print(pos, forcenamed)
... 
>>> foo(pos=10, forcenamed=20)
10 20
>>> foo(10, forcenamed=20)
10 20
>>> foo(10, 20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 positional argument (2 given)

This can also be combined with **kwargs:

def foo(pos, *, forcenamed, **kwargs):

回答 1

您可以通过以下方式定义函数来强制人们在Python3中使用关键字参数。

def foo(*, arg0="default0", arg1="default1", arg2="default2"):
    pass

通过将第一个参数设置为不带名称的位置参数,您可以强制每个调用该函数的人都使用关键字参数,这正是我想问的。在Python2中,唯一的方法是定义一个这样的函数

def foo(**kwargs):
    pass

这将迫使调用者使用kwargs,但这并不是一个很好的解决方案,因为您随后必须进行检查以仅接受所需的参数。

You can force people to use keyword arguments in Python3 by defining a function in the following way.

def foo(*, arg0="default0", arg1="default1", arg2="default2"):
    pass

By making the first argument a positional argument with no name you force everyone who calls the function to use the keyword arguments which is what I think you were asking about. In Python2 the only way to do this is to define a function like this

def foo(**kwargs):
    pass

That’ll force the caller to use kwargs but this isn’t that great of a solution as you’d then have to put a check to only accept the argument that you need.


回答 2

的确,大多数编程语言都将参数顺序作为函数调用协定的一部分,但这不是必须的。为什么会这样?我对这个问题的理解是,Python在这方面是否与其他编程语言有所不同。除了适用于Python 2的其他良好答案外,请考虑以下因素:

__named_only_start = object()

def info(param1,param2,param3,_p=__named_only_start,spacing=10,collapse=1):
    if _p is not __named_only_start:
        raise TypeError("info() takes at most 3 positional arguments")
    return str(param1+param2+param3) +"-"+ str(spacing) +"-"+ str(collapse)

调用方能够提供参数spacing并按collapse位置(无exceptions)提供的唯一方法是:

info(arg1, arg2, arg3, module.__named_only_start, 11, 2)

在Python中,不使用属于其他模块的私有元素的约定已经非常基本。与Python本身一样,这种参数约定只能被强制执行。

否则,调用将采用以下形式:

info(arg1, arg2, arg3, spacing=11, collapse=2)

一个电话

info(arg1, arg2, arg3, 11, 2)

将为参数分配值11 _p以及该函数的第一条指令引发的异常。

特点:

  • 之前_p=__named_only_start的参数按位置(或按名称)被接受。
  • 之后的参数_p=__named_only_start必须仅通过名称提供(除非__named_only_start获得并使用了有关特殊前哨对象的知识)。

优点:

  • 参数在数量和含义上都是明确的(当然,如果还选择了好名字,则在后面)。
  • 如果将前哨指定为第一个参数,则所有参数都需要按名称指定。
  • 调用该函数时,可以通过__named_only_start在相应位置使用哨兵对象来切换到位置模式。
  • 可以预见到比其他替代方案更好的性能。

缺点:

  • 检查发生在运行时,而不是编译时。
  • 使用额外的参数(尽管不是参数)和额外的检查。相对于常规功能而言,性能下降较小。
  • 功能是没有该语言直接支持的黑客(请参阅下面的注释)。
  • 调用该函数时,可以通过__named_only_start在正确的位置使用哨兵对象来切换到位置模式。是的,这也可以看作是专业人士。

请记住,该答案仅对Python 2有效。Python3实现了类似的,但非常优雅的,语言支持的机制,在其他答案中也有描述。

我发现,当我打开思路思考时,没有问题或其他人的决定看起来是愚蠢,愚蠢或愚蠢的。恰恰相反:我通常会学到很多东西。

True, most programming languages make parameter order part of the function call contract, but this doesn’t need to be so. Why would it? My understanding of the question is, then, if Python is any different to other programming languages in this respect. In addition to other good answers for Python 2, please consider the following:

__named_only_start = object()

def info(param1,param2,param3,_p=__named_only_start,spacing=10,collapse=1):
    if _p is not __named_only_start:
        raise TypeError("info() takes at most 3 positional arguments")
    return str(param1+param2+param3) +"-"+ str(spacing) +"-"+ str(collapse)

The only way a caller would be able to provide arguments spacing and collapse positionally (without an exception) would be:

info(arg1, arg2, arg3, module.__named_only_start, 11, 2)

The convention of not using private elements belonging to other modules already is very basic in Python. As with Python itself, this convention for parameters would only be semi-enforced.

Otherwise, calls would need to be of the form:

info(arg1, arg2, arg3, spacing=11, collapse=2)

A call

info(arg1, arg2, arg3, 11, 2)

would assign value 11 to parameter _p and an exception risen by the function’s first instruction.

Characteristics:

  • Parameters before _p=__named_only_start are admitted positionally (or by name).
  • Parameters after _p=__named_only_start must be provided by name only (unless knowledge about the special sentinel object __named_only_start is obtained and used).

Pros:

  • Parameters are explicit in number and meaning (the later if good names are also chosen, of course).
  • If the sentinel is specified as first parameter, then all arguments need to be specified by name.
  • When calling the function, it’s possible to switch to positional mode by using the sentinel object __named_only_start in the corresponding position.
  • A better performance than other alternatives can be anticipated.

Cons:

  • Checking occurs during run-time, not compile-time.
  • Use of an extra parameter (though not argument) and an additional check. Small performance degradation respect to regular functions.
  • Functionality is a hack without direct support by the language (see note below).
  • When calling the function, it’s possible to switch to positional mode by using the sentinel object __named_only_start in the right position. Yes, this can also be seen as a pro.

Please do keep in mind that this answer is only valid for Python 2. Python 3 implements the similar, but very elegant, language-supported mechanism described in other answers.

I’ve found that when I open my mind and think about it, no question or other’s decision seems stupid, dumb, or just silly. Quite on the contrary: I typically learn a lot.


回答 3

您可以通过使“伪造的”第一个关键字参数具有默认值而不会“自然地”出现,从而以在Python 2和Python 3中都可以使用的方式 来实现。该关键字参数前面可以有一个或多个没有值的参数:

_dummy = object()

def info(object, _kw=_dummy, spacing=10, collapse=1):
    if _kw is not _dummy:
        raise TypeError("info() takes 1 positional argument but at least 2 were given")

这将允许:

info(odbchelper)        
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

但不是:

info(odbchelper, 12)                

如果将功能更改为:

def info(_kw=_dummy, spacing=10, collapse=1):

那么所有参数都必须具有关键字,并且info(odbchelper)将不再起作用。

这样,您便可以将其他关键字参数放在后面的任何位置_kw,而不必强迫您将其放在最后一个条目之后。这通常是有道理的,例如,按逻辑对事物进行分组或按字母顺序排列关键字可以帮助维护和开发。

因此,无需还原到def(**kwargs)在智能编辑器中使用和丢失签名信息。您的社会契约是通过强迫(其中一些)要求关键字(它们的显示顺序)变得不相关来提供某些信息。

You can do that in a way that works in both Python 2 and Python 3, by making a “bogus” first keyword argument with a default value that will not occur “naturally”. That keyword argument can be preceded by one or more arguments without value:

_dummy = object()

def info(object, _kw=_dummy, spacing=10, collapse=1):
    if _kw is not _dummy:
        raise TypeError("info() takes 1 positional argument but at least 2 were given")

This will allow:

info(odbchelper)        
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

but not:

info(odbchelper, 12)                

If you change the function to:

def info(_kw=_dummy, spacing=10, collapse=1):

then all arguments must have keywords and info(odbchelper) will no longer work.

This will allow you to position additional keyword arguments any place after _kw, without forcing you to put them after the last entry. This often makes sense, e.g. grouping thing logically or arranging keywords alphabetically can help with maintenance and development.

So there is no need to revert to using def(**kwargs) and losing the signature information in your smart editor. Your social contract is to provide certain information, by forcing (some of them) to require keywords, the order these are presented in, has become irrelevant.


回答 4

更新:

我意识到使用**kwargs并不能解决问题。如果您的程序员根据需要更改函数参数,则可以例如将函数更改为:

def info(foo, **kwargs):

并且旧代码将再次中断(因为现在每个函数调用都必须包含第一个参数)。

确实归结为布莱恩所说的话。


(…)人们可能在spacingcollapse(…)之间添加了参数

通常,在更改函数时,新参数应始终结尾。否则,它将破坏代码。应该很明显。
如果有人更改了功能使代码中断,则必须拒绝此更改。
(正如布莱恩所说,这就像是一份合同)

(…)有时不清楚需要输入什么。

通过查看函数的签名(即def info(object, spacing=10, collapse=1)),应该立即看到每个没有默认值的参数都是强制性的。参数的用途是
什么,应该放在文档字符串中。


旧答案(保持完整性)

这可能不是一个好的解决方案:

您可以通过以下方式定义函数:

def info(**kwargs):
    ''' Some docstring here describing possible and mandatory arguments. '''
    spacing = kwargs.get('spacing', 15)
    obj = kwargs.get('object', None)
    if not obj:
       raise ValueError('object is needed')

kwargs是包含任何关键字参数的字典。您可以检查是否存在强制性参数,如果不存在,则引发异常。

不利的一面是,可能不再是显而易见的,哪些参数是可能的,但是使用适当的文档字符串,应该没问题。

Update:

I realized that using **kwargs would not solve the problem. If your programmers change function arguments as they wish, one could, for example, change the function to this:

def info(foo, **kwargs):

and the old code would break again (because now every function call has to include the first argument).

It really comes down to what Bryan says.


(…) people might be adding parameters between spacing and collapse (…)

In general, when changing functions, new arguments should always go to the end. Otherwise it breaks the code. Should be obvious.
If someone changes the function so that the code breaks, this change has to be rejected.
(As Bryan says, it is like a contract)

(…) sometimes it’s not always clear as to what needs to go in.

By looking at the signature of the function (i.e def info(object, spacing=10, collapse=1) ) one should immediately see that every argument that has not a default value, is mandatory.
What the argument is for, should go into the docstring.


Old answer (kept for completeness):

This is probably not a good solution:

You can define functions this way:

def info(**kwargs):
    ''' Some docstring here describing possible and mandatory arguments. '''
    spacing = kwargs.get('spacing', 15)
    obj = kwargs.get('object', None)
    if not obj:
       raise ValueError('object is needed')

kwargs is a dictionary that contains any keyword argument. You can check whether a mandatory argument is present and if not, raise an exception.

The downside is, that it might not be that obvious anymore, which arguments are possible, but with a proper docstring, it should be fine.


回答 5

python3-only关键字参数(*)可以在python2.x中使用**kwargs

考虑以下python3代码:

def f(pos_arg, *, no_default, has_default='default'):
    print(pos_arg, no_default, has_default)

及其行为:

>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 3 were given
>>> f(1, no_default='hi')
1 hi default
>>> f(1, no_default='hi', has_default='hello')
1 hi hello
>>> f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() missing 1 required keyword-only argument: 'no_default'
>>> f(1, no_default=1, wat='wat')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'wat'

可以使用以下方法对此进行模拟,请注意TypeErrorKeyError在“必需的命名参数”情况下,我可以自由切换到,同样要使相同的异常类型也不会花费太多工作

def f(pos_arg, **kwargs):
    no_default = kwargs.pop('no_default')
    has_default = kwargs.pop('has_default', 'default')
    if kwargs:
        raise TypeError('unexpected keyword argument(s) {}'.format(', '.join(sorted(kwargs))))

    print(pos_arg, no_default, has_default)

行为:

>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (3 given)
>>> f(1, no_default='hi')
(1, 'hi', 'default')
>>> f(1, no_default='hi', has_default='hello')
(1, 'hi', 'hello')
>>> f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
KeyError: 'no_default'
>>> f(1, no_default=1, wat='wat')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in f
TypeError: unexpected keyword argument(s) wat

该食谱在python3.x中同样有效,但是如果您仅在python3.x中应避免使用

The python3 keyword-only arguments (*) can be simulated in python2.x with **kwargs

Consider the following python3 code:

def f(pos_arg, *, no_default, has_default='default'):
    print(pos_arg, no_default, has_default)

and its behaviour:

>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 3 were given
>>> f(1, no_default='hi')
1 hi default
>>> f(1, no_default='hi', has_default='hello')
1 hi hello
>>> f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() missing 1 required keyword-only argument: 'no_default'
>>> f(1, no_default=1, wat='wat')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'wat'

This can be simulated using the following, note I’ve taken the liberty of switching TypeError to KeyError in the “required named argument” case, it wouldn’t be too much work to make that the same exception type as well

def f(pos_arg, **kwargs):
    no_default = kwargs.pop('no_default')
    has_default = kwargs.pop('has_default', 'default')
    if kwargs:
        raise TypeError('unexpected keyword argument(s) {}'.format(', '.join(sorted(kwargs))))

    print(pos_arg, no_default, has_default)

And behaviour:

>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (3 given)
>>> f(1, no_default='hi')
(1, 'hi', 'default')
>>> f(1, no_default='hi', has_default='hello')
(1, 'hi', 'hello')
>>> f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
KeyError: 'no_default'
>>> f(1, no_default=1, wat='wat')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in f
TypeError: unexpected keyword argument(s) wat

The recipe works equally as well in python3.x, but should be avoided if you are python3.x only


回答 6

您可以将函数声明为**args仅接收。这将强制使用关键字参数,但是您需要做一些额外的工作以确保仅传递有效名称。

def foo(**args):
   print args

foo(1,2) # Raises TypeError: foo() takes exactly 0 arguments (2 given)
foo(hello = 1, goodbye = 2) # Works fine.

You could declare your functions as receiving **args only. That would mandate keyword arguments but you’d have some extra work to make sure only valid names are passed in.

def foo(**args):
   print args

foo(1,2) # Raises TypeError: foo() takes exactly 0 arguments (2 given)
foo(hello = 1, goodbye = 2) # Works fine.

回答 7

正如其他答案所说,更改功能签名是一个坏主意。在末尾添加新参数,或者在插入参数的情况下修复每个调用方。

如果仍要执行此操作,请使用函数装饰器inspect.getargspec函数。它将使用如下形式:

@require_named_args
def info(object, spacing=10, collapse=1):
    ....

的实现require_named_args留给读者练习。

我不会打扰。每次调用该函数的速度都会很慢,通过更仔细地编写代码,您将获得更好的结果。

As other answers say, changing function signatures is a bad idea. Either add new parameters to the end, or fix every caller if arguments are inserted.

If you still want to do it, use a function decorator and the inspect.getargspec function. It would be used something like this:

@require_named_args
def info(object, spacing=10, collapse=1):
    ....

Implementation of require_named_args is left as an exercise for the reader.

I would not bother. It will be slow every time the function is called, and you will get better results from writing code more carefully.


回答 8

您可以使用**运算符:

def info(**kwargs):

这样,人们被迫使用命名参数。

You could use the ** operator:

def info(**kwargs):

this way people are forced to use named parameters.


回答 9

def cheeseshop(kind, *arguments, **keywords):

在python中,如果使用* args,则意味着您可以为该参数传递n个参数-这将成为函数内部的列表以访问

如果使用** kw表示其关键字参数,则可以按dict的方式进行访问-您可以传递n个数量的kw args,并且如果要限制该用户必须按顺序输入序列和参数,则不要使用*和**-(它为大型架构提供通用解决方案的pythonic方法…)

如果要使用默认值限制功能,则可以在其中检查

def info(object, spacing, collapse)
  spacing = spacing or 10
  collapse = collapse or 1
def cheeseshop(kind, *arguments, **keywords):

in python if use *args that means you can pass n-number of positional arguments for this parameter – which will be accessed as a tuple inside the function.

And if use **kw that means its keyword arguments, that can be access as dict – you can pass n-number of kw args, and if you want to restrict that user must enter the sequence and arguments in order then don’t use * and ** – (its pythonic way to provide generic solutions for big architectures…)

if you want to restrict your function with default values then you can check inside it

def info(object, spacing, collapse)
  spacing = 10 if spacing is None else spacing
  collapse = 1 if collapse is None else collapse

回答 10

我不明白为什么程序员会首先在其他两个之间添加参数。

如果您希望函数参数与名称一起使用(例如, info(spacing=15, object=odbchelper)),则定义它们的顺序无关紧要,因此您最好将新参数放在最后。

如果您确实希望订单很重要,那么更改后就别指望了!

I don’t get why a programmer will add a parameter in between two others in the first place.

If you want the function parameters to be used with names (e.g. info(spacing=15, object=odbchelper) ) then it shouldn’t matter what order they are defined in, so you might as well put the new parameters at the end.

If you do want the order to matter then can’t expect anything to work if you change it!


在Matplotlib中,如何在同一图形上绘制多个函数?

问题:在Matplotlib中,如何在同一图形上绘制多个函数?

我如何可以绘制以下3个功能(即sincos并增加),在域t,在相同的数字?

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0, 2*math.pi, 400)

a = sin(t)
b = cos(t)
c = a + b

How can I plot the following 3 functions (i.e. sin, cos and the addition), on the domain t, in the same figure?

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0, 2*math.pi, 400)

a = sin(t)
b = cos(t)
c = a + b

回答 0

要在同一图形上绘制多个图形,您必须执行以下操作:

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0, 2*math.pi, 400)
a = sin(t)
b = cos(t)
c = a + b

plt.plot(t, a, 'r') # plotting t, a separately 
plt.plot(t, b, 'b') # plotting t, b separately 
plt.plot(t, c, 'g') # plotting t, c separately 
plt.show()

To plot multiple graphs on the same figure you will have to do:

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0, 2*math.pi, 400)
a = sin(t)
b = cos(t)
c = a + b

plt.plot(t, a, 'r') # plotting t, a separately 
plt.plot(t, b, 'b') # plotting t, b separately 
plt.plot(t, c, 'g') # plotting t, c separately 
plt.show()


回答 1

也许是更Python化的方式。

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0,2*math.pi,400)
a = sin(t)
b = cos(t)
c = a + b

plt.plot(t, a, t, b, t, c)
plt.show()

Perhaps a more pythonic way of doing so.

from numpy import *
import math
import matplotlib.pyplot as plt

t = linspace(0,2*math.pi,400)
a = sin(t)
b = cos(t)
c = a + b

plt.plot(t, a, t, b, t, c)
plt.show()


回答 2

只需使用功能plot如下

figure()
...
plot(t, a)
plot(t, b)
plot(t, c)

Just use the function plot as follows

figure()
...
plot(t, a)
plot(t, b)
plot(t, c)

循环创建函数

问题:循环创建函数

我正在尝试在循环内创建函数:

functions = []

for i in range(3):
    def f():
        return i

    # alternatively: f = lambda: i

    functions.append(f)

问题在于所有功能最终都相同。这三个函数都没有返回0、1和2,而是返回2:

print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output:   [2, 2, 2]

为什么会发生这种情况,我应该怎么做才能获得分别输出0、1和2的3个不同函数?

I’m trying to create functions inside of a loop:

functions = []

for i in range(3):
    def f():
        return i

    # alternatively: f = lambda: i

    functions.append(f)

The problem is that all functions end up being the same. Instead of returning 0, 1, and 2, all three functions return 2:

print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output:   [2, 2, 2]

Why is this happening, and what should I do to get 3 different functions that output 0, 1, and 2 respectively?


回答 0

您在后期绑定方面遇到了麻烦 -每个函数都i尽可能晚地查找(因此,在循环结束后调用时,i将设置为2)。

可以通过强制早期绑定轻松解决:更改def f():def f(i=i):

def f(i=i):
    return i

缺省值(右手i输入i=i是参数名的默认值,i左手i输入i=i)是在def时间而不是在call时间查找的,因此从本质上讲,它们是一种专门查找早期绑定的方法。

如果您担心要f获得额外的参数(因此有可能被错误地调用),则有一种更复杂的方法,其中涉及将闭包用作“函数工厂”:

def make_f(i):
    def f():
        return i
    return f

并在循环中使用f = make_f(i)而不是def语句。

You’re running into a problem with late binding — each function looks up i as late as possible (thus, when called after the end of the loop, i will be set to 2).

Easily fixed by forcing early binding: change def f(): to def f(i=i): like this:

def f(i=i):
    return i

Default values (the right-hand i in i=i is a default value for argument name i, which is the left-hand i in i=i) are looked up at def time, not at call time, so essentially they’re a way to specifically looking for early binding.

If you’re worried about f getting an extra argument (and thus potentially being called erroneously), there’s a more sophisticated way which involved using a closure as a “function factory”:

def make_f(i):
    def f():
        return i
    return f

and in your loop use f = make_f(i) instead of the def statement.


回答 1

说明

这里的问题是创建i函数时未保存的值f。而是查询何时调用f的值。i

如果您考虑一下,这种行为是很合理的。实际上,这是功能起作用的唯一合理方式。假设您有一个访问全局变量的函数,如下所示:

global_var = 'foo'

def my_function():
    print(global_var)

global_var = 'bar'
my_function()

当您阅读此代码时,您当然会希望它显示“ bar”,而不是“ foo”,因为在global_var声明函数后,的值已更改。您自己的代码中发生了同样的事情:在您调用时f,的值i已更改并设置为2

解决方案

实际上,有很多方法可以解决此问题。以下是一些选择:

  • i通过将其用作默认参数来强制早期绑定

    与闭包变量(如i)不同,定义函数时会立即对默认参数进行求值:

    for i in range(3):
        def f(i=i):  # <- right here is the important bit
            return i
    
        functions.append(f)

    深入了解其工作方式/原因:函数的默认参数存储为函数的属性;因此,快照的当前i并保存。

    >>> i = 0
    >>> def f(i=i):
    ...     pass
    >>> f.__defaults__  # this is where the current value of i is stored
    (0,)
    >>> # assigning a new value to i has no effect on the function's default arguments
    >>> i = 5
    >>> f.__defaults__
    (0,)
  • 使用函数工厂捕获当前值 i闭包中

    问题的根源是i可以更改的变量。我们可以通过创建另一个永不更改的变量来解决此问题,最简单的方法是闭包

    def f_factory(i):
        def f():
            return i  # i is now a *local* variable of f_factory and can't ever change
        return f
    
    for i in range(3):           
        f = f_factory(i)
        functions.append(f)
  • 使用functools.partial绑定的当前值if

    functools.partial使您可以将参数附加到现有函数。在某种程度上,它也是一种功能工厂。

    import functools
    
    def f(i):
        return i
    
    for i in range(3):    
        f_with_i = functools.partial(f, i)  # important: use a different variable than "f"
        functions.append(f_with_i)

注意:仅当您为变量分配新值时,这些解决方案才有效。如果修改存储在变量中的对象,您将再次遇到相同的问题:

>>> i = []  # instead of an int, i is now a *mutable* object
>>> def f(i=i):
...     print('i =', i)
...
>>> i.append(5)  # instead of *assigning* a new value to i, we're *mutating* it
>>> f()
i = [5]

请注意,i即使我们将其变成默认参数,它仍然有多大变化!如果你的代码发生变异 i,那么你就必须绑定一个副本i你的功能,如下所示:

  • def f(i=i.copy()):
  • f = f_factory(i.copy())
  • f_with_i = functools.partial(f, i.copy())

The Explanation

The issue here is that the value of i is not saved when the function f is created. Rather, f looks up the value of i when it is called.

If you think about it, this behavior makes perfect sense. In fact, it’s the only reasonable way functions can work. Imagine you have a function that accesses a global variable, like this:

global_var = 'foo'

def my_function():
    print(global_var)

global_var = 'bar'
my_function()

When you read this code, you would – of course – expect it to print “bar”, not “foo”, because the value of global_var has changed after the function was declared. The same thing is happening in your own code: By the time you call f, the value of i has changed and been set to 2.

The Solution

There are actually many ways to solve this problem. Here are a few options:

  • Force early binding of i by using it as a default argument

    Unlike closure variables (like i), default arguments are evaluated immediately when the function is defined:

    for i in range(3):
        def f(i=i):  # <- right here is the important bit
            return i
    
        functions.append(f)
    

    To give a little bit of insight into how/why this works: A function’s default arguments are stored as an attribute of the function; thus the current value of i is snapshotted and saved.

    >>> i = 0
    >>> def f(i=i):
    ...     pass
    >>> f.__defaults__  # this is where the current value of i is stored
    (0,)
    >>> # assigning a new value to i has no effect on the function's default arguments
    >>> i = 5
    >>> f.__defaults__
    (0,)
    
  • Use a function factory to capture the current value of i in a closure

    The root of your problem is that i is a variable that can change. We can work around this problem by creating another variable that is guaranteed to never change – and the easiest way to do this is a closure:

    def f_factory(i):
        def f():
            return i  # i is now a *local* variable of f_factory and can't ever change
        return f
    
    for i in range(3):           
        f = f_factory(i)
        functions.append(f)
    
  • Use functools.partial to bind the current value of i to f

    functools.partial lets you attach arguments to an existing function. In a way, it too is a kind of function factory.

    import functools
    
    def f(i):
        return i
    
    for i in range(3):    
        f_with_i = functools.partial(f, i)  # important: use a different variable than "f"
        functions.append(f_with_i)
    

Caveat: These solutions only work if you assign a new value to the variable. If you modify the object stored in the variable, you’ll experience the same problem again:

>>> i = []  # instead of an int, i is now a *mutable* object
>>> def f(i=i):
...     print('i =', i)
...
>>> i.append(5)  # instead of *assigning* a new value to i, we're *mutating* it
>>> f()
i = [5]

Notice how i still changed even though we turned it into a default argument! If your code mutates i, then you must bind a copy of i to your function, like so:

  • def f(i=i.copy()):
  • f = f_factory(i.copy())
  • f_with_i = functools.partial(f, i.copy())

使用哪个更合适:lambda函数或嵌套函数(’def’)?

问题:使用哪个更合适:lambda函数或嵌套函数(’def’)?

我主要使用lambda函数,但有时使用似乎提供相同行为的嵌套函数。

这是一些琐碎的示例,如果在另一个函数中找到它们,它们在功能上会做同样的事情:

Lambda函数

>>> a = lambda x : 1 + x
>>> a(5)
6

嵌套功能

>>> def b(x): return 1 + x

>>> b(5)
6

使用一个相对于另一个有优势吗?(性能?可读性?局限性?一致性?等)

有关系吗 如果不这样做,那确实违反了Python原则:

应该有一种(最好只有一种)明显的方式来做到这一点

I mostly use lambda functions but sometimes use nested functions that seem to provide the same behavior.

Here are some trivial examples where they functionally do the same thing if either were found within another function:

Lambda function

>>> a = lambda x : 1 + x
>>> a(5)
6

Nested function

>>> def b(x): return 1 + x

>>> b(5)
6

Are there advantages to using one over the other? (Performance? Readability? Limitations? Consistency? etc.)

Does it even matter? If it doesn’t then does that violate the Pythonic principle:

There should be one—and preferably only one—obvious way to do it.


回答 0

如果需要将分配lambda给名称,请改用a defdefs只是分配的语法糖,因此结果是相同的,并且它们更具灵活性和可读性。

lambdas只能使用一次,丢弃没有名称的函数。

但是,这种用例很少见。您很少需要传递未命名的函数对象。

内建函数map()filter()需要函数对象,但是列表理解生成器表达式通常比那些函数更具可读性,并且可以覆盖所有用例,而无需使用lambda。

对于情况下,你真的需要一个小的函数对象,你应该使用operator模块的功能,如operator.add代替lambda x, y: x + y

如果您仍然需要一些lambda未涵盖的内容,则可以考虑编写def,以提高可读性。如果功能比operator模块中的功能更复杂,则a def可能更好。

因此,现实世界中的好用lambda例非常少见。

If you need to assign the lambda to a name, use a def instead. defs are just syntactic sugar for an assignment, so the result is the same, and they are a lot more flexible and readable.

lambdas can be used for use once, throw away functions which won’t have a name.

However, this use case is very rare. You rarely need to pass around unnamed function objects.

The builtins map() and filter() need function objects, but list comprehensions and generator expressions are generally more readable than those functions and can cover all use cases, without the need of lambdas.

For the cases you really need a small function object, you should use the operator module functions, like operator.add instead of lambda x, y: x + y

If you still need some lambda not covered, you might consider writing a def, just to be more readable. If the function is more complex than the ones at operator module, a def is probably better.

So, real world good lambda use cases are very rare.


回答 1

实际上,对我来说有两个区别:

首先是关于他们做什么以及他们返回什么:

  • def是不返回任何内容并在本地命名空间中创建“名称”的关键字。

  • lambda是一个关键字,它返回一个函数对象,并且不在本地命名空间中创建“名称”。

因此,如果您需要调用带有函数对象的函数,则在一行python代码中执行此操作的唯一方法是使用lambda。def没有等效功能。

在某些框架中,这实际上很常见。例如,我经常使用Twisted

d.addCallback(lambda result: setattr(self, _someVariable, result))

是很常见的,并且对lambda更为简洁。

第二点区别是允许实际执行的功能。

  • 用’def’定义的函数可以包含任何python代码
  • 用“ lambda”定义的函数必须求值为表达式,因此不能包含诸如print,import,raise,…之类的语句。

例如,

def p(x): print x

如预期般运作

lambda x: print x

是一个SyntaxError。

当然,也有变通方法-代替printsys.stdout.write,或import__import__。但是通常情况下,最好还是使用一个函数。

Practically speaking, to me there are two differences:

The first is about what they do and what they return:

  • def is a keyword that doesn’t return anything and creates a ‘name’ in the local namespace.

  • lambda is a keyword that returns a function object and does not create a ‘name’ in the local namespace.

Hence, if you need to call a function that takes a function object, the only way to do that in one line of python code is with a lambda. There’s no equivalent with def.

In some frameworks this is actually quite common; for example, I use Twisted a lot, and so doing something like

d.addCallback(lambda result: setattr(self, _someVariable, result))

is quite common, and more concise with lambdas.

The second difference is about what the actual function is allowed to do.

  • A function defined with ‘def’ can contain any python code
  • A function defined with ‘lambda’ has to evaluate to an expression, and can thus not contain statements like print, import, raise, …

For example,

def p(x): print x

works as expected, while

lambda x: print x

is a SyntaxError.

Of course, there are workarounds – substitute print with sys.stdout.write, or import with __import__. But usually you’re better off going with a function in that case.


回答 2

Guido van Rossum 在这次采访中说,他希望自己不要让“ lambda”进入Python:

问:您最不满意Python的什么功能?

有时我太快地接受了贡献,后来才意识到这是一个错误。一个例子就是一些函数式编程功能,例如lambda函数。lambda是一个关键字,可让您创建一个小的匿名函数;内置函数(例如map,filter和reduce)可在序列类型(例如列表)上运行该函数。

在实践中,结果并非如此。Python只有两个范围:本地和全局。这使编写lambda函数很痛苦,因为您经常想在lambda定义的作用域中访问变量,但由于这两个作用域而不能。有办法解决这个问题,但这有点不合时宜。在Python中,通常只使用for循环而不是搞乱lambda函数似乎容易得多。只有当已有内置功能可以满足您的需求时,地图和朋友才能正常工作。

恕我直言,Iambdas有时可能很方便,但是通常以可读性为代价很方便。你能告诉我这是怎么做的:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

我写了它,花了我一分钟才弄清楚。这是来自欧拉计划-我不会说哪个问题,因为我讨厌剧透,但是它只需要0.124秒即可:)

In this interview, Guido van Rossum says he wishes he hadn’t let ‘lambda’ into Python:

Q. What feature of Python are you least pleased with?

Sometimes I’ve been too quick in accepting contributions, and later realized that it was a mistake. One example would be some of the functional programming features, such as lambda functions. lambda is a keyword that lets you create a small anonymous function; built-in functions such as map, filter, and reduce run a function over a sequence type, such as a list.

In practice, it didn’t turn out that well. Python only has two scopes: local and global. This makes writing lambda functions painful, because you often want to access variables in the scope where the lambda was defined, but you can’t because of the two scopes. There’s a way around this, but it’s something of a kludge. Often it seems much easier in Python to just use a for loop instead of messing around with lambda functions. map and friends work well only when there’s already a built-in function that does what you want.

IMHO, Iambdas can be convenient sometimes, but usually are convenient at the expense of readibility. Can you tell me what this does:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

I wrote it, and it took me a minute to figure it out. This is from Project Euler – i won’t say which problem because i hate spoilers, but it runs in 0.124 seconds :)


回答 3

对于n = 1000,这是调用函数与lambda的时间:

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

For n=1000 here’s some timeit’s of calling a function vs a lambda:

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

回答 4

性能:

创建一个功能lambda速度稍快比创建它def。差异是由于def在locals表中创建了一个名称条目。生成的函数具有相同的执行速度。


可读性:

对于大多数Python用户而言,Lambda函数的可读性较差,但在某些情况下也更为简洁。考虑从使用非函数例程转换为函数例程:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

如您所见,在lambda您只需要添加lambda v:到原始非功能性版本以转换为功能性版本的意义上,该版本更短且更“容易” 。它也更加简洁。但是请记住,许多Python用户会对lambda语法感到困惑,因此,您失去的长度和真正的复杂性可能会在其他编码人员的困惑中重新获得。


局限性:

  • lambda 除非分配给变量名称,否则函数只能使用一次。
  • lambda分配给变量名的def函数比函数没有优势。
  • lambda 功能可能很难或无法腌制。
  • def 必须仔细选择函数的名称,以使其具有合理的描述性和唯一性,或者至少在范围内未使用。

一致性:

Python大多避免使用函数式编程约定,而倾向于使用过程性和更简单的目标语义。该lambda操作员站直接的对比这种偏见。此外,作为已经流行的替代方法def,该lambda函数为您的语法增加了多样性。有些人会认为这不太一致。


预先存在的功能:

正如其他人所指出的lambda,该领域的许多用途可以由operator或其他模块的成员代替。例如:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

在许多情况下,使用预先存在的功能可以使代码更具可读性。


Python原则:“应该有一种-最好只有一种-显而易见的方法”

这类似于真理教义的单一来源。不幸的是,单行之道的原则一直是Python的渴望,而不是真正的指导原则。考虑一下Python中非常强大的数组理解。它们在功能上等效于mapfilter函数:

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambdadef一样。

这是一个见解,但是我想说,Python语言中用于一般用途的任何东西如果没有明显破坏任何东西,都足够“ Pythonic”。

Performance:

Creating a function with lambda is slightly faster than creating it with def. The difference is due to def creating a name entry in the locals table. The resulting function has the same execution speed.


Readability:

Lambda functions are somewhat less readable for most Python users, but also much more concise in some circumstances. Consider converting from using non-functional to functional routine:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

As you can see, the lambda version is shorter and “easier” in the sense that you only need to add lambda v: to the original non-functional version to convert to the functional version. It’s also a lot more concise. But remember, a lot of Python users will be confused by the lambda syntax, so what you lose in length and real complexity might be gained back in confusion from fellow coders.


Limitations:

  • lambda functions can only be used once, unless assigned to a variable name.
  • lambda functions assigned to variable names have no advantage over def functions.
  • lambda functions can be difficult or impossible to pickle.
  • def functions’ names must be carefully chosen to be reasonably descriptive and unique or at least otherwise unused in scope.

Consistency:

Python mostly avoids functional programming conventions in favor of procedural and simpler objective semantics. The lambda operator stands in direct contrast to this bias. Moreover, as an alternative to the already prevalent def, the lambda function adds diversity to your syntax. Some would consider that less consistent.


Pre-existing functions:

As noted by others, many uses of lambda in the field can be replaced by members of the operator or other modules. For instance:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

Using the pre-existing function can make code more readable in many cases.


The Pythonic principle: “There should be one—and preferably only one—obvious way to do it”

That’s similar to the single source of truth doctrine. Unfortunately, the single-obvious-way-to-do-it principle has always been more an wistful aspiration for Python, rather than a true guiding principal. Consider the very-powerful array comprehensions in Python. They are functionally equivalent to the map and filter functions:

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambda and def are the same.

It’s a matter of opinion, but I would say that anything in the Python language intended for general use which doesn’t obviously break anything is “Pythonic” enough.


回答 5

更可取的是:lambda函数还是嵌套函数(def)?

与常规函数相比,使用lambda有一个优点:它们是在表达式中创建的。

有几个缺点:

  • 没有名字(只是'<lambda>'
  • 没有文档字符串
  • 没有注释
  • 没有复杂的陈述

它们也是相同类型的对象。由于这些原因,我通常更喜欢使用def关键字而不是lambdas 创建函数。

要点-它们是同一类型的对象

Lambda产生与常规函数相同类型的对象

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

由于lambda是函数,因此它们是一流的对象。

Lambda和功能:

  • 可以作为参数传递(与常规函数相同)
  • 在外部函数中创建时,将成为该外部函数的局部变量的闭包

但是,默认情况下,lambda缺少某些功能,这些功能是通过完整的函数定义语法获得的。

兰巴舞__name__'<lambda>'

毕竟,Lambda是匿名函数,因此它们不知道自己的名字。

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

因此无法在其命名空间中以编程方式查找lambda。

这限制了某些事情。例如,foo可以使用序列化代码查找,而l不能:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

我们可以foo很好地查找-因为它知道自己的名字:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambda没有注释,也没有文档字符串

基本上没有记录lambda。让我们重写foo一下以便更好地记录下来:

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

现在,foo具有文档:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

鉴于我们没有相同的机制为lambda提供相同的信息:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

但是我们可以将它们黑客化:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

但是,可能会有一些错误弄乱了帮助的输出。

Lambda只能返回一个表达式

Lambda不能返回复杂的语句,只能返回表达式。

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

当然,表达式可能会相当复杂,如果您非常努力,则可以使用lambda完成相同的操作,但是增加的复杂性更不利于编写清晰的代码。

我们使用Python来提高清晰度和可维护性。过度使用lambda可以解决这个问题。

Lambda 的唯一优势:可以在单个表达式中创建

这是唯一可能的上行空间。由于可以使用表达式创建lambda,因此可以在函数调用内部创建它。

与在其他位置创建的名称相比,在函数调用内部创建一个函数可以避免(廉价的)名称查找。

但是,由于严格评估了Python,因此除了避免名称查找外,这样做没有其他性能上的提高。

对于一个非常简单的表达式,我可以选择一个lambda。

在做交互式Python时,我也倾向于使用lambdas,以避免在可能的情况下出现多行。当我想在调用时将参数传递给构造函数时,我使用以下代码格式timeit.repeat

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

现在:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

我相信微小的时间差以上可以归结为在名称查找return_nullary_function-注意,这是微不足道的。

结论

Lambda非常适合非正式情况,在这种情况下,您希望减少代码行以支持单数点。

Lambda对于更正式的情况是不利的,在这种情况下,您需要为以后将要出现的代码编辑者提供清晰的信息,特别是在它们不平凡的情况下。

我们知道应该给我们的对象起好名字。当对象没有物体时我们该怎么做名称,?

由于所有这些原因,我通常更喜欢使用def代替with 来创建函数lambda

More preferable: lambda functions or nested functions (def)?

There is one advantage to using a lambda over a regular function: they are created in an expression.

There are several drawbacks:

  • no name (just '<lambda>')
  • no docstrings
  • no annotations
  • no complex statements

They are also both the same type of object. For those reasons, I generally prefer to create functions with the def keyword instead of with lambdas.

First point – they’re the same type of object

A lambda results in the same type of object as a regular function

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

Since lambdas are functions, they’re first-class objects.

Both lambdas and functions:

  • can be passed around as an argument (same as a regular function)
  • when created within an outer function become a closure over that outer functions’ locals

But lambdas are, by default, missing some things that functions get via full function definition syntax.

A lamba’s __name__ is '<lambda>'

Lambdas are anonymous functions, after all, so they don’t know their own name.

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

Thus lambda’s can’t be looked up programmatically in their namespace.

This limits certain things. For example, foo can be looked up with serialized code, while l cannot:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

We can lookup foo just fine – because it knows its own name:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambdas have no annotations and no docstring

Basically, lambdas are not documented. Let’s rewrite foo to be better documented:

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

Now, foo has documentation:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

Whereas, we don’t have the same mechanism to give the same information to lambdas:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

But we can hack them on:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

But there’s probably some error messing up the output of help, though.

Lambdas can only return an expression

Lambdas can’t return complex statements, only expressions.

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

Expressions can admittedly be rather complex, and if you try very hard you can probably accomplish the same with a lambda, but the added complexity is more of a detriment to writing clear code.

We use Python for clarity and maintainability. Overuse of lambdas can work against that.

The only upside for lambdas: can be created in a single expression

This is the only possible upside. Since you can create a lambda with an expression, you can create it inside of a function call.

Creating a function inside a function call avoids the (inexpensive) name lookup versus one created elsewhere.

However, since Python is strictly evaluated, there is no other performance gain to doing so aside from avoiding the name lookup.

For a very simple expression, I might choose a lambda.

I also tend to use lambdas when doing interactive Python, to avoid multiple lines when one will do. I use the following sort of code format when I want to pass in an argument to a constructor when calling timeit.repeat:

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

And now:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

I believe the slight time difference above can be attributed to the name lookup in return_nullary_function – note that it is very negligible.

Conclusion

Lambdas are good for informal situations where you want to minimize lines of code in favor of making a singular point.

Lambdas are bad for more formal situations where you need clarity for editors of code who will come later, especially in cases where they are non-trivial.

We know we are supposed to give our objects good names. How can we do so when the object has no name?

For all of these reasons, I generally prefer to create functions with def instead of with lambda.


回答 6

我同意nosklo的建议:如果需要给函数命名,请使用deflambda当我只是将简短的代码片段传递给另一个函数时,我会保留函数,例如:

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

I agree with nosklo’s advice: if you need to give the function a name, use def. I reserve lambda functions for cases where I’m just passing a brief snippet of code to another function, e.g.:

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

回答 7

在同意其他答案的同时,有时它更具可读性。这是一个lambda方便使用的示例,在用例中,我经常遇到N维defaultdict
这是一个例子:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

我发现它比def为第二维创建更具可读性。对于更大的尺寸,这一点更为重要。

While agreeing with the other answers, sometimes it’s more readable. Here’s an example where lambda comes in handy, in a use case I keep encountering of an N dimensional defaultdict.
Here’s an example:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

I find it more readable than creating a def for the second dimension. This is even more significant for higher dimensions.


回答 8

lambda的主要用途一直是用于简单的回调函数,以及用于map,reduce,filter,后者需要将函数用作参数。随着列表理解成为规范,并且允许添加,如:

x = [f for f in range(1, 40) if f % 2]

很难想象在日常使用中使用lambda的真实情况。因此,我要避免使用lambda并创建嵌套函数。

The primary use of lambda has always been for simple callback functions, and for map, reduce, filter, which require a function as an argument. With list comprehensions becoming the norm, and the added allowed if as in:

x = [f for f in range(1, 40) if f % 2]

it’s hard to imagine a real case for the use of lambda in daily use. As a result, I’d say, avoid lambda and create nested functions.


回答 9

Lambda的一个重要限制是它们除了表达式外不能包含其他任何内容。一个lambda表达式几乎不可能产生除琐碎的副作用之外的其他任何东西,因为它的身体不能像人体一样富裕。def “ ed函数”。

话虽这么说,Lua影响了我的编程风格,使之广泛地使用了匿名函数,并且我在其中充斥了代码。最重要的是,我倾向于以不考虑列表推导或生成器的方式将map / reduce视为抽象运算符,就像我要通过使用这些运算符明确推迟实现决策一样。

编辑:这是一个很老的问题,我对此事的看法有所改变。

首先,我强烈反对将lambda表达式分配给变量。因为python具有专门的语法(提示,def)。除此之外,lambda的许多用途(即使没有名称)也具有预定义的(且效率更高)的实现。例如,所讨论的示例可以缩写为just (1).__add__,而无需将其包装在a lambda或中def。许多其他常见的用途可以使用的某种组合来满足operatoritertoolsfunctools模块。

An important limitation of lambdas is that they cannot contain anything besides an expression. It’s nearly impossible for a lambda expression to produce anything besides trivial side effects, since it cannot have anywhere near as rich a body as a def‘ed function.

That being said, Lua influenced my programming style toward the extensive use of anonymous functions, and I litter my code with them. On top of that, I tend to think about map/reduce as abstract operators in ways I don’t consider list comprehensions or generators, almost as If I’m deferring an implementation decision explicitly by using those operators.

Edit: This is a pretty old question, and my opinions on the matter have changed, somewhat.

First off, I am strongly biased against assigning a lambda expression to a variable; as python has a special syntax just for that (hint, def). In addition to that, many of the uses for lambda, even when they don’t get a name, have predefined (and more efficient) implementations. For instance, the example in question can be abbreviated to just (1).__add__, without the need to wrap it in a lambda or def. Many other common uses can be satisfied with some combination of the operator, itertools and functools modules.


回答 10

  • 计算时间。
  • 没有名称的功能。
  • 实现一个功能和多个使用功能。

考虑一个简单的例子,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements
  • Computation time.
  • Function without name.
  • To achieve One function and many use functionality.

Considering a simple example,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements

回答 11

如果仅要将lambda分配给本地范围内的变量,则最好使用def,因为它更具可读性,并且将来可以更轻松地扩展:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

要么

def fun(a, b): return a ** b # more readable
map(fun, someList)

If you are just going to assign the lambda to a variable in the local scope, you may as well use def because it is more readable and can be expanded more easily in the future:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

or

def fun(a, b): return a ** b # more readable
map(fun, someList)

回答 12

我发现的lambda的一种用途是在调试消息中。

由于可以懒惰地评估lambda,因此您可以使用以下代码:

log.debug(lambda: "this is my message: %r" % (some_data,))

而不是可能很昂贵:

log.debug("this is my message: %r" % (some_data,))

即使调试调用由于当前的日志记录级别而没有产生输出,该命令也将处理格式字符串。

当然,要使它按所描述的那样工作,正在使用的日志记录模块必须支持lambda作为“惰性参数”(就像我的日志记录模块一样)。

相同的想法可以应用于按需内容值创建的任何其他惰性评估情况。

例如,此自定义三元运算符:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

代替:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

如果使用lambda,则只会评估由条件选择的表达式,而不会评估lambda。

当然,您可以简单地使用函数而不是lambda,但是对于短表达式而言,lambda更精简。

One use for lambdas I have found… is in debug messages.

Since lambdas can be lazily evaluated you can have code like this:

log.debug(lambda: "this is my message: %r" % (some_data,))

instead of possibly expensive:

log.debug("this is my message: %r" % (some_data,))

which processes the format string even if the debug call does not produce output because of current logging level.

Of course for it to work as described the logging module in use must support lambdas as “lazy parameters” (as my logging module does).

The same idea may be applied to any other case of lazy evaluation for on demand content value creation.

For example this custom ternary operator:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

instead of:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

with lambdas only the expression selected by the condition will be evaluated, without lambdas both will be evaluated.

Of course you could simply use functions instead of lambdas, but for short expressions lambdas are (c)leaner.


回答 13

我同意nosklo。顺便说一句即使使用一次也扔掉功能,大多数情况下,您只想使用操作员模块中的某些功能。

EG:

您有一个带有此签名的函数:myFunction(data,callback function)。

您想传递一个添加2个元素的函数。

使用lambda:

myFunction(data, (lambda x, y : x + y))

pythonic方式:

import operator
myFunction(data, operator.add)

或当然,这是一个简单的示例,但是操作员模块提供了很多东西,包括用于列表和字典的项目设置器/获取器。真的很酷。

I agree with nosklo. By the way, even with a use once, throw away function, most of the time you just want to use something from the operator module.

E.G :

You have a function with this signature : myFunction(data, callback function).

You want to pass a function that add 2 elements.

Using lambda :

myFunction(data, (lambda x, y : x + y))

The pythonic way :

import operator
myFunction(data, operator.add)

Or course this is a simple example, but there is a lot of stuff the operator module provides, including the items setters / getters for list and dict. Really cool.


回答 14

一个主要的区别是您不能def内联使用函数,我认为这是函数最方便的用例lambda。例如,在对对象列表进行排序时:

my_list.sort(key=lambda o: o.x)

因此,我建议继续使用lambda进行此类琐碎的操作,这些操作也并不能真正受益于功能命名所提供的自动文档。

A major difference is that you can not use def functions inline, which is in my opinion the most convenient use case for a lambda function. For example when sorting a list of objects:

my_list.sort(key=lambda o: o.x)

I would therefore suggest keeping the use of lambdas to this kind of trivial operations, which also do not really benefit from the automatic documentation provided by naming the function.


回答 15

lambda对于生成新函数很有用:

>>> def somefunc(x): return lambda y: x+y
>>> f = somefunc(10)
>>> f(2)
12
>>> f(4)
14

lambda is useful for generating new functions:

>>> def somefunc(x): return lambda y: x+y
>>> f = somefunc(10)
>>> f(2)
12
>>> f(4)
14

python中是否有将单词拆分为列表的函数?[重复]

问题:python中是否有将单词拆分为列表的函数?[重复]

python中是否有将单词分解为单个字母列表的函数?例如:

s="Word to Split"

要得到

wordlist=['W','o','r','d','','t','o' ....]

Is there a function in python to split a word into a list of single letters? e.g:

s="Word to Split"

to get

wordlist=['W','o','r','d','','t','o' ....]

回答 0

>>> list("Word to Split")
['W', 'o', 'r', 'd', ' ', 't', 'o', ' ', 'S', 'p', 'l', 'i', 't']
>>> list("Word to Split")
['W', 'o', 'r', 'd', ' ', 't', 'o', ' ', 'S', 'p', 'l', 'i', 't']

回答 1

最简单的方法可能只是使用list(),但也至少还有一个其他选择:

s = "Word to Split"
wordlist = list(s)               # option 1, 
wordlist = [ch for ch in s]      # option 2, list comprehension.

他们应该为您提供您所需要的:

['W','o','r','d',' ','t','o',' ','S','p','l','i','t']

如前所述,第一个可能是最适合您的示例的示例,但是有些用例可能会使后者在处理更复杂的内容时非常方便,例如,如果您想对项目应用某些任意函数,例如:

[doSomethingWith(ch) for ch in s]

The easiest way is probably just to use list(), but there is at least one other option as well:

s = "Word to Split"
wordlist = list(s)               # option 1, 
wordlist = [ch for ch in s]      # option 2, list comprehension.

They should both give you what you need:

['W','o','r','d',' ','t','o',' ','S','p','l','i','t']

As stated, the first is likely the most preferable for your example but there are use cases that may make the latter quite handy for more complex stuff, such as if you want to apply some arbitrary function to the items, such as with:

[doSomethingWith(ch) for ch in s]

回答 2

列表功能将执行此操作

>>> list('foo')
['f', 'o', 'o']

The list function will do this

>>> list('foo')
['f', 'o', 'o']

回答 3

滥用规则,结果相同:(x表示“要拆分的单词”中的x)

实际上是一个迭代器,而不是列表。但是,您可能不太在意。

Abuse of the rules, same result: (x for x in ‘Word to split’)

Actually an iterator, not a list. But it’s likely you won’t really care.


回答 4

text = "just trying out"

word_list = []

for i in range(0, len(text)):
    word_list.append(text[i])
    i+=1

print(word_list)

['j', 'u', 's', 't', ' ', 't', 'r', 'y', 'i', 'n', 'g', ' ', 'o', 'u', 't']
text = "just trying out"

word_list = []

for i in range(0, len(text)):
    word_list.append(text[i])
    i+=1

print(word_list)

['j', 'u', 's', 't', ' ', 't', 'r', 'y', 'i', 'n', 'g', ' ', 'o', 'u', 't']

回答 5

def count():列表=’oixfjhibokxnjfklmhjpxesriktglanwekgfvnk’

word_list = []
# dict = {}
for i in range(len(list)):
    word_list.append(list[i])
# word_list1 = sorted(word_list)
for i in range(len(word_list) - 1, 0, -1):
    for j in range(i):
        if word_list[j] > word_list[j + 1]:
            temp = word_list[j]
            word_list[j] = word_list[j + 1]
            word_list[j + 1] = temp
print("final count of arrival of each letter is : \n", dict(map(lambda x: (x, word_list.count(x)), word_list)))

def count(): list = ‘oixfjhibokxnjfklmhjpxesriktglanwekgfvnk’

word_list = []
# dict = {}
for i in range(len(list)):
    word_list.append(list[i])
# word_list1 = sorted(word_list)
for i in range(len(word_list) - 1, 0, -1):
    for j in range(i):
        if word_list[j] > word_list[j + 1]:
            temp = word_list[j]
            word_list[j] = word_list[j + 1]
            word_list[j + 1] = temp
print("final count of arrival of each letter is : \n", dict(map(lambda x: (x, word_list.count(x)), word_list)))

回答 6

最简单的选择是仅使用spit()命令。但是,如果您不想使用它或由于某种市集原因而无法使用它,则可以始终使用此方法。

word = 'foo'
splitWord = []

for letter in word:
    splitWord.append(letter)

print(splitWord) #prints ['f', 'o', 'o']

The easiest option is to just use the spit() command. However, if you don’t want to use it or it dose not work for some bazaar reason, you can always use this method.

word = 'foo'
splitWord = []

for letter in word:
    splitWord.append(letter)

print(splitWord) #prints ['f', 'o', 'o']