标签归档:idioms

一对单对

问题:一对单对

通常,我发现需要成对处理列表。我想知道哪种方法是有效的pythonic方法,并在Google上找到了它:

pairs = zip(t[::2], t[1::2])

我认为这已经足够好用了,但是在最近涉及成语与效率的讨论之后,我决定进行一些测试:

import time
from itertools import islice, izip

def pairs_1(t):
    return zip(t[::2], t[1::2]) 

def pairs_2(t):
    return izip(t[::2], t[1::2]) 

def pairs_3(t):
    return izip(islice(t,None,None,2), islice(t,1,None,2))

A = range(10000)
B = xrange(len(A))

def pairs_4(t):
    # ignore value of t!
    t = B
    return izip(islice(t,None,None,2), islice(t,1,None,2))

for f in pairs_1, pairs_2, pairs_3, pairs_4:
    # time the pairing
    s = time.time()
    for i in range(1000):
        p = f(A)
    t1 = time.time() - s

    # time using the pairs
    s = time.time()
    for i in range(1000):
        p = f(A)
        for a, b in p:
            pass
    t2 = time.time() - s
    print t1, t2, t2-t1

这些是我计算机上的结果:

1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578

如果我正确地解释了它们,那应该意味着在Python中实现列表,列表索引和列表切片非常有效。这是令人安慰和意外的结果。

是否有另一种“更好”的成对遍历列表的方式?

请注意,如果列表中元素的数量为奇数,则最后一个元素将不在任何对中。

确保包含所有元素的正确方法是哪种?

我从测试答案中添加了这两个建议:

def pairwise(t):
    it = iter(t)
    return izip(it, it)

def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

结果如下:

0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176

到目前为止的结果

最pythonic,非常高效:

pairs = izip(t[::2], t[1::2])

最有效且非常pythonic:

pairs = izip(*[iter(t)]*2)

我花了一点时间想知道第一个答案使用了两个迭代器,而第二个答案使用了一个迭代器。

为了处理具有奇数个元素的序列,建议增加原始序列,增加一个元素(None)与之前的最后一个元素配对,这可以通过实现itertools.izip_longest()

最后

请注意,在Python 3.x中,zip()其行为与itertools.izip()itertools.izip() 消失了。

Often enough, I’ve found the need to process a list by pairs. I was wondering which would be the pythonic and efficient way to do it, and found this on Google:

pairs = zip(t[::2], t[1::2])

I thought that was pythonic enough, but after a recent discussion involving idioms versus efficiency, I decided to do some tests:

import time
from itertools import islice, izip

def pairs_1(t):
    return zip(t[::2], t[1::2]) 

def pairs_2(t):
    return izip(t[::2], t[1::2]) 

def pairs_3(t):
    return izip(islice(t,None,None,2), islice(t,1,None,2))

A = range(10000)
B = xrange(len(A))

def pairs_4(t):
    # ignore value of t!
    t = B
    return izip(islice(t,None,None,2), islice(t,1,None,2))

for f in pairs_1, pairs_2, pairs_3, pairs_4:
    # time the pairing
    s = time.time()
    for i in range(1000):
        p = f(A)
    t1 = time.time() - s

    # time using the pairs
    s = time.time()
    for i in range(1000):
        p = f(A)
        for a, b in p:
            pass
    t2 = time.time() - s
    print t1, t2, t2-t1

These were the results on my computer:

1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578

If I’m interpreting them correctly, that should mean that the implementation of lists, list indexing, and list slicing in Python is very efficient. It’s a result both comforting and unexpected.

Is there another, “better” way of traversing a list in pairs?

Note that if the list has an odd number of elements then the last one will not be in any of the pairs.

Which would be the right way to ensure that all elements are included?

I added these two suggestions from the answers to the tests:

def pairwise(t):
    it = iter(t)
    return izip(it, it)

def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

These are the results:

0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176

Results so far

Most pythonic and very efficient:

pairs = izip(t[::2], t[1::2])

Most efficient and very pythonic:

pairs = izip(*[iter(t)]*2)

It took me a moment to grok that the first answer uses two iterators while the second uses a single one.

To deal with sequences with an odd number of elements, the suggestion has been to augment the original sequence adding one element (None) that gets paired with the previous last element, something that can be achieved with itertools.izip_longest().

Finally

Note that, in Python 3.x, zip() behaves as itertools.izip(), and itertools.izip() is gone.


回答 0

我最喜欢的方式:

from itertools import izip

def pairwise(t):
    it = iter(t)
    return izip(it,it)

# for "pairs" of any length
def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

当您要配对所有元素时,您显然可能需要一个fillvalue:

from itertools import izip_longest
def blockwise(t, size=2, fillvalue=None):
    it = iter(t)
    return izip_longest(*[it]*size, fillvalue=fillvalue)

My favorite way to do it:

from itertools import izip

def pairwise(t):
    it = iter(t)
    return izip(it,it)

# for "pairs" of any length
def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

When you want to pair all elements you obviously might need a fillvalue:

from itertools import izip_longest
def blockwise(t, size=2, fillvalue=None):
    it = iter(t)
    return izip_longest(*[it]*size, fillvalue=fillvalue)

回答 1

我想说您的初始解决方案pairs = zip(t[::2], t[1::2])是最好的解决方案,因为它最容易阅读(在Python 3中,它会zip自动返回一个迭代器而不是列表)。

为了确保包括所有元素,您可以通过扩展列表None

然后,如果列表中元素的数量为奇数,则最后一对将为(item, None)

>>> t = [1,2,3,4,5]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, None)]
>>> t = [1,2,3,4,5,6]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, 6)]

I’d say that your initial solution pairs = zip(t[::2], t[1::2]) is the best one because it is easiest to read (and in Python 3, zip automatically returns an iterator instead of a list).

To ensure that all elements are included, you could simply extend the list by None.

Then, if the list has an odd number of elements, the last pair will be (item, None).

>>> t = [1,2,3,4,5]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, None)]
>>> t = [1,2,3,4,5,6]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, 6)]

回答 2

我从小的免责声明开始-不要使用下面的代码。根本不是Pythonic,我只是为了好玩而写。它类似于@ THC4k pairwise函数,但使用iterlambda闭包。它不使用itertools模块,不支持fillvalue。我把它放在这里是因为有人可能会觉得有趣:

pairwise = lambda t: iter((lambda f: lambda: (f(), f()))(iter(t).next), None)

I start with small disclaimer – don’t use the code below. It’s not Pythonic at all, I wrote just for fun. It’s similar to @THC4k pairwise function but it uses iter and lambda closures. It doesn’t use itertools module and doesn’t support fillvalue. I put it here because someone might find it interesting:

pairwise = lambda t: iter((lambda f: lambda: (f(), f()))(iter(t).next), None)

回答 3

就大多数pythonic而言,我想说python源文档中提供食谱(其中一些看起来很像@JochenRitzel提供的答案)可能是您最好的选择;)

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

As far as most pythonic goes, I’d say the recipes supplied in the python source docs (some of which look a lot like the answers that @JochenRitzel provided) is probably your best bet ;)

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

On modern python you just have to use zip_longest(*args, fillvalue=fillvalue) according to the corresponding doc page.


回答 4

是否有另一种“更好”的成对遍历列表的方式?

我不能肯定地说,但我对此表示怀疑:任何其他遍历都会包含更多必须解释的Python代码。诸如zip()之类的内置函数是用C编写的,这要快得多。

确保包含所有元素的正确方法是哪种?

检查列表的长度,如果它是奇数(len(list) & 1 == 1),则复制列表并附加一个项目。

Is there another, “better” way of traversing a list in pairs?

I can’t say for sure but I doubt it: Any other traversal would include more Python code which has to be interpreted. The built-in functions like zip() are written in C which is much faster.

Which would be the right way to ensure that all elements are included?

Check the length of the list and if it’s odd (len(list) & 1 == 1), copy the list and append an item.


回答 5

>>> my_list = [1,2,3,4,5,6,7,8,9,10]
>>> my_pairs = list()
>>> while(my_list):
...     a = my_list.pop(0); b = my_list.pop(0)
...     my_pairs.append((a,b))
... 
>>> print(my_pairs)
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
>>> my_list = [1,2,3,4,5,6,7,8,9,10]
>>> my_pairs = list()
>>> while(my_list):
...     a = my_list.pop(0); b = my_list.pop(0)
...     my_pairs.append((a,b))
... 
>>> print(my_pairs)
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

回答 6

只做:

>>> l = [1, 2, 3, 4, 5, 6]
>>> [(x,y) for x,y in zip(l[:-1], l[1:])]
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

Only do it:

>>> l = [1, 2, 3, 4, 5, 6]
>>> [(x,y) for x,y in zip(l[:-1], l[1:])]
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

回答 7

这是使用生成器创建对/腿的示例。生成器不受堆栈限制

def pairwise(data):
    zip(data[::2], data[1::2])

例:

print(list(pairwise(range(10))))

输出:

[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

Here is an example of creating pairs/legs by using a generator. Generators are free from stack limits

def pairwise(data):
    zip(data[::2], data[1::2])

Example:

print(list(pairwise(range(10))))

Output:

[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

回答 8

万一有人需要明智的答案算法,这里是:

>>> def getPairs(list):
...     out = []
...     for i in range(len(list)-1):
...         a = list.pop(0)
...         for j in a:
...             out.append([a, j])
...     return b
>>> 
>>> k = [1, 2, 3, 4]
>>> l = getPairs(k)
>>> l
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

但是请注意,您原来的列表也将被简化为最后一个元素,因为您使用pop了它。

>>> k
[4]

Just in case someone needs the answer algorithm-wise, here it is:

>>> def getPairs(list):
...     out = []
...     for i in range(len(list)-1):
...         a = list.pop(0)
...         for j in a:
...             out.append([a, j])
...     return b
>>> 
>>> k = [1, 2, 3, 4]
>>> l = getPairs(k)
>>> l
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

But take note that your original list will also be reduced to its last element, because you used pop on it.

>>> k
[4]

Python:将None转换为空字符串的最惯用方式?

问题:Python:将None转换为空字符串的最惯用方式?

做以下事情的最惯用的方法是什么?

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

更新:我合并了Tryptich的建议使用str(s),这使此例程可用于字符串以外的其他类型。Vinay Sajip的lambda建议给我留下了深刻的印象,但是我想保持我的代码相对简单。

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)

What is the most idiomatic way to do the following?

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

update: I’m incorporating Tryptich’s suggestion to use str(s), which makes this routine work for other types besides strings. I’m awfully impressed by Vinay Sajip’s lambda suggestion, but I want to keep my code relatively simple.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)

回答 0

如果您实际上希望函数的行为类似于str()内置函数,但是当参数为None时返回空字符串,请执行以下操作:

def xstr(s):
    if s is None:
        return ''
    return str(s)

If you actually want your function to behave like the str() built-in, but return an empty string when the argument is None, do this:

def xstr(s):
    if s is None:
        return ''
    return str(s)

回答 1

def xstr(s):
    return '' if s is None else str(s)
def xstr(s):
    return '' if s is None else str(s)

回答 2

可能最短的是 str(s or '')

因为None为False,如果x为false,则“ x或y”返回y。有关详细说明,请参见布尔运算符。它很短,但不是很明确。

Probably the shortest would be str(s or '')

Because None is False, and “x or y” returns y if x is false. See Boolean Operators for a detailed explanation. It’s short, but not very explicit.


回答 3

如果您知道该值将始终是字符串或无:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''

If you know that the value will always either be a string or None:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''

回答 4

return s or '' 可以很好地解决您所说的问题!

return s or '' will work just fine for your stated problem!


回答 5

def xstr(s):
   return s or ""
def xstr(s):
   return s or ""

回答 6

功能方式(单线)

xstr = lambda s: '' if s is None else s

Functional way (one-liner)

xstr = lambda s: '' if s is None else s

回答 7

一个巧妙的单线代码可以在其他一些答案上进行构建:

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

甚至只是:

s = (a or '') + (b or '')

A neat one-liner to do this building on some of the other answers:

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

or even just:

s = (a or '') + (b or '')

回答 8

def xstr(s):
    return {None:''}.get(s, s)
def xstr(s):
    return {None:''}.get(s, s)

回答 9

我使用max函数:

max(None, '')  #Returns blank
max("Hello",'') #Returns Hello

就像一个吊饰;)只需将字符串放在函数的第一个参数中即可。

I use max function:

max(None, '')  #Returns blank
max("Hello",'') #Returns Hello

Works like a charm ;) Just put your string in the first parameter of the function.


回答 10

如果您需要与Python 2.4兼容,请在上面进行修改

xstr = lambda s: s is not None and s or ''

Variation on the above if you need to be compatible with Python 2.4

xstr = lambda s: s is not None and s or ''

回答 11

如果要格式化字符串,则可以执行以下操作:

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)

If it is about formatting strings, you can do the following:

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)

回答 12

def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))

回答 13

在下面说明的场景中,我们总是可以避免类型转换。

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

在上面的示例中,如果变量customer的值为None,则在分配给’name’的同时进一步进行强制转换。“ if”子句中的比较将始终失败。

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

上面的示例将正常工作。当从URL,JSON或XML中获取值,甚至值需要进一步的类型转换以进行任何操作时,这种情况非常普遍。

We can always avoid type casting in scenarios explained below.

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

In the example above in case variable customer’s value is None the it further gets casting while getting assigned to ‘name’. The comparison in ‘if’ clause will always fail.

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

Above example will work properly. Such scenarios are very common when values are being fetched from URL, JSON or XML or even values need further type casting for any manipulation.


回答 14

使用短路评估:

s = a or '' + b or ''

由于+对字符串不是很好的操作,因此最好使用格式字符串:

s = "%s%s" % (a or '', b or '')

Use short circuit evaluation:

s = a or '' + b or ''

Since + is not a very good operation on strings, better use format strings:

s = "%s%s" % (a or '', b or '')

回答 15

如果使用的是python v3.7,请使用F字符串

xstr = F"{s}"

Use F string if you are using python v3.7

xstr = F"{s}"

在“ for”循环中检测最后一个元素的pythonic方法是什么?

问题:在“ for”循环中检测最后一个元素的pythonic方法是什么?

我想知道对for循环中的最后一个元素进行特殊处理的最佳方法(更紧凑和“ pythonic”的方法)。有一段代码仅应元素之间调用,而在最后一个元素中将被隐藏。

这是我目前的操作方式:

for i, data in enumerate(data_list):
    code_that_is_done_for_every_element
    if i != len(data_list) - 1:
        code_that_is_done_between_elements

有什么更好的办法吗?

注意:我不希望使用hack之类的东西reduce;)

I’d like to know the best way (more compact and “pythonic” way) to do a special treatment for the last element in a for loop. There is a piece of code that should be called only between elements, being suppressed in the last one.

Here is how I currently do it:

for i, data in enumerate(data_list):
    code_that_is_done_for_every_element
    if i != len(data_list) - 1:
        code_that_is_done_between_elements

Is there any better way?

Note: I don’t want to make it with hacks such as using reduce. ;)


回答 0

在大多数情况下,使第一个迭代成为特殊情况而不是最后一个案例更容易(且更便宜):

first = True
for data in data_list:
    if first:
        first = False
    else:
        between_items()

    item()

这将适用于任何可迭代的对象,即使对于那些没有len()

file = open('/path/to/file')
for line in file:
    process_line(line)

    # No way of telling if this is the last line!

除此之外,我认为没有通用的更好的解决方案,因为这取决于您要执行的操作。例如,如果要从列表中构建字符串,则使用自然str.join()要比使用for“特殊情况”循环更好。


使用相同的原理,但更紧凑:

for i, line in enumerate(data_list):
    if i > 0:
        between_items()
    item()

看起来很熟悉,不是吗?:)


对于@ofko以及其他确实需要确定iterable的当前值是否len()是最后一个值的人,您需要向前看:

def lookahead(iterable):
    """Pass through all values from the given iterable, augmented by the
    information if there are more values to come after the current one
    (True), or if it is the last value (False).
    """
    # Get an iterator and pull the first value.
    it = iter(iterable)
    last = next(it)
    # Run the iterator to exhaustion (starting from the second value).
    for val in it:
        # Report the *previous* value (more to come).
        yield last, True
        last = val
    # Report the last value.
    yield last, False

然后,您可以像这样使用它:

>>> for i, has_more in lookahead(range(3)):
...     print(i, has_more)
0 True
1 True
2 False

Most of the times it is easier (and cheaper) to make the first iteration the special case instead of the last one:

first = True
for data in data_list:
    if first:
        first = False
    else:
        between_items()

    item()

This will work for any iterable, even for those that have no len():

file = open('/path/to/file')
for line in file:
    process_line(line)

    # No way of telling if this is the last line!

Apart from that, I don’t think there is a generally superior solution as it depends on what you are trying to do. For example, if you are building a string from a list, it’s naturally better to use str.join() than using a for loop “with special case”.


Using the same principle but more compact:

for i, line in enumerate(data_list):
    if i > 0:
        between_items()
    item()

Looks familiar, doesn’t it? :)


For @ofko, and others who really need to find out if the current value of an iterable without len() is the last one, you will need to look ahead:

def lookahead(iterable):
    """Pass through all values from the given iterable, augmented by the
    information if there are more values to come after the current one
    (True), or if it is the last value (False).
    """
    # Get an iterator and pull the first value.
    it = iter(iterable)
    last = next(it)
    # Run the iterator to exhaustion (starting from the second value).
    for val in it:
        # Report the *previous* value (more to come).
        yield last, True
        last = val
    # Report the last value.
    yield last, False

Then you can use it like this:

>>> for i, has_more in lookahead(range(3)):
...     print(i, has_more)
0 True
1 True
2 False

回答 1

尽管这个问题已经很老了,但我还是通过Google来到这里的,我发现了一种非常简单的方法:列表切片。假设您要在所有列表条目之间添加“&”。

s = ""
l = [1, 2, 3]
for i in l[:-1]:
    s = s + str(i) + ' & '
s = s + str(l[-1])

这将返回“ 1&2&3”。

Although that question is pretty old, I came here via google and I found a quite simple way: List slicing. Let’s say you want to put an ‘&’ between all list entries.

s = ""
l = [1, 2, 3]
for i in l[:-1]:
    s = s + str(i) + ' & '
s = s + str(l[-1])

This returns ‘1 & 2 & 3’.


回答 2

“之间的代码”是头尾模式的一个示例。

您有一个项目,其后是一系列(在项目之间)对。您也可以将其视为(项目之间)对的序列,后跟一个项目。通常,将第一个元素作为特殊条件,而将所有其他元素作为“标准”条件,则更为简单。

此外,为避免重复代码,您必须提供一个函数或其他对象来包含您不想重复的代码。将if语句嵌入到一个循环中,该循环始终为假(一次除外),这有点愚蠢。

def item_processing( item ):
    # *the common processing*

head_tail_iter = iter( someSequence )
head = head_tail_iter.next()
item_processing( head )
for item in head_tail_iter:
    # *the between processing*
    item_processing( item )

这是更可靠的,因为它更容易证明,它不会创建额外的数据结构(即列表的副本),也不需要浪费很多执行if条件,而if条件总是一次,除非一次。

The ‘code between’ is an example of the Head-Tail pattern.

You have an item, which is followed by a sequence of ( between, item ) pairs. You can also view this as a sequence of (item, between) pairs followed by an item. It’s generally simpler to take the first element as special and all the others as the “standard” case.

Further, to avoid repeating code, you have to provide a function or other object to contain the code you don’t want to repeat. Embedding an if statement in a loop which is always false except one time is kind of silly.

def item_processing( item ):
    # *the common processing*

head_tail_iter = iter( someSequence )
head = next(head_tail_iter)
item_processing( head )
for item in head_tail_iter:
    # *the between processing*
    item_processing( item )

This is more reliable because it’s slightly easier to prove, It doesn’t create an extra data structure (i.e., a copy of a list) and doesn’t require a lot of wasted execution of an if condition which is always false except once.


回答 3

如果您只是想修改其中的最后一个元素,data_list则可以使用表示法:

L[-1]

但是,您似乎要做的还不止这些。您的方式并没有错。我什至快速浏览了一些Django代码的模板标签,它们基本上完成了您正在做的事情。

If you’re simply looking to modify the last element in data_list then you can simply use the notation:

L[-1]

However, it looks like you’re doing more than that. There is nothing really wrong with your way. I even took a quick glance at some Django code for their template tags and they do basically what you’re doing.


回答 4

如果项目是唯一的:

for x in list:
    #code
    if x == list[-1]:
        #code

其他选择:

pos = -1
for x in list:
    pos += 1
    #code
    if pos == len(list) - 1:
        #code


for x in list:
    #code
#code - e.g. print x


if len(list) > 0:
    for x in list[:-1]
        #code
    for x in list[-1]:
        #code

if the items are unique:

for x in list:
    #code
    if x == list[-1]:
        #code

other options:

pos = -1
for x in list:
    pos += 1
    #code
    if pos == len(list) - 1:
        #code


for x in list:
    #code
#code - e.g. print x


if len(list) > 0:
    for x in list[:-1]
        #code
    for x in list[-1]:
        #code

回答 5

这类似于Ants Aasma的方法,但不使用itertools模块。这也是一个滞后的迭代器,它在迭代器流中先看一个元素:

def last_iter(it):
    # Ensure it's an iterator and get the first field
    it = iter(it)
    prev = next(it)
    for item in it:
        # Lag by one item so I know I'm not at the end
        yield 0, prev
        prev = item
    # Last item
    yield 1, prev

def test(data):
    result = list(last_iter(data))
    if not result:
        return
    if len(result) > 1:
        assert set(x[0] for x in result[:-1]) == set([0]), result
    assert result[-1][0] == 1

test([])
test([1])
test([1, 2])
test(range(5))
test(xrange(4))

for is_last, item in last_iter("Hi!"):
    print is_last, item

This is similar to Ants Aasma’s approach but without using the itertools module. It’s also a lagging iterator which looks-ahead a single element in the iterator stream:

def last_iter(it):
    # Ensure it's an iterator and get the first field
    it = iter(it)
    prev = next(it)
    for item in it:
        # Lag by one item so I know I'm not at the end
        yield 0, prev
        prev = item
    # Last item
    yield 1, prev

def test(data):
    result = list(last_iter(data))
    if not result:
        return
    if len(result) > 1:
        assert set(x[0] for x in result[:-1]) == set([0]), result
    assert result[-1][0] == 1

test([])
test([1])
test([1, 2])
test(range(5))
test(xrange(4))

for is_last, item in last_iter("Hi!"):
    print is_last, item

回答 6

您可以在输入数据上使用滑动窗口来窥视下一个值,并使用哨兵来检测上一个值。这适用于任何可迭代的项目,因此您无需事先知道长度。成对实现来自itertools配方

from itertools import tee, izip, chain

def pairwise(seq):
    a,b = tee(seq)
    next(b, None)
    return izip(a,b)

def annotated_last(seq):
    """Returns an iterable of pairs of input item and a boolean that show if
    the current item is the last item in the sequence."""
    MISSING = object()
    for current_item, next_item in pairwise(chain(seq, [MISSING])):
        yield current_item, next_item is MISSING:

for item, is_last_item in annotated_last(data_list):
    if is_last_item:
        # current item is the last item

You can use a sliding window over the input data to get a peek at the next value and use a sentinel to detect the last value. This works on any iterable, so you don’t need to know the length beforehand. The pairwise implementation is from itertools recipes.

from itertools import tee, izip, chain

def pairwise(seq):
    a,b = tee(seq)
    next(b, None)
    return izip(a,b)

def annotated_last(seq):
    """Returns an iterable of pairs of input item and a boolean that show if
    the current item is the last item in the sequence."""
    MISSING = object()
    for current_item, next_item in pairwise(chain(seq, [MISSING])):
        yield current_item, next_item is MISSING:

for item, is_last_item in annotated_last(data_list):
    if is_last_item:
        # current item is the last item

回答 7

除了最后一个元素之外,是否没有可能遍历所有元素,并在循环之外处理最后一个元素?毕竟,创建了一个循环来执行与您循环的所有元素相似的操作;如果一个元素需要一些特殊的东西,它就不应该出现在循环中。

(另请参见此问题:循环中的最后一个元素是否值得单独处理

编辑:由于问题更多地是关于“之间”,所以第一个元素是特殊的,因为它没有前任,或者最后一个元素是特殊的,因为它没有后继。

Is there no possibility to iterate over all-but the last element, and treat the last one outside of the loop? After all, a loop is created to do something similar to all elements you loop over; if one element needs something special, it shouldn’t be in the loop.

(see also this question: does-the-last-element-in-a-loop-deserve-a-separate-treatment)

EDIT: since the question is more about the “in between”, either the first element is the special one in that it has no predecessor, or the last element is special in that it has no successor.


回答 8

我喜欢@ ethan-t的方法,但是while True从我的角度来看很危险。

data_list = [1, 2, 3, 2, 1]  # sample data
L = list(data_list)  # destroy L instead of data_list
while L:
    e = L.pop(0)
    if L:
        print(f'process element {e}')
    else:
        print(f'process last element {e}')
del L

在这里,data_list使得最后一个元素在值上等于列表中的第一个。L可以交换,data_list但在这种情况下,循环后结果为空。while True如果您在处理之前检查列表是否为空或不需要检查,也可以使用(检查!)。

data_list = [1, 2, 3, 2, 1]
if data_list:
    while True:
        e = data_list.pop(0)
        if data_list:
            print(f'process element {e}')
        else:
            print(f'process last element {e}')
            break
else:
    print('list is empty')

好的方面是它很快。坏-它是可破坏的(data_list变空)。

最直观的解决方案:

data_list = [1, 2, 3, 2, 1]  # sample data
for i, e in enumerate(data_list):
    if i != len(data_list) - 1:
        print(f'process element {e}')
    else:
        print(f'process last element {e}')

哦,是的,您已经提出了!

I like the approach of @ethan-t, but while True is dangerous from my point of view.

data_list = [1, 2, 3, 2, 1]  # sample data
L = list(data_list)  # destroy L instead of data_list
while L:
    e = L.pop(0)
    if L:
        print(f'process element {e}')
    else:
        print(f'process last element {e}')
del L

Here, data_list is so that last element is equal by value to the first one of the list. L can be exchanged with data_list but in this case it results empty after the loop. while True is also possible to use if you check that list is not empty before the processing or the check is not needed (ouch!).

data_list = [1, 2, 3, 2, 1]
if data_list:
    while True:
        e = data_list.pop(0)
        if data_list:
            print(f'process element {e}')
        else:
            print(f'process last element {e}')
            break
else:
    print('list is empty')

The good part is that it is fast. The bad – it is destructible (data_list becomes empty).

Most intuitive solution:

data_list = [1, 2, 3, 2, 1]  # sample data
for i, e in enumerate(data_list):
    if i != len(data_list) - 1:
        print(f'process element {e}')
    else:
        print(f'process last element {e}')

Oh yes, you have already proposed it!


回答 9

您的方式没有错,除非您将有100 000个循环并要保存100 000个“ if”语句。在这种情况下,您可以这样:

iterable = [1,2,3] # Your date
iterator = iter(iterable) # get the data iterator

try :   # wrap all in a try / except
    while 1 : 
        item = iterator.next() 
        print item # put the "for loop" code here
except StopIteration, e : # make the process on the last element here
    print item

输出:

1
2
3
3

但实际上,就您而言,我觉得这太过分了。

无论如何,切片可能会让您更幸运:

for item in iterable[:-1] :
    print item
print "last :", iterable[-1]

#outputs
1
2
last : 3

要不就 :

for item in iterable :
    print item
print iterable[-1]

#outputs
1
2
3
last : 3

最终,采用KISS方式为您做事,这将适用于任何可迭代的事物,包括那些没有__len__

item = ''
for item in iterable :
    print item
print item

1
2
3
3

如果觉得我会那样做,对我来说似乎很简单。

There is nothing wrong with your way, unless you will have 100 000 loops and wants save 100 000 “if” statements. In that case, you can go that way :

iterable = [1,2,3] # Your date
iterator = iter(iterable) # get the data iterator

try :   # wrap all in a try / except
    while 1 : 
        item = iterator.next() 
        print item # put the "for loop" code here
except StopIteration, e : # make the process on the last element here
    print item

Outputs :

1
2
3
3

But really, in your case I feel like it’s overkill.

In any case, you will probably be luckier with slicing :

for item in iterable[:-1] :
    print item
print "last :", iterable[-1]

#outputs
1
2
last : 3

or just :

for item in iterable :
    print item
print iterable[-1]

#outputs
1
2
3
last : 3

Eventually, a KISS way to do you stuff, and that would work with any iterable, including the ones without __len__ :

item = ''
for item in iterable :
    print item
print item

Ouputs:

1
2
3
3

If feel like I would do it that way, seems simple to me.


回答 10

使用切片和is检查最后一个元素:

for data in data_list:
    <code_that_is_done_for_every_element>
    if not data is data_list[-1]:
        <code_that_is_done_between_elements>

注意:仅当列表中的所有元素实际上都不同(在内存中具有不同的位置)时,此方法才有效。在后台,Python可能会检测到相等的元素,并为它们重用相同的对象。例如,对于具有相同值和共同整数的字符串。

Use slicing and is to check for the last element:

for data in data_list:
    <code_that_is_done_for_every_element>
    if not data is data_list[-1]:
        <code_that_is_done_between_elements>

Caveat emptor: This only works if all elements in the list are actually different (have different locations in memory). Under the hood, Python may detect equal elements and reuse the same objects for them. For instance, for strings of the same value and common integers.


回答 11

如果您要查看清单,对我来说,这也可行:

for j in range(0, len(Array)):
    if len(Array) - j > 1:
        notLast()

if you are going through the list, for me this worked too:

for j in range(0, len(Array)):
    if len(Array) - j > 1:
        notLast()

回答 12

Google将我带到这个老问题,我想我可以为这个问题添加另一种方法。

这里的大多数答案将按要求处理for循环控制,但是,如果data_list是可破坏的,我建议您从列表中弹出项目,直到最终得到一个空列表:

while True:
    element = element_list.pop(0)
    do_this_for_all_elements()
    if not element:
        do_this_only_for_last_element()
        break
    do_this_for_all_elements_but_last()

如果您不需要对最后一个元素做任何事情,甚至可以在len(element_list)时使用。我发现此解决方案比next()更优雅。

Google brought me to this old question and I think I could add a different approach to this problem.

Most of the answers here would deal with a proper treatment of a for loop control as it was asked, but if the data_list is destructible, I would suggest that you pop the items from the list until you end up with an empty list:

while True:
    element = element_list.pop(0)
    do_this_for_all_elements()
    if not element:
        do_this_only_for_last_element()
        break
    do_this_for_all_elements_but_last()

you could even use while len(element_list) if you don’t need to do anything with the last element. I find this solution more elegant then dealing with next().


回答 13

对我而言,处理列表结尾处的特殊情况的最简单,最Python的方法是:

for data in data_list[:-1]:
    handle_element(data)
handle_special_element(data_list[-1])

当然,这也可以用来以特殊方式处理第一个元素。

For me the most simple and pythonic way to handle a special case at the end of a list is:

for data in data_list[:-1]:
    handle_element(data)
handle_special_element(data_list[-1])

Of course this can also be used to treat the first element in a special way .


回答 14

除了递增计数,您还可以递减计数:

  nrToProcess = len(list)
  for s in list:
    s.doStuff()
    nrToProcess -= 1
    if nrToProcess==0:  # this is the last one
      s.doSpecialStuff()

Instead of counting up, you can also count down:

  nrToProcess = len(list)
  for s in list:
    s.doStuff()
    nrToProcess -= 1
    if nrToProcess==0:  # this is the last one
      s.doSpecialStuff()

回答 15

将最后一项的特殊处理延迟到循环之后。

>>> for i in (1, 2, 3):
...     pass
...
>>> i
3

Delay the special handling of the last item until after the loop.

>>> for i in (1, 2, 3):
...     pass
...
>>> i
3

回答 16

可以有多种方式。切片将最快。再添加一个使用.index()方法的对象:

>>> l1 = [1,5,2,3,5,1,7,43]                                                 
>>> [i for i in l1 if l1.index(i)+1==len(l1)]                               
[43]

There can be multiple ways. slicing will be fastest. Adding one more which uses .index() method:

>>> l1 = [1,5,2,3,5,1,7,43]                                                 
>>> [i for i in l1 if l1.index(i)+1==len(l1)]                               
[43]

回答 17

假设输入为迭代器,以下是使用itertools中的tee和izip的方法:

from itertools import tee, izip
items, between = tee(input_iterator, 2)  # Input must be an iterator.
first = items.next()
do_to_every_item(first)  # All "do to every" operations done to first item go here.
for i, b in izip(items, between):
    do_between_items(b)  # All "between" operations go here.
    do_to_every_item(i)  # All "do to every" operations go here.

演示:

>>> def do_every(x): print "E", x
...
>>> def do_between(x): print "B", x
...
>>> test_input = iter(range(5))
>>>
>>> from itertools import tee, izip
>>>
>>> items, between = tee(test_input, 2)
>>> first = items.next()
>>> do_every(first)
E 0
>>> for i,b in izip(items, between):
...     do_between(b)
...     do_every(i)
...
B 0
E 1
B 1
E 2
B 2
E 3
B 3
E 4
>>>

Assuming input as an iterator, here’s a way using tee and izip from itertools:

from itertools import tee, izip
items, between = tee(input_iterator, 2)  # Input must be an iterator.
first = items.next()
do_to_every_item(first)  # All "do to every" operations done to first item go here.
for i, b in izip(items, between):
    do_between_items(b)  # All "between" operations go here.
    do_to_every_item(i)  # All "do to every" operations go here.

Demo:

>>> def do_every(x): print "E", x
...
>>> def do_between(x): print "B", x
...
>>> test_input = iter(range(5))
>>>
>>> from itertools import tee, izip
>>>
>>> items, between = tee(test_input, 2)
>>> first = items.next()
>>> do_every(first)
E 0
>>> for i,b in izip(items, between):
...     do_between(b)
...     do_every(i)
...
B 0
E 1
B 1
E 2
B 2
E 3
B 3
E 4
>>>

回答 18

我想到的最简单的解决方案是:

for item in data_list:
    try:
        print(new)
    except NameError: pass
    new = item
print('The last item: ' + str(new))

因此,我们总是通过延迟处理一次迭代来向前看一项。要跳过第一次迭代期间的操作,我只是捕捉到了错误。

当然,您需要考虑一下,以便在NameError需要时提出它。

同时保持`counstruct

try:
    new
except NameError: pass
else:
    # continue here if no error was raised

这依赖于先前未定义新名称。如果您偏执狂,可以new使用以下方法确保不存在:

try:
    del new
except NameError:
    pass

另外,您当然也可以使用if语句(if notfirst: print(new) else: notfirst = True)。但据我所知,开销更大。


Using `timeit` yields:

    ...: try: new = 'test' 
    ...: except NameError: pass
    ...: 
100000000 loops, best of 3: 16.2 ns per loop

所以我希望开销是无法避免的。

The most simple solution coming to my mind is:

for item in data_list:
    try:
        print(new)
    except NameError: pass
    new = item
print('The last item: ' + str(new))

So we always look ahead one item by delaying the the processing one iteration. To skip doing something during the first iteration I simply catch the error.

Of course you need to think a bit, in order for the NameError to be raised when you want it.

Also keep the `counstruct

try:
    new
except NameError: pass
else:
    # continue here if no error was raised

This relies that the name new wasn’t previously defined. If you are paranoid you can ensure that new doesn’t exist using:

try:
    del new
except NameError:
    pass

Alternatively you can of course also use an if statement (if notfirst: print(new) else: notfirst = True). But as far as I know the overhead is bigger.


Using `timeit` yields:

    ...: try: new = 'test' 
    ...: except NameError: pass
    ...: 
100000000 loops, best of 3: 16.2 ns per loop

so I expect the overhead to be unelectable.


回答 19

计数一次,并跟上剩余的项目数:

remaining = len(data_list)
for data in data_list:
    code_that_is_done_for_every_element

    remaining -= 1
    if remaining:
        code_that_is_done_between_elements

这样,您只需评估列表的长度一次。该页面上的许多解决方案似乎都假定长度是预先不可用的,但这不是您的问题的一部分。如果您有长度,请使用它。

Count the items once and keep up with the number of items remaining:

remaining = len(data_list)
for data in data_list:
    code_that_is_done_for_every_element

    remaining -= 1
    if remaining:
        code_that_is_done_between_elements

This way you only evaluate the length of the list once. Many of the solutions on this page seem to assume the length is unavailable in advance, but that is not part of your question. If you have the length, use it.


回答 20

我想到的一个简单的解决方案是:

for i in MyList:
    # Check if 'i' is the last element in the list
    if i == MyList[-1]:
        # Do something different for the last
    else:
        # Do something for all other elements

第二个同样简单的解决方案可以通过使用计数器来实现:

# Count the no. of elements in the list
ListLength = len(MyList)
# Initialize a counter
count = 0

for i in MyList:
    # increment counter
    count += 1
    # Check if 'i' is the last element in the list
    # by using the counter
    if count == ListLength:
        # Do something different for the last
    else:
        # Do something for all other elements

One simple solution that comes to mind would be:

for i in MyList:
    # Check if 'i' is the last element in the list
    if i == MyList[-1]:
        # Do something different for the last
    else:
        # Do something for all other elements

A second equally simple solution could be achieved by using a counter:

# Count the no. of elements in the list
ListLength = len(MyList)
# Initialize a counter
count = 0

for i in MyList:
    # increment counter
    count += 1
    # Check if 'i' is the last element in the list
    # by using the counter
    if count == ListLength:
        # Do something different for the last
    else:
        # Do something for all other elements

Python成语返回第一项或无

问题:Python成语返回第一项或无

我敢肯定,有一种更简单的方法可以做到这一点,而这只是我自己没有想到的。

我正在调用一堆返回列表的方法。该列表可能为空。如果列表是非空的,我想返回第一项。否则,我想返回无。此代码有效:

my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None

在我看来,这样做应该有一个简单的一句习惯用语,但是对于我的一生,我无法想到。在那儿?

编辑:

我在这里寻找单行表达式的原因并不是我喜欢令人难以置信的简洁代码,而是因为我不得不编写很多这样的代码:

x = get_first_list()
if x:
    # do something with x[0]
    # inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
    # do something with y[0]
    # inevitably forget the [0] part AGAIN, and have another bug to fix

我想做的事情肯定可以通过一个函数来完成(可能会做到):

def first_item(list_or_none):
    if list_or_none: return list_or_none[0]

x = first_item(get_first_list())
if x:
    # do something with x
y = first_item(get_second_list())
if y:
    # do something with y

我发布了这个问题,是因为我经常对Python中的简单表达式可以做什么感到惊讶,并且我认为如果有一个简单的表达式可以完成此任务,那么编写函数是一件很愚蠢的事情。但是看到这些答案,似乎函数简单的解决方案。

I’m sure there’s a simpler way of doing this that’s just not occurring to me.

I’m calling a bunch of methods that return a list. The list may be empty. If the list is non-empty, I want to return the first item; otherwise, I want to return None. This code works:

my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None

It seems to me that there should be a simple one-line idiom for doing this, but for the life of me I can’t think of it. Is there?

Edit:

The reason that I’m looking for a one-line expression here is not that I like incredibly terse code, but because I’m having to write a lot of code like this:

x = get_first_list()
if x:
    # do something with x[0]
    # inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
    # do something with y[0]
    # inevitably forget the [0] part AGAIN, and have another bug to fix

What I’d like to be doing can certainly be accomplished with a function (and probably will be):

def first_item(list_or_none):
    if list_or_none: return list_or_none[0]

x = first_item(get_first_list())
if x:
    # do something with x
y = first_item(get_second_list())
if y:
    # do something with y

I posted the question because I’m frequently surprised by what simple expressions in Python can do, and I thought that writing a function was a silly thing to do if there was a simple expression could do the trick. But seeing these answers, it seems like a function is the simple solution.


回答 0

Python 2.6以上

next(iter(your_list), None)

如果your_list可以None

next(iter(your_list or []), None)

Python 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

例:

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

另一个选择是内联以上函数:

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

为了避免break您可以写:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

哪里:

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return

Python 2.6+

next(iter(your_list), None)

If your_list can be None:

next(iter(your_list or []), None)

Python 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

Example:

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

Another option is to inline the above function:

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

To avoid break you could write:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

Where:

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return

回答 1

最好的方法是这样的:

a = get_list()
return a[0] if a else None

您也可以在一行中完成此操作,但是对于程序员而言,阅读起来要困难得多:

return (get_list()[:1] or [None])[0]

The best way is this:

a = get_list()
return a[0] if a else None

You could also do it in one line, but it’s much harder for the programmer to read:

return (get_list()[:1] or [None])[0]

回答 2

(get_list() or [None])[0]

那应该工作。

顺便说一句,我没有使用变量list,因为它会覆盖内置list()函数。

编辑:我在这里有一个稍微简单一点,但错误的版本。

(get_list() or [None])[0]

That should work.

BTW I didn’t use the variable list, because that overwrites the builtin list() function.

Edit: I had a slightly simpler, but wrong version here earlier.


回答 3

python最惯用的方式是在list上使用next(),因为list是可迭代的。就像@JFSebastian在2011年12月13日发表的评论一样。

next(iter(the_list), None)如果the_list为空,则返回None 。参见next()Python 2.6+

或者,如果您确定the_list不为空:

iter(the_list).next()参见iterator.next()Python 2.2+

The most python idiomatic way is to use the next() on a iterator since list is iterable. just like what @J.F.Sebastian put in the comment on Dec 13, 2011.

next(iter(the_list), None) This returns None if the_list is empty. see next() Python 2.6+

or if you know for sure the_list is not empty:

iter(the_list).next() see iterator.next() Python 2.2+


回答 4

如果您发现自己想从列表理解中提取第一件事(或无),则可以切换到生成器来执行以下操作:

next((x for x in blah if cond), None)

专业版:如果blah不可索引,则可以使用。专业版:语法不熟悉。虽然在ipython中进行黑客入侵和过滤时非常有用。

If you find yourself trying to pluck the first thing (or None) from a list comprehension you can switch to a generator to do it like:

next((x for x in blah if cond), None)

Pro: works if blah isn’t indexable Con: it’s unfamiliar syntax. It’s useful while hacking around and filtering stuff in ipython though.


回答 5

OP的解决方案即将到来,只有几件事可以使其变得更加Pythonic。

一方面,不需要获取列表的长度。如果检查,Python中的空列表的评估结果为False。只是简单地说

if list:

另外,将变量分配给与保留字重叠的变量是一个非常糟糕的主意。“列表”是Python中的保留字。

所以我们将其更改为

some_list = get_list()
if some_list:

许多解决方案在这里遗漏的一个非常重要的一点是,所有Python函数/方法默认都返回None。请尝试以下方法。

def does_nothing():
    pass

foo = does_nothing()
print foo

除非您需要返回None来尽早终止函数,否则没有必要显式返回None。非常简洁,只要它存在就返回第一个条目。

some_list = get_list()
if some_list:
    return list[0]

最后,也许这是暗含的,但只是为了明确(因为explicit比隐式更好),您不应该让您的函数从另一个函数获取列表。只需将其作为参数传递即可。因此,最终结果将是

def get_first_item(some_list): 
    if some_list:
        return list[0]

my_list = get_list()
first_item = get_first_item(my_list)

就像我说的,OP差不多在那儿了,只需轻轻一点就可以找到您想要的Python风格。

The OP’s solution is nearly there, there are just a few things to make it more Pythonic.

For one, there’s no need to get the length of the list. Empty lists in Python evaluate to False in an if check. Just simply say

if list:

Additionally, it’s a very Bad Idea to assign to variables that overlap with reserved words. “list” is a reserved word in Python.

So let’s change that to

some_list = get_list()
if some_list:

A really important point that a lot of solutions here miss is that all Python functions/methods return None by default. Try the following below.

def does_nothing():
    pass

foo = does_nothing()
print foo

Unless you need to return None to terminate a function early, it’s unnecessary to explicitly return None. Quite succinctly, just return the first entry, should it exist.

some_list = get_list()
if some_list:
    return list[0]

And finally, perhaps this was implied, but just to be explicit (because explicit is better than implicit), you should not have your function get the list from another function; just pass it in as a parameter. So, the final result would be

def get_first_item(some_list): 
    if some_list:
        return list[0]

my_list = get_list()
first_item = get_first_item(my_list)

As I said, the OP was nearly there, and just a few touches give it the Python flavor you’re looking for.


回答 6

for item in get_list():
    return item
for item in get_list():
    return item

回答 7

坦白地说,我认为没有更好的成语:您清楚而简洁-不需要任何“更好”的东西。也许吧,但是这的确是一个风格问题,你可以改变if len(list) > 0:使用if list:-一个空列表将永远评估为假。

在相关说明中,Python 不是 Perl(无双关!),您不必获取最酷的代码。
实际上,我在Python中看到的最糟糕的代码也很酷:-),并且完全无法维护。

顺便说一句,当list [0]计算为False(例如,空字符串或零)时,我在这里看到的大多数解决方案都没有考虑-在这种情况下,它们都返回None而不是正确的元素。

Frankly speaking, I do not think there is a better idiom: your is clear and terse – no need for anything “better”. Maybe, but this is really a matter of taste, you could change if len(list) > 0: with if list: – an empty list will always evaluate to False.

On a related note, Python is not Perl (no pun intended!), you do not have to get the coolest code possible.
Actually, the worst code I have seen in Python, was also very cool :-) and completely unmaintainable.

By the way, most of the solution I have seen here do not take into consideration when list[0] evaluates to False (e.g. empty string, or zero) – in this case, they all return None and not the correct element.


回答 8

返回第一项的Python习惯用法或无?

最Python化的方法是最受支持的答案所展示的内容,这是我阅读该问题时想到的第一件事。这是使用方法,首先将可能为空的列表传递给函数:

def get_first(l): 
    return l[0] if l else None

如果列表是从get_list函数返回的:

l = get_list()
return l[0] if l else None

在此演示了其他方法,并附有说明

for

当我开始想办法做到这一点时,这是我想到的第二件事:

for item in get_list():
    return item

假定函数在此处结束,None如果get_list返回空列表,则隐式返回。下面的显式代码完全等效:

for item in get_list():
    return item
return None

if some_list

还提出了以下建议(我更正了错误的变量名),该建议也使用了隐式None。这将比上面更好,因为它使用逻辑检查而不是可能不会发生的迭代。这应该更容易立即了解正在发生的事情。但是,如果我们正在编写易读性和可维护性,则还应该return None在末尾添加显式内容:

some_list = get_list()
if some_list:
    return some_list[0]

切片or [None]并选择零索引

这个也是最受好评的答案:

return (get_list()[:1] or [None])[0]

切片是不必要的,它会在内存中创建一个额外的单项列表。以下应该表现更好。为了说明,or如果第一个元素False在布尔上下文中,则get_list返回第二个元素,因此,如果返回一个空列表,则括号中包含的表达式将返回一个带有“ None”的列表,然后该0索引将被索引访问:

return (get_list() or [None])[0]

下一个使用以下事实,如果第一项True在布尔上下文中,则返回第二项,并且由于它两次引用my_list,因此它不比三元表达式更好(从技术上讲也不是单行):

my_list = get_list() 
return (my_list and my_list[0]) or None

next

然后,我们有以下巧妙地利用内建的nextiter

return next(iter(get_list()), None)

为了说明,iter返回带有.next方法的迭代器。(.__next__在Python 3中)。然后内建函数next调用该.next方法,如果迭代器已用尽,则返回默认值None

多余的三元表达式(a if b else c)并返回

提出了以下内容,但最好采用反函数,因为通常最好用正数而不是负数来理解逻辑。由于get_list被调用两次,除非以某种方式记录结果,否则执行效果会很差:

return None if not get_list() else get_list()[0]

更好的逆:

return get_list()[0] if get_list() else None

更好的是,使用局部变量,这样get_list只能被调用一次,并且您首先讨论了推荐的Pythonic解决方案:

l = get_list()
return l[0] if l else None

Python idiom to return first item or None?

The most Pythonic approach is what the most upvoted answer demonstrated, and it was the first thing to come to my mind when I read the question. Here’s how to use it, first if the possibly empty list is passed into a function:

def get_first(l): 
    return l[0] if l else None

And if the list is returned from a get_list function:

l = get_list()
return l[0] if l else None

Other ways demonstrated to do this here, with explanations

for

When I began trying to think of clever ways to do this, this is the second thing I thought of:

for item in get_list():
    return item

This presumes the function ends here, implicitly returning None if get_list returns an empty list. The below explicit code is exactly equivalent:

for item in get_list():
    return item
return None

if some_list

The following was also proposed (I corrected the incorrect variable name) which also uses the implicit None. This would be preferable to the above, as it uses the logical check instead of an iteration that may not happen. This should be easier to understand immediately what is happening. But if we’re writing for readability and maintainability, we should also add the explicit return None at the end:

some_list = get_list()
if some_list:
    return some_list[0]

slice or [None] and select zeroth index

This one is also in the most up-voted answer:

return (get_list()[:1] or [None])[0]

The slice is unnecessary, and creates an extra one-item list in memory. The following should be more performant. To explain, or returns the second element if the first is False in a boolean context, so if get_list returns an empty list, the expression contained in the parentheses will return a list with ‘None’, which will then be accessed by the 0 index:

return (get_list() or [None])[0]

The next one uses the fact that and returns the second item if the first is True in a boolean context, and since it references my_list twice, it is no better than the ternary expression (and technically not a one-liner):

my_list = get_list() 
return (my_list and my_list[0]) or None

next

Then we have the following clever use of the builtin next and iter

return next(iter(get_list()), None)

To explain, iter returns an iterator with a .next method. (.__next__ in Python 3.) Then the builtin next calls that .next method, and if the iterator is exhausted, returns the default we give, None.

redundant ternary expression (a if b else c) and circling back

The below was proposed, but the inverse would be preferable, as logic is usually better understood in the positive instead of the negative. Since get_list is called twice, unless the result is memoized in some way, this would perform poorly:

return None if not get_list() else get_list()[0]

The better inverse:

return get_list()[0] if get_list() else None

Even better, use a local variable so that get_list is only called one time, and you have the recommended Pythonic solution first discussed:

l = get_list()
return l[0] if l else None

回答 9

关于惯用语,有一个itertools配方,称为nth

从itertools配方中:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

如果您需要单行,请考虑安装一个为您实现此食谱的库,例如more_itertools

import more_itertools as mit

mit.nth([3, 2, 1], 0)
# 3

mit.nth([], 0)                                             # default is `None`
# None

可以使用另一个仅返回第一项的工具more_itertools.first

mit.first([3, 2, 1])
# 3

mit.first([], default=None)
# None

这些itertools通常可扩展用于任何迭代,而不仅适用于列表。

Regarding idioms, there is an itertools recipe called nth.

From itertools recipes:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

If you want one-liners, consider installing a library that implements this recipe for you, e.g. more_itertools:

import more_itertools as mit

mit.nth([3, 2, 1], 0)
# 3

mit.nth([], 0)                                             # default is `None`
# None

Another tool is available that only returns the first item, called more_itertools.first.

mit.first([3, 2, 1])
# 3

mit.first([], default=None)
# None

These itertools scale generically for any iterable, not only for lists.


回答 10

my_list[0] if len(my_list) else None

my_list[0] if len(my_list) else None


回答 11

出于好奇,我选择了两个解决方案。使用return语句过早结束for循环的解决方案在使用Python 2.5.1的计算机上的成本稍高,我怀疑这与设置可迭代性有关。

import random
import timeit

def index_first_item(some_list):
    if some_list:
        return some_list[0]


def return_first_item(some_list):
    for item in some_list:
        return item


empty_lists = []
for i in range(10000):
    empty_lists.append([])

assert empty_lists[0] is not empty_lists[1]

full_lists = []
for i in range(10000):
    full_lists.append(list([random.random() for i in range(10)]))

mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)

if __name__ == '__main__':
    ENV = 'import firstitem'
    test_data = ('empty_lists', 'full_lists', 'mixed_lists')
    funcs = ('index_first_item', 'return_first_item')
    for data in test_data:
        print "%s:" % data
        for func in funcs:
            t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
                func, data), ENV)
            times = t.repeat()
            avg_time = sum(times) / len(times)
            print "  %s:" % func
            for time in times:
                print "    %f seconds" % time
            print "    %f seconds avg." % avg_time

这些是我得到的时间:

empty_lists:
  index_first_item:
    0.748353秒
    0.741086秒
    0.741191秒
    平均0.743543秒
  return_first_item:
    0.785511秒
    0.822178秒
    0.782846秒
    平均0.796845秒
完整列表:
  index_first_item:
    0.762618秒
    0.788040秒
    0.786849秒
    平均0.779169秒
  return_first_item:
    0.802735秒
    0.878706秒
    0.808781秒
    平均0.830074秒
mixed_lists:
  index_first_item:
    0.791129秒
    0.743526秒
    0.744441秒
    平均0.759699秒
  return_first_item:
    0.784801秒
    0.785146秒
    0.840193秒
    平均0.803380秒

Out of curiosity, I ran timings on two of the solutions. The solution which uses a return statement to prematurely end a for loop is slightly more costly on my machine with Python 2.5.1, I suspect this has to do with setting up the iterable.

import random
import timeit

def index_first_item(some_list):
    if some_list:
        return some_list[0]


def return_first_item(some_list):
    for item in some_list:
        return item


empty_lists = []
for i in range(10000):
    empty_lists.append([])

assert empty_lists[0] is not empty_lists[1]

full_lists = []
for i in range(10000):
    full_lists.append(list([random.random() for i in range(10)]))

mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)

if __name__ == '__main__':
    ENV = 'import firstitem'
    test_data = ('empty_lists', 'full_lists', 'mixed_lists')
    funcs = ('index_first_item', 'return_first_item')
    for data in test_data:
        print "%s:" % data
        for func in funcs:
            t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
                func, data), ENV)
            times = t.repeat()
            avg_time = sum(times) / len(times)
            print "  %s:" % func
            for time in times:
                print "    %f seconds" % time
            print "    %f seconds avg." % avg_time

These are the timings I got:

empty_lists:
  index_first_item:
    0.748353 seconds
    0.741086 seconds
    0.741191 seconds
    0.743543 seconds avg.
  return_first_item:
    0.785511 seconds
    0.822178 seconds
    0.782846 seconds
    0.796845 seconds avg.
full_lists:
  index_first_item:
    0.762618 seconds
    0.788040 seconds
    0.786849 seconds
    0.779169 seconds avg.
  return_first_item:
    0.802735 seconds
    0.878706 seconds
    0.808781 seconds
    0.830074 seconds avg.
mixed_lists:
  index_first_item:
    0.791129 seconds
    0.743526 seconds
    0.744441 seconds
    0.759699 seconds avg.
  return_first_item:
    0.784801 seconds
    0.785146 seconds
    0.840193 seconds
    0.803380 seconds avg.

回答 12

try:
    return a[0]
except IndexError:
    return None
try:
    return a[0]
except IndexError:
    return None

回答 13

def head(iterable):
    try:
        return iter(iterable).next()
    except StopIteration:
        return None

print head(xrange(42, 1000)  # 42
print head([])               # None

顺便说一句:我会将您的通用程序流程改编成这样的东西:

lists = [
    ["first", "list"],
    ["second", "list"],
    ["third", "list"]
]

def do_something(element):
    if not element:
        return
    else:
        # do something
        pass

for li in lists:
    do_something(head(li))

(尽可能避免重复)

def head(iterable):
    try:
        return iter(iterable).next()
    except StopIteration:
        return None

print head(xrange(42, 1000)  # 42
print head([])               # None

BTW: I’d rework your general program flow into something like this:

lists = [
    ["first", "list"],
    ["second", "list"],
    ["third", "list"]
]

def do_something(element):
    if not element:
        return
    else:
        # do something
        pass

for li in lists:
    do_something(head(li))

(Avoiding repetition whenever possible)


回答 14

这个怎么样:

(my_list and my_list[0]) or None

注意:这对于对象列表应该可以正常工作,但是如果根据以下注释列出数字或字符串,则可能会返回错误的答案。

How about this:

(my_list and my_list[0]) or None

Note: This should work fine for lists of objects but it might return incorrect answer in case of number or string list per the comments below.


回答 15

不知道这是什么pythonic,但是直到库中有第一个函数,我才在源代码中包括它:

first = lambda l, default=None: next(iter(l or []), default)

这只是一行(变成黑色),避免了依赖关系。

Not sure how pythonic this is but until there is a first function in the library I include this in the source:

first = lambda l, default=None: next(iter(l or []), default)

It’s just one line (conforms to black) and avoids dependencies.


回答 16

使用and-or技巧:

a = get_list()
return a and a[0] or None

Using the and-or trick:

a = get_list()
return a and a[0] or None

回答 17

可能不是最快的解决方案,但没有人提到此选项:

dict(enumerate(get_list())).get(0)

如果get_list()可以退货,None您可以使用:

dict(enumerate(get_list() or [])).get(0)

优点:

-一条线

-您只需拨打get_list()一次

-容易理解

Probably not the fastest solution, but nobody mentioned this option:

dict(enumerate(get_list())).get(0)

if get_list() can return None you can use:

dict(enumerate(get_list() or [])).get(0)

Advantages:

-one line

-you just call get_list() once

-easy to understand


回答 18

我的用例只是设置局部变量的值。

我个人找到了尝试,除了风格更清晰的阅读

items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item

而不是切片列表。

items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item

My use case was only to set the value of a local variable.

Personally I found the try and except style cleaner to read

items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item

than slicing a list.

items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item

回答 19

一些人建议做这样的事情:

list = get_list()
return list and list[0] or None

这在许多情况下都有效,但是仅当list [0]不等于0,False或空字符串时才有效。如果list [0]为0,False或空字符串,则该方法将错误地返回None。

我已经在自己的代码中多次创建了该错误!

Several people have suggested doing something like this:

list = get_list()
return list and list[0] or None

That works in many cases, but it will only work if list[0] is not equal to 0, False, or an empty string. If list[0] is 0, False, or an empty string, the method will incorrectly return None.

I’ve created this bug in my own code one too many times !


回答 20

您可以使用Extract Method。换句话说,将代码提取到您要调用的方法中。

我不会尝试对其进行更多压缩,一个衬板似乎比详细版本更难读。而且,如果您使用提取方法,那是一个衬里;)

You could use Extract Method. In other words extract that code into a method which you’d then call.

I wouldn’t try to compress it much more, the one liners seem harder to read than the verbose version. And if you use Extract Method, it’s a one liner ;)


回答 21

if mylist != []:

       print(mylist[0])

   else:

       print(None)
if mylist != []:

       print(mylist[0])

   else:

       print(None)

回答 22

不是C语言三元运算符的惯用python吗

cond and true_expr or false_expr

即。

list = get_list()
return list and list[0] or None

isn’t the idiomatic python equivalent to C-style ternary operators

cond and true_expr or false_expr

ie.

list = get_list()
return list and list[0] or None

获取与字典中的最小值对应的键

问题:获取与字典中的最小值对应的键

如果我有Python字典,如何获得包含最小值的条目的键?

我正在考虑与该min()功能有关的事情…

给定输入:

{320:1, 321:0, 322:3}

它将返回321

If I have a Python dictionary, how do I get the key to the entry which contains the minimum value?

I was thinking about something to do with the min() function…

Given the input:

{320:1, 321:0, 322:3}

It would return 321.


回答 0

最好:min(d, key=d.get)-没有理由插入无用的lambda间接层或提取项目或密钥!

Best: min(d, key=d.get) — no reason to interpose a useless lambda indirection layer or extract items or keys!


回答 1

这实际上是提供OP所需解决方案的答案:

>>> d = {320:1, 321:0, 322:3}
>>> d.items()
[(320, 1), (321, 0), (322, 3)]
>>> # find the minimum by comparing the second element of each tuple
>>> min(d.items(), key=lambda x: x[1]) 
(321, 0)

d.iteritems()但是,对于较大的词典,使用将更为有效。

Here’s an answer that actually gives the solution the OP asked for:

>>> d = {320:1, 321:0, 322:3}
>>> d.items()
[(320, 1), (321, 0), (322, 3)]
>>> # find the minimum by comparing the second element of each tuple
>>> min(d.items(), key=lambda x: x[1]) 
(321, 0)

Using d.iteritems() will be more efficient for larger dictionaries, however.


回答 2

对于具有相等最小值的多个键,可以使用列表理解:

d = {320:1, 321:0, 322:3, 323:0}

minval = min(d.values())
res = [k for k, v in d.items() if v==minval]

[321, 323]

等效功能版本:

res = list(filter(lambda x: d[x]==minval, d))

For multiple keys which have equal lowest value, you can use a list comprehension:

d = {320:1, 321:0, 322:3, 323:0}

minval = min(d.values())
res = [k for k, v in d.items() if v==minval]

[321, 323]

An equivalent functional version:

res = list(filter(lambda x: d[x]==minval, d))

回答 3

min(d.items(), key=lambda x: x[1])[0]

min(d.items(), key=lambda x: x[1])[0]


回答 4

>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321

回答 5

对于您有多个最小键并希望保持简单的情况

def minimums(some_dict):
    positions = [] # output variable
    min_value = float("inf")
    for k, v in some_dict.items():
        if v == min_value:
            positions.append(k)
        if v < min_value:
            min_value = v
            positions = [] # output variable
            positions.append(k)

    return positions

minimums({'a':1, 'b':2, 'c':-1, 'd':0, 'e':-1})

['e', 'c']

For the case where you have multiple minimal keys and want to keep it simple

def minimums(some_dict):
    positions = [] # output variable
    min_value = float("inf")
    for k, v in some_dict.items():
        if v == min_value:
            positions.append(k)
        if v < min_value:
            min_value = v
            positions = [] # output variable
            positions.append(k)

    return positions

minimums({'a':1, 'b':2, 'c':-1, 'd':0, 'e':-1})

['e', 'c']

回答 6

如果您不确定是否没有多个最小值,我建议:

d = {320:1, 321:0, 322:3, 323:0}
print ', '.join(str(key) for min_value in (min(d.values()),) for key in d if d[key]==min_value)

"""Output:
321, 323
"""

If you are not sure that you have not multiple minimum values, I would suggest:

d = {320:1, 321:0, 322:3, 323:0}
print ', '.join(str(key) for min_value in (min(d.values()),) for key in d if d[key]==min_value)

"""Output:
321, 323
"""

回答 7

编辑:这是OP 关于最小密钥而不是最小答案的原始问题的答案。


您可以使用keys函数获取字典的键,并且正确使用min来查找该列表的最小值。

Edit: this is an answer to the OP’s original question about the minimal key, not the minimal answer.


You can get the keys of the dict using the keys function, and you’re right about using min to find the minimum of that list.


回答 8

解决具有相同最小值的多个键的另一种方法:

>>> dd = {320:1, 321:0, 322:3, 323:0}
>>>
>>> from itertools import groupby
>>> from operator import itemgetter
>>>
>>> print [v for k,v in groupby(sorted((v,k) for k,v in dd.iteritems()), key=itemgetter(0)).next()[1]]
[321, 323]

Another approach to addressing the issue of multiple keys with the same min value:

>>> dd = {320:1, 321:0, 322:3, 323:0}
>>>
>>> from itertools import groupby
>>> from operator import itemgetter
>>>
>>> print [v for k,v in groupby(sorted((v,k) for k,v in dd.iteritems()), key=itemgetter(0)).next()[1]]
[321, 323]

回答 9

使用min与迭代器(对于Python 3使用items代替iteritems); 代替lambda使用itemgetterfrom运算符,它比lambda更快。

from operator import itemgetter
min_key, _ = min(d.iteritems(), key=itemgetter(1))

Use min with an iterator (for python 3 use items instead of iteritems); instead of lambda use the itemgetter from operator, which is faster than lambda.

from operator import itemgetter
min_key, _ = min(d.iteritems(), key=itemgetter(1))

回答 10

d={}
d[320]=1
d[321]=0
d[322]=3
value = min(d.values())
for k in d.keys(): 
    if d[k] == value:
        print k,d[k]
d={}
d[320]=1
d[321]=0
d[322]=3
value = min(d.values())
for k in d.keys(): 
    if d[k] == value:
        print k,d[k]

回答 11

我比较了以下三个选项的执行情况:

    import random, datetime

myDict = {}
for i in range( 10000000 ):
    myDict[ i ] = random.randint( 0, 10000000 )



# OPTION 1

start = datetime.datetime.now()

sorted = []
for i in myDict:
    sorted.append( ( i, myDict[ i ] ) )
sorted.sort( key = lambda x: x[1] )
print( sorted[0][0] )

end = datetime.datetime.now()
print( end - start )



# OPTION 2

start = datetime.datetime.now()

myDict_values = list( myDict.values() )
myDict_keys = list( myDict.keys() )
min_value = min( myDict_values )
print( myDict_keys[ myDict_values.index( min_value ) ] )

end = datetime.datetime.now()
print( end - start )



# OPTION 3

start = datetime.datetime.now()

print( min( myDict, key=myDict.get ) )

end = datetime.datetime.now()
print( end - start )

样本输出:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048

I compared how the following three options perform:

    import random, datetime

myDict = {}
for i in range( 10000000 ):
    myDict[ i ] = random.randint( 0, 10000000 )



# OPTION 1

start = datetime.datetime.now()

sorted = []
for i in myDict:
    sorted.append( ( i, myDict[ i ] ) )
sorted.sort( key = lambda x: x[1] )
print( sorted[0][0] )

end = datetime.datetime.now()
print( end - start )



# OPTION 2

start = datetime.datetime.now()

myDict_values = list( myDict.values() )
myDict_keys = list( myDict.keys() )
min_value = min( myDict_values )
print( myDict_keys[ myDict_values.index( min_value ) ] )

end = datetime.datetime.now()
print( end - start )



# OPTION 3

start = datetime.datetime.now()

print( min( myDict, key=myDict.get ) )

end = datetime.datetime.now()
print( end - start )

Sample output:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048

回答 12

要创建可排序的类,您必须重写6个特殊函数,以便min()函数可以调用它

这些方法的__lt__ , __le__, __gt__, __ge__, __eq__ , __ne__顺序是小于,小于或等于,大于,大于或等于,等于,不等于。例如,您应该实现__lt__如下:

def __lt__(self, other):
  return self.comparable_value < other.comparable_value

那么您可以使用min函数,如下所示:

minValue = min(yourList, key=(lambda k: yourList[k]))

这对我有用。

to create an orderable class you have to override 6 special functions, so that it would be called by the min() function

these methods are__lt__ , __le__, __gt__, __ge__, __eq__ , __ne__ in order they are less than, less than or equal, greater than, greater than or equal, equal, not equal. for example you should implement __lt__ as follows:

def __lt__(self, other):
  return self.comparable_value < other.comparable_value

then you can use the min function as follows:

minValue = min(yourList, key=(lambda k: yourList[k]))

this worked for me.


回答 13

min(zip(d.values(), d.keys()))[1]

使用zip函数创建包含值和键的元组的迭代器。然后用min函数包装它,min函数根据第一个键取最小值。这将返回一个包含(值,键)对的元组。索引[1]用于获取对应的密钥

min(zip(d.values(), d.keys()))[1]

Use the zip function to create an iterator of tuples containing values and keys. Then wrap it with a min function which takes the minimum based on the first key. This returns a tuple containing (value, key) pair. The index of [1] is used to get the corresponding key


回答 14

# python 
d={320:1, 321:0, 322:3}
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys())
  321
# python 
d={320:1, 321:0, 322:3}
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys())
  321

回答 15

这是你想要的?

d = dict()
d[15.0]='fifteen'
d[14.0]='fourteen'
d[14.5]='fourteenandhalf'

print d[min(d.keys())]

打印“十四”

Is this what you are looking for?

d = dict()
d[15.0]='fifteen'
d[14.0]='fourteen'
d[14.5]='fourteenandhalf'

print d[min(d.keys())]

Prints ‘fourteen’


__name__ ==“ __main__”是什么?

问题:__name__ ==“ __main__”是什么?

给定以下代码,该if __name__ == "__main__":是什么?

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

Given the following code, what does the if __name__ == "__main__": do?

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

回答 0

每当Python解释器读取源文件时,它都会做两件事:

  • 它设置了一些特殊变量,例如__name__,然后

  • 它执行文件中找到的所有代码。

让我们看看它是如何工作的,以及它与您关于__name__我们在Python脚本中经常看到的检查问题的关系。

代码样例

让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。假设以下文件位于foo.py

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

特殊变量

当Python交互程序读取源文件时,它首先定义一些特殊变量。在这种情况下,我们关心__name__变量。

当您的模块是主程序时

如果您将模块(源文件)作为主程序运行,例如

python foo.py

解释器将硬编码字符串赋值"__main__"__name__变量,即

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

当您的模块由另一个导入时

另一方面,假设其他模块是主程序,并且它将导入您的模块。这意味着在主程序中或主程序导入的某些其他模块中有这样的语句:

# Suppose this is in some other main program.
import foo

解释器将搜索您的foo.py文件(以及搜索其他一些变体),并在执行该模块之前,它将"foo"导入语句中的名称分配给__name__变量,即

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

执行模块的代码

设置特殊变量后,解释器一次执行一次语句,执行模块中的所有代码。您可能想要在代码示例侧面打开另一个窗口,以便您可以按照以下说明进行操作。

总是

  1. 它打印字符串"before import"(不带引号)。

  2. 它将加载math模块并将其分配给名为的变量math。这等效于替换import math为以下内容(请注意,这__import__是Python中的低级函数,它接受字符串并触发实际的导入):

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. 它输出字符串"before functionA"

  2. 它执行该def块,创建一个功能对象,然后将该功能对象分配给名为的变量functionA

  3. 它输出字符串"before functionB"

  4. 它执行第二个def块,创建另一个函数对象,然后将其分配给名为的变量functionB

  5. 它输出字符串"before __name__ guard"

仅当您的模块是主程序时

  1. 如果您的模块是主程序,那么它将看到__name__确实已将其设置为,"__main__"并且它将调用两个函数,分别输出字符串"Function A""Function B 10.0"

仅当您的模块由另一个导入时

  1. 相反)如果您的模块不是主程序,而是由另一个程序导入的,__name__则将为"foo",不是"__main__",它将跳过if语句的主体。

总是

  1. "after __name__ guard"在两种情况下都将打印字符串。

摘要

总而言之,这是两种情况下的打印内容:

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

为什么这样工作?

您自然会想知道为什么有人会想要这个。好吧,有时您想编写一个.py文件,该文件既可以被其他程序和/或模块用作模块,也可以作为主程序本身运行。例子:

  • 您的模块是一个库,但是您希望有一个脚本模式,在其中运行一些单元测试或演示。

  • 您的模块仅用作主程序,但是它具有一些单元测试,并且测试框架通过导入.py文件(如脚本)并运行特殊的测试功能来工作。您不希望它只是因为正在导入模块而尝试运行脚本。

  • 您的模块主要用作主程序,但它也为高级用户提供了程序员友好的API。

除了这些示例之外,可以优雅地用Python运行脚本只是设置一些魔术变量并导入脚本。“运行”脚本是导入脚本模块的副作用。

思想的食物

  • 问题:我可以有多个__name__检查块吗?答:这样做很奇怪,但是这种语言不会阻止您。

  • 假设以下内容在中foo2.py。如果python foo2.py在命令行上说会怎样?为什么?

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • 现在,弄清楚如果删除__name__签入会发生什么foo3.py
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • 当用作脚本时,它将做什么?当作为模块导入时?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

Whenever the Python interpreter reads a source file, it does two things:

  • it sets a few special variables like __name__, and then

  • it executes all of the code found in the file.

Let’s see how this works and how it relates to your question about the __name__ checks we always see in Python scripts.

Code Sample

Let’s use a slightly different code sample to explore how imports and scripts work. Suppose the following is in a file called foo.py.

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

Special Variables

When the Python interpeter reads a source file, it first defines a few special variables. In this case, we care about the __name__ variable.

When Your Module Is the Main Program

If you are running your module (the source file) as the main program, e.g.

python foo.py

the interpreter will assign the hard-coded string "__main__" to the __name__ variable, i.e.

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

When Your Module Is Imported By Another

On the other hand, suppose some other module is the main program and it imports your module. This means there’s a statement like this in the main program, or in some other module the main program imports:

# Suppose this is in some other main program.
import foo

The interpreter will search for your foo.py file (along with searching for a few other variants), and prior to executing that module, it will assign the name "foo" from the import statement to the __name__ variable, i.e.

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Executing the Module’s Code

After the special variables are set up, the interpreter executes all the code in the module, one statement at a time. You may want to open another window on the side with the code sample so you can follow along with this explanation.

Always

  1. It prints the string "before import" (without quotes).

  2. It loads the math module and assigns it to a variable called math. This is equivalent to replacing import math with the following (note that __import__ is a low-level function in Python that takes a string and triggers the actual import):

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. It prints the string "before functionA".

  2. It executes the def block, creating a function object, then assigning that function object to a variable called functionA.

  3. It prints the string "before functionB".

  4. It executes the second def block, creating another function object, then assigning it to a variable called functionB.

  5. It prints the string "before __name__ guard".

Only When Your Module Is the Main Program

  1. If your module is the main program, then it will see that __name__ was indeed set to "__main__" and it calls the two functions, printing the strings "Function A" and "Function B 10.0".

Only When Your Module Is Imported by Another

  1. (instead) If your module is not the main program but was imported by another one, then __name__ will be "foo", not "__main__", and it’ll skip the body of the if statement.

Always

  1. It will print the string "after __name__ guard" in both situations.

Summary

In summary, here’s what’d be printed in the two cases:

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

Why Does It Work This Way?

You might naturally wonder why anybody would want this. Well, sometimes you want to write a .py file that can be both used by other programs and/or modules as a module, and can also be run as the main program itself. Examples:

  • Your module is a library, but you want to have a script mode where it runs some unit tests or a demo.

  • Your module is only used as a main program, but it has some unit tests, and the testing framework works by importing .py files like your script and running special test functions. You don’t want it to try running the script just because it’s importing the module.

  • Your module is mostly used as a main program, but it also provides a programmer-friendly API for advanced users.

Beyond those examples, it’s elegant that running a script in Python is just setting up a few magic variables and importing the script. “Running” the script is a side effect of importing the script’s module.

Food for Thought

  • Question: Can I have multiple __name__ checking blocks? Answer: it’s strange to do so, but the language won’t stop you.

  • Suppose the following is in foo2.py. What happens if you say python foo2.py on the command-line? Why?

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • Now, figure out what will happen if you remove the __name__ check in foo3.py:
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • What will this do when used as a script? When imported as a module?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

回答 1

通过将脚本作为命令传递给Python解释器来运行脚本时,

python myscript.py

缩进级别为0的所有代码都将执行。可以很好地定义已定义的函数和类,但是不会运行任何代码。与其他语言不同,它没有main()自动运行的功能-main()函数隐式是顶层的所有代码。

在这种情况下,顶级代码是一个if块。 __name__是一个内置变量,其结果为当前模块的名称。但是,如果模块直接运行(如上myscript.py所示),则将__name__其设置为string "__main__"。因此,您可以通过测试来测试您的脚本是直接运行还是通过其他方式导入

if __name__ == "__main__":
    ...

如果将脚本导入另一个模块,则将导入其各种功能和类定义,并执行其顶层代码,但是上述if子句的then-body中的代码将不会运行,因为条件是没见过。作为一个基本示例,请考虑以下两个脚本:

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

现在,如果您将解释器调用为

python one.py

输出将是

top-level in one.py
one.py is being run directly

如果two.py改为运行:

python two.py

你得到

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

因此,当模块one加载时,其__name__等于"one"而不是"__main__"

When your script is run by passing it as a command to the Python interpreter,

python myscript.py

all of the code that is at indentation level 0 gets executed. Functions and classes that are defined are, well, defined, but none of their code gets run. Unlike other languages, there’s no main() function that gets run automatically – the main() function is implicitly all the code at the top level.

In this case, the top-level code is an if block. __name__ is a built-in variable which evaluates to the name of the current module. However, if a module is being run directly (as in myscript.py above), then __name__ instead is set to the string "__main__". Thus, you can test whether your script is being run directly or being imported by something else by testing

if __name__ == "__main__":
    ...

If your script is being imported into another module, its various function and class definitions will be imported and its top-level code will be executed, but the code in the then-body of the if clause above won’t get run as the condition is not met. As a basic example, consider the following two scripts:

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

Now, if you invoke the interpreter as

python one.py

The output will be

top-level in one.py
one.py is being run directly

If you run two.py instead:

python two.py

You get

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

Thus, when module one gets loaded, its __name__ equals "one" instead of "__main__".


回答 2

__name__变量(imho)的最简单解释如下:

创建以下文件。

# a.py
import b

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

运行它们将为您提供以下输出:

$ python a.py
Hello World from b!

如您所见,导入模块时,Python globals()['__name__']在此模块中设置模块的名称。同样,在导入时,模块中的所有代码都在运行。由于if语句评估到False这一部分没有执行。

$ python b.py
Hello World from __main__!
Hello World again from __main__!

如您所见,执行文件时,Python globals()['__name__']在该文件中将设置为"__main__"。这次,该if语句求值True并正在运行。

The simplest explanation for the __name__ variable (imho) is the following:

Create the following files.

# a.py
import b

and

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

Running them will get you this output:

$ python a.py
Hello World from b!

As you can see, when a module is imported, Python sets globals()['__name__'] in this module to the module’s name. Also, upon import all the code in the module is being run. As the if statement evaluates to False this part is not executed.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

As you can see, when a file is executed, Python sets globals()['__name__'] in this file to "__main__". This time, the if statement evaluates to True and is being run.


回答 3

怎么if __name__ == "__main__":办?

概述基础知识:

  • __name__在作为程序入口点的模块中,全局变量为'__main__'。否则,这就是您导入模块的名称。

  • 因此,if仅当模块是程序的入口点时,该块下的代码才会运行。

  • 它允许模块中的代码可由其他模块导入,而无需在导入时执行下面的代码块。


我们为什么需要这个?

开发和测试您的代码

假设您正在编写旨在用作模块的Python脚本:

def do_important():
    """This function does something very important"""

可以通过在底部添加此函数调用测试模块:

do_important()

并使用以下命令运行它(在命令提示符下):

~$ python important.py

问题

但是,如果要将模块导入到另一个脚本:

import important

在导入时,do_important将调用该函数,因此您可能会do_important()在底部注释掉函数调用。

# do_important() # I must remember to uncomment to execute this!

然后,您必须记住是否已注释掉测试函数调用。这种额外的复杂性将意味着您可能会忘记,从而使您的开发过程更加麻烦。

更好的方法

__name__变量指向当前Python解释器所在的命名空间。

在导入的模块中,它是该模块的名称。

但是在主模块(或交互式Python会话,即解释器的Read,Eval,Print Loop或REPL)中,您正在运行其所有内容"__main__"

因此,如果您在执行之前进行检查:

if __name__ == "__main__":
    do_important()

有了以上内容,您的代码将仅在以主模块运行(或从另一个脚本有意调用)时执行。

更好的方法

不过,有一种Python方式可以对此进行改进。

如果我们想从模块外部运行该业务流程怎么办?

如果我们放上我们想在开发和测试这样的函数时使用的代码,然后在执行以下操作时'__main__'立即进行检查:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

现在,我们在模块末尾具有最终功能,如果我们将模块作为主要模块运行,则该功能将运行。

它将允许在不运行该main功能的情况下将该模块及其功能和类导入其他脚本,并且还将允许从其他'__main__'模块运行时调用该模块(及其功能和类),即

import important
important.main()

这个习语也可以在Python文档中的__main__模块说明中找到。该文本指出:

此模块表示解释程序的主程序在其中执行的(否则为匿名)范围-从标准输入,脚本文件或交互式提示中读取的命令。在这种环境中,惯用的“条件脚本”节使脚本运行:

if __name__ == '__main__':
    main()

What does the if __name__ == "__main__": do?

To outline the basics:

  • The global variable, __name__, in the module that is the entry point to your program, is '__main__'. Otherwise, it’s the name you import the module by.

  • So, code under the if block will only run if the module is the entry point to your program.

  • It allows the code in the module to be importable by other modules, without executing the code block beneath on import.


Why do we need this?

Developing and Testing Your Code

Say you’re writing a Python script designed to be used as a module:

def do_important():
    """This function does something very important"""

You could test the module by adding this call of the function to the bottom:

do_important()

and running it (on a command prompt) with something like:

~$ python important.py

The Problem

However, if you want to import the module to another script:

import important

On import, the do_important function would be called, so you’d probably comment out your function call, do_important(), at the bottom.

# do_important() # I must remember to uncomment to execute this!

And then you’ll have to remember whether or not you’ve commented out your test function call. And this extra complexity would mean you’re likely to forget, making your development process more troublesome.

A Better Way

The __name__ variable points to the namespace wherever the Python interpreter happens to be at the moment.

Inside an imported module, it’s the name of that module.

But inside the primary module (or an interactive Python session, i.e. the interpreter’s Read, Eval, Print Loop, or REPL) you are running everything from its "__main__".

So if you check before executing:

if __name__ == "__main__":
    do_important()

With the above, your code will only execute when you’re running it as the primary module (or intentionally call it from another script).

An Even Better Way

There’s a Pythonic way to improve on this, though.

What if we want to run this business process from outside the module?

If we put the code we want to exercise as we develop and test in a function like this and then do our check for '__main__' immediately after:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

We now have a final function for the end of our module that will run if we run the module as the primary module.

It will allow the module and its functions and classes to be imported into other scripts without running the main function, and will also allow the module (and its functions and classes) to be called when running from a different '__main__' module, i.e.

import important
important.main()

This idiom can also be found in the Python documentation in an explanation of the __main__ module. That text states:

This module represents the (otherwise anonymous) scope in which the interpreter’s main program executes — commands read either from standard input, from a script file, or from an interactive prompt. It is this environment in which the idiomatic “conditional script” stanza causes a script to run:

if __name__ == '__main__':
    main()

回答 4

if __name__ == "__main__"是使用(例如)命令从(例如)命令行运行脚本时运行的部分python myscript.py

if __name__ == "__main__" is the part that runs when the script is run from (say) the command line using a command like python myscript.py.


回答 5

怎么if __name__ == "__main__":办?

__name__是存在于所有命名空间中的全局变量(在Python中,global实际上是在模块级别上表示)。它通常是模块的名称(作为str类型)。

但是,作为唯一的特殊情况,无论您运行什么Python进程,如mycode.py:

python mycode.py

否则将匿名全局命名空间的值分配'__main__'__name__

因此,包括最后几行

if __name__ == '__main__':
    main()
  • 在mycode.py脚本的末尾,
  • 当它是由Python进程运行的主要入口点模块时,

将导致脚本的唯一定义main函数运行。

使用此构造的另一个好处:如果程序决定何时,还可以将代码作为模块导入另一个脚本中,然后运行main函数。

import mycode
# ... any amount of other code
mycode.main()

What does if __name__ == "__main__": do?

__name__ is a global variable (in Python, global actually means on the module level) that exists in all namespaces. It is typically the module’s name (as a str type).

As the only special case, however, in whatever Python process you run, as in mycode.py:

python mycode.py

the otherwise anonymous global namespace is assigned the value of '__main__' to its __name__.

Thus, including the final lines

if __name__ == '__main__':
    main()
  • at the end of your mycode.py script,
  • when it is the primary, entry-point module that is run by a Python process,

will cause your script’s uniquely defined main function to run.

Another benefit of using this construct: you can also import your code as a module in another script and then run the main function if and when your program decides:

import mycode
# ... any amount of other code
mycode.main()

回答 6

在这里,有关代码的“如何”的机制有很多不同之处,但是对我而言,直到我理解了“为什么”之后,才有意义。这对新程序员特别有用。

取得文件“ ab.py”:

def a():
    print('A function in ab file');
a()

还有第二个文件“ xy.py”:

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

这段代码实际上在做什么?

当你执行时xy.py,你import ab。import语句在导入时立即运行模块,因此ab的操作要在的其余部分之前执行xy。完成后ab,继续xy

解释器会跟踪运行哪个脚本__name__。当您运行脚本时(无论您使用什么名称),解释器都会调用它"__main__",使其成为运行外部脚本后返回的主脚本或“主”脚本。

从该"__main__"脚本调用的任何其他脚本都被分配了其文件名作为其文件名__name__(例如__name__ == "ab.py")。因此,线if __name__ == "__main__":是解释程序的测试,以确定它是否正在解释/解析最初执行的“ home”脚本,或者它是否正在临时窥视另一个(外部)脚本。这使程序员可以灵活地让脚本在直接执行与在外部执行之间有所不同。

让我们逐步看一下上面的代码,以了解发生了什么,首先关注未缩进的行及其在脚本中出现的顺序。请记住,函数-或def-块在被调用之前不会自行执行任何操作。如果自言自语,口译员可能会说:

  • 打开xy.py作为“主”文件;"__main__"__name__变量中调用它。
  • 使用导入并打开文件__name__ == "ab.py"
  • 哦,有功能。我会记住的。
  • 好的,功能a();我才知道 打印’ ab文件中函数 ‘。
  • 文件结尾;回到"__main__"
  • 哦,有功能。我会记住的。
  • 另一个。
  • 功能x(); 好,打印“ 外围任务:可能在其他项目中有用 ”。
  • 这是什么?一个if声明。好了,条件已经满足(变量__name__已设置为"__main__"),所以我将输入main()函数并打印’ main函数:这是操作所在

最下面的两行表示:“如果这是"__main__"‘或’home’脚本,则执行名为main()“ 的功能。这就是为什么您会def main():在顶部看到一个块的原因,其中包含脚本功能的主要流程。

为什么要实施呢?

还记得我之前说的有关导入语句的内容吗?导入模块时,它不仅会“识别”它并等待进一步的指令-实际上会运行脚本中包含的所有可执行操作。因此,将脚本的内容main()有效地隔离到函数中,将其隔离,以便在被另一个脚本导入时不会立即运行。

同样,会有exceptions,但是通常的做法是main()通常不会在外部调用它。因此,您可能想知道又一件事:如果我们不调用main(),为什么还要调用脚本呢?这是因为许多人使用独立的函数来构造脚本,这些独立的函数旨在独立于文件中的其余代码运行。然后在脚本正文中的其他位置调用它们。这使我想到了这一点:

但是代码没有它就可以工作

恩,那就对了。可以从函数未包含的内联脚本中调用这些单独的main()函数。如果您习惯了(就像我在编程的早期学习阶段那样)构建可以完全满足您需要的内联脚本,并且如果您再次需要该操作,那么您将尝试再次找出它。嗯,您不习惯这种代码的内部结构,因为它的构建更加复杂并且阅读起来也不那么直观。

但这是一个脚本,可能无法从外部调用其功能,因为如果执行该脚本,它将立即开始计算和分配变量。而且,如果您想重用某个功能,则新脚本与旧脚本的关联性可能会很高,以至于变量会冲突。

在拆分独立功能时,您可以通过将其调用到另一个脚本中来重用以前的工作。例如,“ example.py”可能会导入“ xy.py”并调用x(),从而利用“ xy.py” 中的“ x”功能。(也许是将给定文本字符串的第三个单词大写;从数字列表中创建一个NumPy数组并对其进行平方;或者对3D表面进行趋势处理。这种可能性是无限的。)

(顺便说一句,这个问题包含@kindall的答案,它最终帮助我理解了-原因,而不是方法。不幸的是,它被标记为与副本的副本,我认为这是错误的。)

There are lots of different takes here on the mechanics of the code in question, the “How”, but for me none of it made sense until I understood the “Why”. This should be especially helpful for new programmers.

Take file “ab.py”:

def a():
    print('A function in ab file');
a()

And a second file “xy.py”:

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

What is this code actually doing?

When you execute xy.py, you import ab. The import statement runs the module immediately on import, so ab‘s operations get executed before the remainder of xy‘s. Once finished with ab, it continues with xy.

The interpreter keeps track of which scripts are running with __name__. When you run a script – no matter what you’ve named it – the interpreter calls it "__main__", making it the master or ‘home’ script that gets returned to after running an external script.

Any other script that’s called from this "__main__" script is assigned its filename as its __name__ (e.g., __name__ == "ab.py"). Hence, the line if __name__ == "__main__": is the interpreter’s test to determine if it’s interpreting/parsing the ‘home’ script that was initially executed, or if it’s temporarily peeking into another (external) script. This gives the programmer flexibility to have the script behave differently if it’s executed directly vs. called externally.

Let’s step through the above code to understand what’s happening, focusing first on the unindented lines and the order they appear in the scripts. Remember that function – or def – blocks don’t do anything by themselves until they’re called. What the interpreter might say if mumbled to itself:

  • Open xy.py as the ‘home’ file; call it "__main__" in the __name__ variable.
  • Import and open file with the __name__ == "ab.py".
  • Oh, a function. I’ll remember that.
  • Ok, function a(); I just learned that. Printing ‘A function in ab file‘.
  • End of file; back to "__main__"!
  • Oh, a function. I’ll remember that.
  • Another one.
  • Function x(); ok, printing ‘peripheral task: might be useful in other projects‘.
  • What’s this? An if statement. Well, the condition has been met (the variable __name__ has been set to "__main__"), so I’ll enter the main() function and print ‘main function: this is where the action is‘.

The bottom two lines mean: “If this is the "__main__" or ‘home’ script, execute the function called main()“. That’s why you’ll see a def main(): block up top, which contains the main flow of the script’s functionality.

Why implement this?

Remember what I said earlier about import statements? When you import a module it doesn’t just ‘recognize’ it and wait for further instructions – it actually runs all the executable operations contained within the script. So, putting the meat of your script into the main() function effectively quarantines it, putting it in isolation so that it won’t immediately run when imported by another script.

Again, there will be exceptions, but common practice is that main() doesn’t usually get called externally. So you may be wondering one more thing: if we’re not calling main(), why are we calling the script at all? It’s because many people structure their scripts with standalone functions that are built to be run independent of the rest of the code in the file. They’re then later called somewhere else in the body of the script. Which brings me to this:

But the code works without it

Yes, that’s right. These separate functions can be called from an in-line script that’s not contained inside a main() function. If you’re accustomed (as I am, in my early learning stages of programming) to building in-line scripts that do exactly what you need, and you’ll try to figure it out again if you ever need that operation again … well, you’re not used to this kind of internal structure to your code, because it’s more complicated to build and it’s not as intuitive to read.

But that’s a script that probably can’t have its functions called externally, because if it did it would immediately start calculating and assigning variables. And chances are if you’re trying to re-use a function, your new script is related closely enough to the old one that there will be conflicting variables.

In splitting out independent functions, you gain the ability to re-use your previous work by calling them into another script. For example, “example.py” might import “xy.py” and call x(), making use of the ‘x’ function from “xy.py”. (Maybe it’s capitalizing the third word of a given text string; creating a NumPy array from a list of numbers and squaring them; or detrending a 3D surface. The possibilities are limitless.)

(As an aside, this question contains an answer by @kindall that finally helped me to understand – the why, not the how. Unfortunately it’s been marked as a duplicate of this one, which I think is a mistake.)


回答 7

当我们的模块(M.py)中有某些语句时,我们希望在将其作为main(而不是导入)运行时执行该语句,我们可以将这些语句(测试用例,打印语句)放在此if块下。

默认情况下(当模块作为主模块运行而不是导入时),该__name__变量设置为"__main__",导入时,该__name__变量将获得一个不同的值,很可能是模块的名称('M')。这有助于一起运行模块的不同变体,分离其特定的输入和输出语句,以及是否存在测试用例。

简而言之,使用此’ if __name__ == "main"‘块可防止在导入模块时运行(某些)代码。

When there are certain statements in our module (M.py) we want to be executed when it’ll be running as main (not imported), we can place those statements (test-cases, print statements) under this if block.

As by default (when module running as main, not imported) the __name__ variable is set to "__main__", and when it’ll be imported the __name__ variable will get a different value, most probably the name of the module ('M'). This is helpful in running different variants of a modules together, and separating their specific input & output statements and also if there are any test-cases.

In short, use this ‘if __name__ == "main" ‘ block to prevent (certain) code from being run when the module is imported.


回答 8

简而言之,__name__是为每个脚本定义的变量,用于定义脚本是作为主模块运行还是作为导入模块运行。

因此,如果我们有两个脚本;

#script1.py
print "Script 1's name: {}".format(__name__)

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

执行script1的输出是

Script 1's name: __main__

执行script2的输出是:

Script1's name is script1
Script 2's name: __main__

如你看到的, __name__告诉我们哪个代码是“主”模块。这很棒,因为您可以编写代码,而不必担心C / C ++中的结构性问题,在这种情况下,如果文件未实现“ main”功能,则无法将其编译为可执行文件,如果可以,然后它不能用作库。

假设您编写的Python脚本功能出色,并实现了许多对其他用途有用的功能。如果要使用它们,我可以导入您的脚本并使用它们而无需执行您的程序(假设您的代码仅在if __name__ == "__main__":上下文中执行 )。而在C / C ++中,您将必须将这些部分分成一个单独的模块,然后再包含文件。如下图所示;

箭头是导入链接。对于三个试图包含先前模块代码的模块,有六个文件(九个,计算实现文件)和五个链接。除非将其专门编译为库,否则很难将其他代码包含到C项目中。现在将其描述为适用于Python:

您编写了一个模块,如果有人想使用您的代码,他们只需将其导入即可,并且__name__变量可以帮助将程序的可执行部分与库部分分开。

Put simply, __name__ is a variable defined for each script that defines whether the script is being run as the main module or it is being run as an imported module.

So if we have two scripts;

#script1.py
print "Script 1's name: {}".format(__name__)

and

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

The output from executing script1 is

Script 1's name: __main__

And the output from executing script2 is:

Script1's name is script1
Script 2's name: __main__

As you can see, __name__ tells us which code is the ‘main’ module. This is great, because you can just write code and not have to worry about structural issues like in C/C++, where, if a file does not implement a ‘main’ function then it cannot be compiled as an executable and if it does, it cannot then be used as a library.

Say you write a Python script that does something great and you implement a boatload of functions that are useful for other purposes. If I want to use them I can just import your script and use them without executing your program (given that your code only executes within the if __name__ == "__main__": context). Whereas in C/C++ you would have to portion out those pieces into a separate module that then includes the file. Picture the situation below;

The arrows are import links. For three modules each trying to include the previous modules code there are six files (nine, counting the implementation files) and five links. This makes it difficult to include other code into a C project unless it is compiled specifically as a library. Now picture it for Python:

You write a module, and if someone wants to use your code they just import it and the __name__ variable can help to separate the executable portion of the program from the library part.


回答 9

让我们以更抽象的方式看一下答案:

假设我们在以下代码中x.py

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

块A和B,当我们正在运行的运行x.py

但是,y.py例如,当我们运行另一个模块时,仅运行块A(而不运行B),例如,在其中x.py导入了代码并从那里运行代码(例如,当x.py从中调用in函数时y.py)。

Let’s look at the answer in a more abstract way:

Suppose we have this code in x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

Blocks A and B are run when we are running x.py.

But just block A (and not B) is run when we are running another module, y.py for example, in which x.py is imported and the code is run from there (like when a function in x.py is called from y.py).


回答 10

交互式运行Python时,会为本地__name__变量分配的值__main__。同样,当您从命令行执行Python模块,而不是将其导入另一个模块时,__name__属性被分配为的值__main__,而不是模块的实际名称。通过这种方式,模块可以查看自己的__name__值来自行确定如何使用它们,无论是作为对另一个程序的支持还是作为从命令行执行的主要应用程序。因此,以下习语在Python模块中非常普遍:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.

When you run Python interactively the local __name__ variable is assigned a value of __main__. Likewise, when you execute a Python module from the command line, rather than importing it into another module, its __name__ attribute is assigned a value of __main__, rather than the actual name of the module. In this way, modules can look at their own __name__ value to determine for themselves how they are being used, whether as support for another program or as the main application executed from the command line. Thus, the following idiom is quite common in Python modules:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.

回答 11

考虑:

if __name__ == "__main__":
    main()

它检查__name__Python脚本的属性是否为"__main__"。换句话说,如果程序本身已执行,则属性将为__main__,因此程序将被执行(在这种情况下,main()函数)。

但是,如果模块使用了您的Python脚本,if则将执行该语句之外的任何代码,因此if \__name__ == "\__main__"仅用于检查该程序是否用作模块,从而决定是否运行该代码。

Consider:

if __name__ == "__main__":
    main()

It checks if the __name__ attribute of the Python script is "__main__". In other words, if the program itself is executed, the attribute will be __main__, so the program will be executed (in this case the main() function).

However, if your Python script is used by a module, any code outside of the if statement will be executed, so if \__name__ == "\__main__" is used just to check if the program is used as a module or not, and therefore decides whether to run the code.


回答 12

在解释任何有关if __name__ == '__main__'它的内容之前,重要的是要了解它是什么__name__以及它做什么。

什么__name__

__name__DunderAlias-可以认为是全局变量(可从模块访问),并且与相似global

它是type(__name__)(yielding <class 'str'>)指示的字符串(如上所述),并且是Python 3Python 2版本的内置标准。

哪里:

它不仅可以在脚本中使用,而且可以在解释器和模块/包中找到。

口译员:

>>> print(__name__)
__main__
>>>

脚本:

test_file.py

print(__name__)

导致 __main__

模块或包装:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

导致 somefile

请注意,在包或模块中使用时,使用__name__文件名。没有给出实际模块或包路径的路径,但是具有自己的DunderAlias__file__,因此可以这一点。

您应该看到,where __name__,它总是在其中返回主文件(或程序)__main__,并且如果它是一个模块/程序包,或者正在运行其他Python脚本的任何东西,则将在其中返回文件名。起源于。

实践:

作为变量意味着它的值可以被覆盖(“可以”并不意味着“应该”),覆盖的值__name__将导致缺乏可读性。因此,无论出于任何原因都不要这样做。如果您需要一个变量,请定义一个新变量。

始终假定__name__为be 的值__main__或文件名。再次更改此默认值将引起更多混乱,这会带来好处,并进一步导致问题。

例:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

通常,将if __name__ == '__main__'in 包含在脚本中被认为是一种好习惯。

现在回答if __name__ == '__main__'

现在我们知道__name__事物的行为变得更加清晰:

一个if是包含的代码块,如果给定的值是true,将执行流控制语句。我们已经看到这__name__可以采取
__main__导入的文件名导入的文件名。

这意味着,如果__name__等于,__main__则该文件必须是主文件并且必须实际上正在运行(或者它是解释器),而不是导入脚本的模块或包。

如果确实__name__采用了值,__main__那么该代码块中的所有内容都将执行。

这告诉我们,如果正在运行的文件是主文件(或者直接从解释器运行),则必须执行该条件。如果它是一个包,则不应该,并且值不应该是__main__

模块:

__name__ 也可以在模块中使用以定义模块名称

变体:

也可以使用进行其他一些不太常见但有用的事情__name__,我将在这里展示一些:

仅当文件是模块或软件包时才执行:

if __name__ != '__main__':
    # Do some useful things 

如果文件是主文件,则运行一个条件,如果文件不是主文件,则运行另一个条件:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

您也可以使用它在软件包和模块上提供可运行的帮助功能/实用程序,而无需精心使用库。

它还允许模块作为主脚本从命令行运行,这也非常有用。

Before explaining anything about if __name__ == '__main__' it is important to understand what __name__ is and what it does.

What is __name__?

__name__ is a DunderAlias – can be thought of as a global variable (accessible from modules) and works in a similar way to global.

It is a string (global as mentioned above) as indicated by type(__name__) (yielding <class 'str'>), and is an inbuilt standard for both Python 3 and Python 2 versions.

Where:

It can not only be used in scripts but can also be found in both the interpreter and modules/packages.

Interpreter:

>>> print(__name__)
__main__
>>>

Script:

test_file.py:

print(__name__)

Resulting in __main__

Module or package:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Resulting in somefile

Notice that when used in a package or module, __name__ takes the name of the file. The path of the actual module or package path is not given, but has its own DunderAlias __file__, that allows for this.

You should see that, where __name__, where it is the main file (or program) will always return __main__, and if it is a module/package, or anything that is running off some other Python script, will return the name of the file where it has originated from.

Practice:

Being a variable means that it’s value can be overwritten (“can” does not mean “should”), overwriting the value of __name__ will result in a lack of readability. So do not do it, for any reason. If you need a variable define a new variable.

It is always assumed that the value of __name__ to be __main__ or the name of the file. Once again changing this default value will cause more confusion that it will do good, causing problems further down the line.

example:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

It is considered good practice in general to include the if __name__ == '__main__' in scripts.

Now to answer if __name__ == '__main__':

Now we know the behaviour of __name__ things become clearer:

An if is a flow control statement that contains the block of code will execute if the value given is true. We have seen that __name__ can take either __main__ or the file name it has been imported from.

This means that if __name__ is equal to __main__ then the file must be the main file and must actually be running (or it is the interpreter), not a module or package imported into the script.

If indeed __name__ does take the value of __main__ then whatever is in that block of code will execute.

This tells us that if the file running is the main file (or you are running from the interpreter directly) then that condition must execute. If it is a package then it should not, and the value will not be __main__.

Modules:

__name__ can also be used in modules to define the name of a module

Variants:

It is also possible to do other, less common but useful things with __name__, some I will show here:

Executing only if the file is a module or package:

if __name__ != '__main__':
    # Do some useful things 

Running one condition if the file is the main one and another if it is not:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

You can also use it to provide runnable help functions/utilities on packages and modules without the elaborate use of libraries.

It also allows modules to be run from the command line as main scripts, which can be also very useful.


回答 13

我认为最好是深入浅出的答案:

__name__:Python中的每个模块都有一个称为的特殊属性__name__。它是一个内置变量,返回模块的名称。

__main__:与其他编程语言一样,Python也具有执行入口点,即main。'__main__' 是执行顶级代码的作用域的名称。基本上,您有两种使用Python模块的方式:直接将其作为脚本运行,或将其导入。当模块作为脚本运行时,其__name__设置为__main__

因此,当模块作为主程序运行时,该__name__属性的值将设置为__main__。否则,的值将__name__ 设置为包含模块的名称。

I think it’s best to break the answer in depth and in simple words:

__name__: Every module in Python has a special attribute called __name__. It is a built-in variable that returns the name of the module.

__main__: Like other programming languages, Python too has an execution entry point, i.e., main. '__main__' is the name of the scope in which top-level code executes. Basically you have two ways of using a Python module: Run it directly as a script, or import it. When a module is run as a script, its __name__ is set to __main__.

Thus, the value of the __name__ attribute is set to __main__ when the module is run as the main program. Otherwise the value of __name__ is set to contain the name of the module.


回答 14

这是从命令行调用Python文件时的特殊功能。通常用于调用“ main()”函数或执行其他适当的启动代码,例如命令行参数处理。

它可以用几种方式编写。另一个是:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说您应该在生产代码中使用它,但是它可以说明没有什么“魔术” if __name__ == '__main__'。在Python文件中调用主函数是一个很好的约定。

It is a special for when a Python file is called from the command line. This is typically used to call a “main()” function or execute other appropriate startup code, like commandline arguments handling for instance.

It could be written in several ways. Another is:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

I am not saying you should use this in production code, but it serves to illustrate that there is nothing “magical” about if __name__ == '__main__'. It is a good convention for invoking a main function in Python files.


回答 15

系统(Python解释器)为源文件(模块)提供了许多变量。您可以随时获取它们的值,因此,让我们关注__name__变量/属性:

当Python加载源代码文件时,它将执行在其中找到的所有代码。(请注意,它不会调用文件中定义的所有方法和函数,但会定义它们。)

但是,在解释器执行源代码文件之前,它会为该文件定义一些特殊的变量。__名称__是Python为每个源代码文件自动定义的那些特殊变量之一。

如果Python正在将此源代码文件作为主程序加载(即,您运行的文件),那么它将为此文件设置特殊的__name__变量,使其具有值“ __main__”

如果是从另一个模块导入的,则将__name__设置为该模块的名称。

因此,在部分示例中:

if __name__ == "__main__":
   lock = thread.allocate_lock()
   thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
   thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

表示代码块:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

仅当您直接运行模块时才会执行;如果另一个模块正在调用/导入该代码块,则该代码块将不会执行,因为__name__的值在该特定实例中将不等于“ main ”。

希望这会有所帮助。

There are a number of variables that the system (Python interpreter) provides for source files (modules). You can get their values anytime you want, so, let us focus on the __name__ variable/attribute:

When Python loads a source code file, it executes all of the code found in it. (Note that it doesn’t call all of the methods and functions defined in the file, but it does define them.)

Before the interpreter executes the source code file though, it defines a few special variables for that file; __name__ is one of those special variables that Python automatically defines for each source code file.

If Python is loading this source code file as the main program (i.e. the file you run), then it sets the special __name__ variable for this file to have a value “__main__”.

If this is being imported from another module, __name__ will be set to that module’s name.

So, in your example in part:

if __name__ == "__main__":
   lock = thread.allocate_lock()
   thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
   thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

means that the code block:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

will be executed only when you run the module directly; the code block will not execute if another module is calling/importing it because the value of __name__ will not equal to “main” in that particular instance.

Hope this helps out.


回答 16

if __name__ == "__main__": 基本上是顶级脚本环境,它指定了解释器(“我首先执行的优先级最高”)。

'__main__'是执行顶级代码的作用域的名称。从标准输入,脚本或交互式提示中读取时,模块的__name__设置等于'__main__'

if __name__ == "__main__":
    # Execute only if run as a script
    main()

if __name__ == "__main__": is basically the top-level script environment, and it specifies the interpreter that (‘I have the highest priority to be executed first’).

'__main__' is the name of the scope in which top-level code executes. A module’s __name__ is set equal to '__main__' when read from standard input, a script, or from an interactive prompt.

if __name__ == "__main__":
    # Execute only if run as a script
    main()

回答 17

在本页的所有答案中,我都读了很多东西。我想说的是,如果您知道这件事,那么您肯定会理解这些答案,否则,您仍然会感到困惑。

简而言之,您需要了解以下几点:

  1. import a 操作实际上会运行所有可以在“ a”中运行的内容

  2. 由于第1点,导入时可能不希望所有内容都在“ a”中运行

  3. 为了解决第2点的问题,python允许您进行条件检查

  4. __name__是所有.py模块中的隐式变量;当a.py被导入,的值__name__a.py模块设置为它的文件名“ a“; 当a.py直接使用运行“ python a.py”,该装置a.py在所述入口点,则该值__name__a.py模块被设置为一个字符串__main__

  5. 基于python如何__name__为每个模块设置变量的机制,您知道如何实现第3点吗?答案很简单,对吧?把一个if条件:if __name__ == "__main__": ...; 您甚至可以__name__ == "a"根据您的功能需求放

python特殊之处很重要的一点是第4点!其余只是基本逻辑。

I’ve been reading so much throughout the answers on this page. I would say, if you know the thing, for sure you will understand those answers, otherwise, you are still confused.

To be short, you need to know several points:

  1. import a action actually runs all that can be ran in “a”

  2. Because of point 1, you may not want everything to be run in “a” when importing it

  3. To solve the problem in point 2, python allows you to put a condition check

  4. __name__ is an implicit variable in all .py modules; when a.py is imported, the value of __name__ of a.py module is set to its file name “a“; when a.py is run directly using “python a.py“, which means a.py is the entry point, then the value of __name__ of a.py module is set to a string __main__

  5. Based on the mechanism how python sets the variable __name__ for each module, do you know how to achieve point 3? The answer is fairly easy, right? Put a if condition: if __name__ == "__main__": ...; you can even put if __name__ == "a" depending on your functional need

The important thing that python is special at is point 4! The rest is just basic logic.


回答 18

考虑:

print __name__

上面的输出是__main__

if __name__ == "__main__":
  print "direct method"

上面的陈述是正确的,并显示“ direct method”。假设他们在另一个类中导入了该类,则不会打印“直接方法”,因为在导入时它将设置__name__ equal to "first model name"

Consider:

print __name__

The output for the above is __main__.

if __name__ == "__main__":
  print "direct method"

The above statement is true and prints “direct method”. Suppose if they imported this class in another class it doesn’t print “direct method” because, while importing, it will set __name__ equal to "first model name".


回答 19

您可以使该文件可用作脚本以及可导入模块

fibo.py(名为的模块fibo

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

参考:https : //docs.python.org/3.5/tutorial/modules.html

You can make the file usable as a script as well as an importable module.

fibo.py (a module named fibo)

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Reference: https://docs.python.org/3.5/tutorial/modules.html


回答 20

的原因

if __name__ == "__main__":
    main()

主要是为了避免由于直接导入代码而导致的导入锁定问题。你想运行,如果是直接调用的文件(这是main()__name__ == "__main__"情况),,但是如果导入了代码,则导入程序必须从真正的主模块输入代码,以避免导入锁定问题。

副作用是您自动登录支持多个入口点的方法。您可以使用main()作为入口点来运行程序,但不必如此。虽然setup.py期望main(),但其他工具使用备用入口点。例如,要将文件作为gunicorn进程运行,请定义app()函数而不是main()。与一样setup.pygunicorn导入您的代码,因此您不希望它在导入时执行任何操作(由于导入锁定问题)。

The reason for

if __name__ == "__main__":
    main()

is primarily to avoid the import lock problems that would arise from having code directly imported. You want main() to run if your file was directly invoked (that’s the __name__ == "__main__" case), but if your code was imported then the importer has to enter your code from the true main module to avoid import lock problems.

A side-effect is that you automatically sign on to a methodology that supports multiple entry points. You can run your program using main() as the entry point, but you don’t have to. While setup.py expects main(), other tools use alternate entry points. For example, to run your file as a gunicorn process, you define an app() function instead of a main(). Just as with setup.py, gunicorn imports your code so you don’t want it do do anything while it’s being imported (because of the import lock issue).


回答 21

该答案适用于学习Python的Java程序员。每个Java文件通常包含一个公共类。您可以通过两种方式使用该类:

  1. 从其他文件调用类。您只需要将其导入调用程序中即可。

  2. 出于测试目的,单独运行类。

对于后一种情况,该类应包含一个公共的静态void main()方法。在Python中,此目的由全局定义的标签实现'__main__'

This answer is for Java programmers learning Python. Every Java file typically contains one public class. You can use that class in two ways:

  1. Call the class from other files. You just have to import it in the calling program.

  2. Run the class stand alone, for testing purposes.

For the latter case, the class should contain a public static void main() method. In Python this purpose is served by the globally defined label '__main__'.


回答 22

if __name__ == '__main__': 仅当模块作为脚本调用时,才会执行以下代码。

例如,考虑以下模块my_test_module.py

# my_test_module.py

print('This is going to be printed out, no matter what')

if __name__ == '__main__':
    print('This is going to be printed out, only if user invokes the module as a script')

第一种可能性:导入my_test_module.py另一个模块

# main.py

import my_test_module

if __name__ == '__main__':
    print('Hello from main.py')

现在,如果您调用main.py

python main.py 

>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'

请注意,仅执行print()in中的顶级语句my_test_module


第二种可能性:my_test_module.py作为脚本调用

现在,如果您my_test_module.py以Python脚本运行,则两个print()语句都将执行:

python my_test_module.py

>>> 'This is going to be printed out, no matter what'
>>> 'This is going to be printed out, only if user invokes the module as a script'

The code under if __name__ == '__main__': will only be executed if the module is invoked as a script.

As an example consider the following module my_test_module.py:

# my_test_module.py

print('This is going to be printed out, no matter what')

if __name__ == '__main__':
    print('This is going to be printed out, only if user invokes the module as a script')

1st possibility: Import my_test_module.py in another module

# main.py

import my_test_module

if __name__ == '__main__':
    print('Hello from main.py')

Now if you invoke main.py:

python main.py 

>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'

Note that only the top-level print() statement in my_test_module is executed.


2nd possibility: Invoke my_test_module.py as a script

Now if you run my_test_module.py as a Python script, both print() statements will be exectued:

python my_test_module.py

>>> 'This is going to be printed out, no matter what'
>>> 'This is going to be printed out, only if user invokes the module as a script'

回答 23

python中的每个模块都有一个名为的属性__name____name__ attribute 的值__main__ 是直接运行模块时(例如)python my_module.py。否则(如您说的那样import my_module)的值__name__ 是模块的名称。

简短说明一下小例子。

#Script test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

我们可以直接执行为

python test.py  

输出量

Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

现在假设我们从其他脚本中调用上述脚本

#script external_calling.py

import test
print(test.apple)
test.hello_world()

print(test.__name__)

当您执行此

python external_calling.py

输出量

42
I am inside hello_world
test

所以,以上是自我解释,当你调用其他脚本的测试,如果循环__name__test.py不会执行。

Every module in python has a attribute called __name__. The value of __name__ attribute is __main__ when the module is run directly, like python my_module.py. Otherwise (like when you say import my_module) the value of __name__ is the name of the module.

Small example to explain in short.

#Script test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

We can execute this directly as

python test.py  

Output

Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

Now suppose we call above script from other script

#script external_calling.py

import test
print(test.apple)
test.hello_world()

print(test.__name__)

When you execute this

python external_calling.py

Output

42
I am inside hello_world
test

So, above is self explanatory that when you call test from other script, if loop __name__ in test.py will not execute.


回答 24

如果此.py文件是由其他.py文件导入的,则“ if语句”下的代码将不会执行。

如果此.py是python this_py.py在shell下运行,或在Windows中双击。“ if语句”下的代码将被执行。

通常是为了测试而编写的。

If this .py file are imported by other .py files, the code under “the if statement” will not be executed.

If this .py are run by python this_py.py under shell, or double clicked in Windows. the code under “the if statement” will be executed.

It is usually written for testing.


回答 25

如果python解释器正在运行特定模块,则__name__全局变量将具有值"__main__"

  def a():
      print("a")
  def b():
      print("b")

  if __name__ == "__main__": 

          print ("you can see me" )
          a()
  else: 

          print ("You can't see me")
          b()

运行此脚本打印件时,您可以看到我

一个

如果您导入此文件,请说A到文件B并执行文件B,则if __name__ == "__main__"文件A中的文件将变为false,因此将其打印出来 您看不到我

b

If the python interpreter is running a particular module then __name__ global variable will have value "__main__"

  def a():
      print("a")
  def b():
      print("b")

  if __name__ == "__main__": 

          print ("you can see me" )
          a()
  else: 

          print ("You can't see me")
          b()

When you run this script prints you can see me

a

If you import this file say A to file B and execute the file B then if __name__ == "__main__" in file A becomes false, so it prints You can’t see me

b


回答 26

所有答案都对功能进行了解释。但是,我将提供其用法的一个示例,这可能有助于进一步澄清该概念。

假设您有两个Python文件a.py和b.py。现在,a.py导入b.py。我们运行a.py文件,首先执行“ import b.py”代码。在其余的a.py代码运行之前,文件b.py中的代码必须完全运行。

在b.py代码中,有一些代码是该文件b.py独有的,我们不希望导入b.py文件的任何其他文件(b.py文件除外)来运行它。

这就是这行代码检查的内容。如果它是运行代码的主文件(即b.py)(在这种情况下不是)(运行a.py是主文件),则仅执行代码。

All the answers have pretty much explained the functionality. But I will provide one example of its usage which might help clearing out the concept further.

Assume that you have two Python files, a.py and b.py. Now, a.py imports b.py. We run the a.py file, where the “import b.py” code is executed first. Before the rest of the a.py code runs, the code in the file b.py must run completely.

In the b.py code there is some code that is exclusive to that file b.py and we don’t want any other file (other than b.py file), that has imported the b.py file, to run it.

So that is what this line of code checks. If it is the main file (i.e., b.py) running the code, which in this case it is not (a.py is the main file running), then only the code gets executed.


回答 27

创建一个文件a.py

print(__name__) # It will print out __main__

__name__始终等于__main__该文件直接运行时表明它是主文件。

在同一目录中创建另一个文件b.py

import a  # Prints a

运行。它将打印一个,即被导入文件的名称。

因此,为了显示同一文件的两种不同行为,这是一个常用的技巧:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly

Create a file, a.py:

print(__name__) # It will print out __main__

__name__ is always equal to __main__ whenever that file is run directly showing that this is the main file.

Create another file, b.py, in the same directory:

import a  # Prints a

Run it. It will print a, i.e., the name of the file which is imported.

So, to show two different behavior of the same file, this is a commonly used trick:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly

回答 28

如果name ==’ main ‘:

我们__name__ == '__main__':经常查看。

它检查是否正在导入模块。

换句话说,if仅当代码直接运行时,才会执行该块中的代码。这里的directly意思是not imported

让我们看一下使用打印模块名称的简单代码的作用:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

如果我们直接通过运行代码python test.py,则模块名称为__main__

call test()
test module name=__main__

if name == ‘main‘:

We see if __name__ == '__main__': quite often.

It checks if a module is being imported or not.

In other words, the code within the if block will be executed only when the code runs directly. Here directly means not imported.

Let’s see what it does using a simple code that prints the name of the module:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

If we run the code directly via python test.py, the module name is __main__:

call test()
test module name=__main__

回答 29

简而言之,就像C编程语言中的main函数一样,它是运行文件的入口。

Simply, it is the entry point to run the file, like the main function in the C programming language.


Python-patterns Python中的设计模式/习惯用法的集合

Python模式

Python中的设计模式和习惯用法的集合

当前模式

创作模式

图案 描述
abstract_factory 对特定工厂使用泛型函数
borg 实例间状态共享的单例
builder 生成器对象接收参数并返回构造的对象,而不是使用多个构造函数
factory 委托专用函数/方法来创建实例
lazy_evaluation Python中延迟计算的属性模式
pool 预实例化并维护一组相同类型的实例
prototype 为新实例使用原型的工厂和克隆(如果实例化成本较高)

结构模式

图案 描述
3-tier 数据<->业务逻辑<->表示分离(严格关系)
adapter 使用白名单使一个接口适应另一个接口
bridge 客户端-提供商中间人,用于软化界面更改
composite 允许客户端统一处理各个对象和组合
decorator 将功能与其他功能一起包装以影响输出
facade 使用一个类作为多个其他类的API
flyweight 透明地重用具有相似/相同状态的对象的现有实例
front_controller 进入应用程序的单个处理程序请求
mvc 模型<->视图<->控制器(非严格关系)
proxy 对象将操作传递给其他对象

行为模式

图案 描述
chain_of_responsibility 应用一系列连续的处理程序来尝试和处理数据
catalog 通用方法将根据构造参数调用不同的专用方法
chaining_method 继续回调下一个对象方法
command 捆绑命令和参数以供稍后调用
iterator 遍历容器并访问容器的元素
iterator(Alt.实施。) 遍历容器并访问容器的元素
mediator 知道如何连接其他对象并充当代理的对象
memento 生成可用于返回到以前状态的不透明令牌
observer 提供回调以通知数据的事件/更改
publish_subscribe 源将事件/数据联合到0+注册的侦听器
registry 跟踪给定类的所有子类
specification 通过使用布尔逻辑将业务规则链接在一起,可以重新组合业务规则
state 逻辑被组织成离散数量的潜在状态和可以转换到的下一个状态
strategy 对相同数据的可选操作
template 对象强加了一个结构,但接受可插入的组件
visitor 调用集合中所有项的回调

可测试性模式的设计

图案 描述
dependency_injection 依赖项注入的3种变体

基本模式

图案 描述
delegation_pattern 对象通过委托给第二个对象(委托)来处理请求

其他

图案 描述
blackboard 架构模型,集合不同子系统知识构建解决方案,AI方法-非四人帮模式
graph_search 绘图算法–非四人组模式
hsm 分层状态机-非四人组模式

视频

Design Patterns in Python by Peter Ullrich

Sebastian Buczyński – Why you don’t need design patterns in Python?

You Don’t Need That!

Pluggable Libs Through Design Patterns

贡献

添加或修改实施时,请查看以下准则:

输出

具有示例模式的所有文件都具有### OUTPUT ###部分(迁移到输出=“。”正在进行中)

append_output.sh(例如./append_output.sh borg.py)生成/更新它

文档字符串

以文档字符串的形式添加模块级描述,其中包含指向相应参考资料或其他有用信息的链接

如果您知道一些,请添加“Python生态系统中的示例”部分。它展示了如何将模式应用于现实世界的问题

facade.py有一个很好的详细描述的示例,但有时是较短的示例,如template.py就足够了

在某些情况下,带有doctest的类级文档字符串也会有所帮助(请参见adapter.py),但可读的输出部分要好得多

Python 2兼容性

要查看某些模式的Python2兼容版本,请查看legacy标签

更新自述文件

当其他工作完成后-更新自述文件的相应部分

特拉维斯CI

请跑吧toxtox -e ci37在提交修补程序之前,请确保您的更改将通过CI

您还可以运行flake8pytest手动命令。示例可在tox.ini

通过问题分类进行贡献

您可以对问题进行分类并提取请求,其中可能包括重现错误报告或要求提供重要信息,如版本号或重现说明。如果您想要开始对问题进行分类,一种简单的开始方法是subscribe to python-patterns on CodeTriage