1

我正在用python编写一组脚本,我来到了这个:

line = "a b c d e f g"
a, b, c, d, e, f, g = line.split()

我很清楚这些是在实施过程中做出的决定,但python不应该(或确实)提供类似的东西:

_, _, var_needed, _, _, another_var_needed, _ = line.split()

以及 Prolog 确实提供,以排除著名的singleton variables.

我不确定,但它不会避免不必要的分配吗?或者创建对split调用结果的引用不计入开销?

编辑:

抱歉,我的意思是:在 Prolog 中,就我而言,表达如下:

test(L, N) :-
    test(L, 0, N).
test([], N, N).
test([_|T], M, N) :-
    V is M + 1,
    test(T, V, N).

表示的变量_是不可访问的,因为我认为对列表中确实存在的值的引用[_|T]甚至没有创建。

但是,在 Python 中,如果我使用_,我可以使用分配给 的最后一个值_,而且,我确实假设每个变量都发生了分配_——这可能被认为是一种开销。

我的问题是是否不应该(或是否有)一种语法来避免这种不必要的归属。

4

3 回答 3

7

_是一个完全有效的变量名,是的,您可以在解包操作中多次使用变量,因此您编写的内容将起作用。_将以该行中分配的最后一个值结束。一些 Python 程序员确实以这种方式使用它。

_被一些 Python 交互式 shell 用于特殊用途,这可能会使一些读者感到困惑,因此一些程序员不会出于这个原因使用它。

没有办法避免分配str.split():它总是分割整行,并且总是分配结果字符串。只是,在这种情况下,他们中的一些人活得不长。但话又说回来,谁呢?

您可以避免一些分配,例如re.finditer()

import re

fi = re.finditer(r"\S+", line)
next(fi)
next(fi)
var_needed = next(fi).group()
next(fi)
next(fi)
another_var_needed = next(fi).group()
# we don't care about the last match so we don't ask for it

但是next()返回一个Match对象,因此它将被分配(并立即丢弃,因为我们没有将它保存在任何地方)。所以你真的只保存最后的分配。如果你的字符串很长,我猜你得到一个Match对象而不是字符串这一事实可以节省一些内存甚至时间;我认为匹配的字符串在您要求之前不会从源字符串中切出。你可以确定它。

您甚至可以将上述内容概括为一个仅从字符串返回所需标记的函数:

import re

def get_tokens(text, *toknums):
    toknums = set(toknums)
    maxtok = max(toknums)
    for i, m in enumerate(re.finditer(r"\S", text)):
        if i in toknums:
            yield m.group()
        elif i > maxtok:
            break

var1, var2 = get_tokens("a b c d e f g", 2, 5)

但它仍然不是很漂亮。

于 2012-12-19T22:11:26.677 回答
3

事实上,_在 Python 中是一个有效的标识符,人们经常用它来接受一个不再需要的值,所以你的代码已经是很棒的 Python。

_Python 中没有与Prolog 中的语法完全对应的语法。当你_在 Python 中使用时,它是一个真正持有对值的引用的真实变量。

也就是说,在运行 Python 程序时,有很多很多的对象被分配和释放。即使您可以控制一些地方,就像您展示的那样,这只是杯水车薪,并且不会影响程序的资源使用量。

于 2012-12-19T22:11:52.067 回答
2

就语法而言

_, _, var_needed, _, _, another_var_needed, _ = line.split()

是有效的蟒蛇。我会说它甚至是惯用的,虽然有点不寻常。

于 2012-12-19T22:10:58.123 回答