Python 如果只有函数 B 需要函数 A,是否应该在 B 中定义 A?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4831680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 17:43:50  来源:igfitidea点击:

If function A is required only by function B should A be defined inside B?

pythoncoding-style

提问by nukl

Simple example. Two methods, one called from another:

简单的例子。两种方法,一种从另一种调用:

def method_a(arg):
    some_data = method_b(arg)

def method_b(arg):
    return some_data

In Python we can declare definside another def. So, if method_bis required for and called only from method_a, should I declare method_binside method_a? like this :

在 Python 中,我们可以def在另一个def. 所以,如果method_b只需要 from 调用method_a,我应该method_b在 inside声明method_a吗?像这样 :

def method_a(arg):

    def method_b(arg):
        return some_data

    some_data = method_b(arg)

Or should I avoid doing this?

或者我应该避免这样做?

回答by user225312

>>> def sum(x, y):
...     def do_it():
...             return x + y
...     return do_it
... 
>>> a = sum(1, 3)
>>> a
<function do_it at 0xb772b304>
>>> a()
4

Is this what you were looking for? It's called a closure.

这就是你要找的吗?这叫做闭包

回答by vz0

It's actually fine to declare one function inside another one. This is specially useful creating decorators.

在另一个函数中声明一个函数实际上很好。这对于创建装饰器特别有用。

However, as a rule of thumb, if the function is complex (more than 10 lines) it might be a better idea to declare it on the module level.

但是,根据经验,如果函数很复杂(超过 10 行),最好在模块级别声明它。

回答by martineau

You don't really gain much by doing this, in fact it slows method_adown because it'll define and recompile the other function every time it's called. Given that, it would probably be better to just prefix the function name with underscore to indicate it's a private method -- i.e. _method_b.

这样做并没有真正获得多少收益,实际上它会变慢method_a,因为每次调用它时它都会定义和重新编译另一个函数。鉴于此,最好在函数名称前加上下划线以表明它是一个私有方法——即_method_b.

I suppose you mightwant to do this if the nested function's definition varied each time for some reason, but that may indicate a flaw in your design. That said, there isa valid reason to do this to allow the nested function to use arguments that were passed to the outer function but not explicitly passed on to them, which sometimes occurs when writing function decorators, for example. It's what is being shown in the accepted answer although a decorator is not being defined or used.

如果嵌套函数的定义由于某种原因每次都不同,我想您可能想要这样做,但这可能表明您的设计存在缺陷。也就是说,这样做有正当理由的,允许嵌套函数使用传递给外部函数但未显式传递给它们的参数,例如,在编写函数装饰器时有时会发生这种情况。尽管没有定义或使用装饰器,但这就是已接受的答案中显示的内容。

Update:

更新:

Here's proof that nesting them is slower (using Python 3.6.1), although admittedly not by much in this trivial case:

以下是嵌套它们较慢的证据(使用 Python 3.6.1),尽管在这个微不足道的情况下肯定不是很多:

setup = """
class Test(object):
    def separate(self, arg):
        some_data = self._method_b(arg)

    def _method_b(self, arg):
        return arg+1

    def nested(self, arg):

        def method_b2(self, arg):
            return arg+1

        some_data = method_b2(self, arg)

obj = Test()
"""
from timeit import Timer
print(min(Timer(stmt='obj.separate(42)', setup=setup).repeat()))  # -> 0.24479823284461724
print(min(Timer(stmt='obj.nested(42)', setup=setup).repeat()))    # -> 0.26553459700452575

Note I added some selfarguments to your sample functions to make them more like real methods (although method_b2still isn't technically a method of the Testclass). Also the nested function is actually called in that version, unlike yours.

注意我self向您的示例函数添加了一些参数,使它们更像真正的方法(尽管从method_b2技术上讲仍然不是Test类的方法)。此外,嵌套函数实际上是在该版本中调用的,与您的不同。

回答by mikelikespie

It's perfectly OK doing it that way, but unless you need to use a closure or return the function I'd probably put in the module level. I imagine in the second code example you mean:

这样做完全可以,但是除非您需要使用闭包或返回我可能会放在模块级别的函数。我想在第二个代码示例中你的意思是:

...
some_data = method_b() # not some_data = method_b

otherwise, some_data will be the function.

否则, some_data 将是函数。

Having it at the module level will allow other functions to use method_b() and if you're using something like Sphinx(and autodoc) for documentation, it will allow you to document method_b as well.

将它放在模块级别将允许其他函数使用 method_b() 并且如果您使用Sphinx(和 autodoc)之类的东西作为文档,它也将允许您记录 method_b。

You also may want to consider just putting the functionality in two methods in a class if you're doing something that can be representable by an object. This contains logic well too if that's all you're looking for.

如果您正在做一些可以由对象表示的事情,您可能还想考虑将功能放在一个类中的两个方法中。如果这就是您要寻找的全部内容,那么这也很好地包含了逻辑。

回答by chao787

It's just a principle about exposure APIs.

这只是一个关于暴露 API 的原则。

Using python, It's a good idea to avoid exposure API in outer space(module or class), function is a good encapsulation place.

使用python,避免将API暴露在外层空间(模块或类)是个好主意,函数是一个很好的封装场所。

It could be a good idea. when you ensure

这可能是个好主意。当你确保

  1. inner function is ONLYused by outer function.
  2. insider function has a goodname to explain its purpose because the code talks.
  3. code cannot directly understand by your colleagues(or other code-reader).
  1. 内部函数仅供外部函数使用。
  2. 内部函数有一个很好的名字来解释它的目的,因为代码会说话。
  3. 您的同事(或其他代码阅读器)无法直接理解代码。

Even though, Abuse this technique may cause problems and implies a design flaw.

尽管如此,滥用此技术可能会导致问题并暗示设计缺陷。

Just from my exp, Maybe misunderstand your question.

仅从我的经验来看,也许误解了您的问题。

回答by mdlp0716

Do something like:

做类似的事情:

def some_function():
    return some_other_function()
def some_other_function():
    return 42 

if you were to run some_function()it would then run some_other_function()and returns 42.

如果您要运行some_function()它,它将运行some_other_function()并返回 42。

EDIT: I originally stated that you shouldn't define a function inside of another but it was pointed out that it is practical to do this sometimes.

编辑:我最初说过你不应该在另一个内部定义一个函数,但有人指出有时这样做是可行的。

回答by CivFan

A function inside of a function is commonly used for closures.

函数内部的函数通常用于闭包

(There is a lot of contentionover what exactlymakes a closure a closure.)

(有一个很大的竞争究竟是什么使一个封闭的封闭。)

Here's an example using the built-in sum(). It defines startonce and uses it from then on:

这是一个使用内置sum(). 它定义start一次并从那时起使用它:

def sum_partial(start):
    def sum_start(iterable):
        return sum(iterable, start)
    return sum_start

In use:

正在使用:

>>> sum_with_1 = sum_partial(1)
>>> sum_with_3 = sum_partial(3)
>>> 
>>> sum_with_1
<function sum_start at 0x7f3726e70b90>
>>> sum_with_3
<function sum_start at 0x7f3726e70c08>
>>> sum_with_1((1,2,3))
7
>>> sum_with_3((1,2,3))
9

Built-in python closure

内置python闭包

functools.partialis an example of a closure.

functools.partial是一个闭包的例子。

From the python docs, it's roughly equivalent to:

从 python docs,它大致相当于:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

(Kudos to @user225312 below for the answer. I find this example easier to figure out, and hopefully will help answer @mango's comment.)

(感谢@user225312 下面的答案。我发现这个例子更容易理解,希望能帮助回答@mango 的评论。)

回答by miracle173

I found this question because I wanted to pose a question why there is a performance impact if one uses nested functions. I ran tests for the following functions using Python 3.2.5 on a Windows Notebook with a Quad Core 2.5 GHz Intel i5-2530M processor

我发现这个问题是因为我想提出一个问题,为什么使用嵌套函数会影响性能。我在带有四核 2.5 GHz Intel i5-2530M 处理器的 Windows 笔记本上使用 Python 3.2.5 对以下函数进行了测试

def square0(x):
    return x*x

def square1(x):
    def dummy(y):
        return y*y
    return x*x

def square2(x):
    def dummy1(y):
        return y*y
    def dummy2(y):
        return y*y
    return x*x

def square5(x):
    def dummy1(y):
        return y*y
    def dummy2(y):
        return y*y
    def dummy3(y):
        return y*y
    def dummy4(y):
        return y*y
    def dummy5(y):
        return y*y
    return x*x

I measured the following 20 times, also for square1, square2, and square5:

我测量了以下 20 次,也测量了 square1、square2 和 square5:

s=0
for i in range(10**6):
    s+=square0(i)

and got the following results

并得到以下结果

>>> 
m = mean, s = standard deviation, m0 = mean of first testcase
[m-3s,m+3s] is a 0.997 confidence interval if normal distributed

square? m     s       m/m0  [m-3s ,m+3s ]
square0 0.387 0.01515 1.000 [0.342,0.433]
square1 0.460 0.01422 1.188 [0.417,0.503]
square2 0.552 0.01803 1.425 [0.498,0.606]
square5 0.766 0.01654 1.979 [0.717,0.816]
>>> 

square0has no nested function, square1has one nested function, square2has two nested functions and square5has five nested functions. The nested functions are only declared but not called.

square0没有嵌套函数,square1有一个嵌套函数,square2有两个嵌套函数和square5五个嵌套函数。嵌套函数只被声明而不被调用。

So if you have defined 5 nested funtions in a function that you don't call then the execution time of the function is twice of the function without a nested function. I think should be cautious when using nested functions.

因此,如果您在不调用的函数中定义了 5 个嵌套函数,则该函数的执行时间是没有嵌套函数的函数的两倍。我认为在使用嵌套函数时应该谨慎。

The Python file for the whole test that generates this output can be found at ideone.

生成此输出的整个测试的 Python 文件可以在ideone 中找到。

回答by miracle173

So in the end it is largely a question about how smart the python implementation is or is not, particularly in the case of the inner function not being a closure but simply an in function needed helper only.

所以最终这主要是一个关于 python 实现有多智能的问题,特别是在内部函数不是闭包而只是一个函数中需要的助手的情况下。

In clean understandable design having functions only where they are needed and not exposed elsewhere is good design whether they be embedded in a module, a class as a method, or inside another function or method. When done well they really improve the clarity of the code.

在干净易懂的设计中,函数只在需要的地方使用而不在其他地方暴露是好的设计,无论它们是嵌入到模块中,作为方法的类,还是在另一个函数或方法中。如果做得好,它们确实会提高代码的清晰度。

And when the inner function is a closure that can also help with clarity quite a bit even if that function is not returned out of the containing function for use elsewhere.

当内部函数是一个闭包时,即使该函数没有从包含函数中返回以在其他地方使用,它也可以帮助清晰一些。

So I would say generally do use them but be aware of the possible performance hit when you actually are concerned about performance and only remove them if you do actual profiling that shows they best be removed.

所以我会说通常会使用它们,但是当您真正关心性能时要注意可能的性能损失,并且只有在您进行实际分析表明它们最好被删除时才删除它们。

Do not do premature optimization of just using "inner functions BAD" throughout all python code you write. Please.

不要在您编写的所有 Python 代码中仅使用“内部函数 BAD”进行过早优化。请。

回答by CivFan

Generally, no, do not define functions inside functions.

一般来说,不,不要在函数内部定义函数。

Unless you have a really good reason. Which you don't.

除非你有很好的理由。你没有。

Why not?

为什么不?

What isa really good reason to define functions inside functions?

在函数内部定义函数的真正好理由什么?

When what you actuallywant is a dingdang closure.

当您真正想要的是 dingdang闭包时