标签归档:tuples

如何从熊猫的两列中形成元组列

问题:如何从熊猫的两列中形成元组列

我有一个Pandas DataFrame,我想将’lat’和’long’列组合成一个元组。

<class 'pandas.core.frame.DataFrame'>
Int64Index: 205482 entries, 0 to 209018
Data columns:
Month           205482  non-null values
Reported by     205482  non-null values
Falls within    205482  non-null values
Easting         205482  non-null values
Northing        205482  non-null values
Location        205482  non-null values
Crime type      205482  non-null values
long            205482  non-null values
lat             205482  non-null values
dtypes: float64(4), object(5)

我尝试使用的代码是:

def merge_two_cols(series): 
    return (series['lat'], series['long'])

sample['lat_long'] = sample.apply(merge_two_cols, axis=1)

但是,这返回以下错误:

---------------------------------------------------------------------------
 AssertionError                            Traceback (most recent call last)
<ipython-input-261-e752e52a96e6> in <module>()
      2     return (series['lat'], series['long'])
      3 
----> 4 sample['lat_long'] = sample.apply(merge_two_cols, axis=1)
      5

AssertionError: Block shape incompatible with manager 

我怎么解决这个问题?

I’ve got a Pandas DataFrame and I want to combine the ‘lat’ and ‘long’ columns to form a tuple.

<class 'pandas.core.frame.DataFrame'>
Int64Index: 205482 entries, 0 to 209018
Data columns:
Month           205482  non-null values
Reported by     205482  non-null values
Falls within    205482  non-null values
Easting         205482  non-null values
Northing        205482  non-null values
Location        205482  non-null values
Crime type      205482  non-null values
long            205482  non-null values
lat             205482  non-null values
dtypes: float64(4), object(5)

The code I tried to use was:

def merge_two_cols(series): 
    return (series['lat'], series['long'])

sample['lat_long'] = sample.apply(merge_two_cols, axis=1)

However, this returned the following error:

---------------------------------------------------------------------------
 AssertionError                            Traceback (most recent call last)
<ipython-input-261-e752e52a96e6> in <module>()
      2     return (series['lat'], series['long'])
      3 
----> 4 sample['lat_long'] = sample.apply(merge_two_cols, axis=1)
      5

AssertionError: Block shape incompatible with manager 

How can I solve this problem?


回答 0

适应吧zip。在处理列数据时,它很方便。

df['new_col'] = list(zip(df.lat, df.long))

与使用apply或相比,它不那么复杂且速度更快map。诸如此类的np.dstack速度是的两倍zip,但不会给您元组。

Get comfortable with zip. It comes in handy when dealing with column data.

df['new_col'] = list(zip(df.lat, df.long))

It’s less complicated and faster than using apply or map. Something like np.dstack is twice as fast as zip, but wouldn’t give you tuples.


回答 1

In [10]: df
Out[10]:
          A         B       lat      long
0  1.428987  0.614405  0.484370 -0.628298
1 -0.485747  0.275096  0.497116  1.047605
2  0.822527  0.340689  2.120676 -2.436831
3  0.384719 -0.042070  1.426703 -0.634355
4 -0.937442  2.520756 -1.662615 -1.377490
5 -0.154816  0.617671 -0.090484 -0.191906
6 -0.705177 -1.086138 -0.629708  1.332853
7  0.637496 -0.643773 -0.492668 -0.777344
8  1.109497 -0.610165  0.260325  2.533383
9 -1.224584  0.117668  1.304369 -0.152561

In [11]: df['lat_long'] = df[['lat', 'long']].apply(tuple, axis=1)

In [12]: df
Out[12]:
          A         B       lat      long                             lat_long
0  1.428987  0.614405  0.484370 -0.628298      (0.484370195967, -0.6282975278)
1 -0.485747  0.275096  0.497116  1.047605      (0.497115615839, 1.04760475074)
2  0.822527  0.340689  2.120676 -2.436831      (2.12067574274, -2.43683074367)
3  0.384719 -0.042070  1.426703 -0.634355      (1.42670326172, -0.63435462504)
4 -0.937442  2.520756 -1.662615 -1.377490     (-1.66261469102, -1.37749004179)
5 -0.154816  0.617671 -0.090484 -0.191906  (-0.0904840623396, -0.191905582481)
6 -0.705177 -1.086138 -0.629708  1.332853     (-0.629707821728, 1.33285348929)
7  0.637496 -0.643773 -0.492668 -0.777344   (-0.492667604075, -0.777344111021)
8  1.109497 -0.610165  0.260325  2.533383        (0.26032456699, 2.5333825651)
9 -1.224584  0.117668  1.304369 -0.152561     (1.30436900612, -0.152560909725)
In [10]: df
Out[10]:
          A         B       lat      long
0  1.428987  0.614405  0.484370 -0.628298
1 -0.485747  0.275096  0.497116  1.047605
2  0.822527  0.340689  2.120676 -2.436831
3  0.384719 -0.042070  1.426703 -0.634355
4 -0.937442  2.520756 -1.662615 -1.377490
5 -0.154816  0.617671 -0.090484 -0.191906
6 -0.705177 -1.086138 -0.629708  1.332853
7  0.637496 -0.643773 -0.492668 -0.777344
8  1.109497 -0.610165  0.260325  2.533383
9 -1.224584  0.117668  1.304369 -0.152561

In [11]: df['lat_long'] = df[['lat', 'long']].apply(tuple, axis=1)

In [12]: df
Out[12]:
          A         B       lat      long                             lat_long
0  1.428987  0.614405  0.484370 -0.628298      (0.484370195967, -0.6282975278)
1 -0.485747  0.275096  0.497116  1.047605      (0.497115615839, 1.04760475074)
2  0.822527  0.340689  2.120676 -2.436831      (2.12067574274, -2.43683074367)
3  0.384719 -0.042070  1.426703 -0.634355      (1.42670326172, -0.63435462504)
4 -0.937442  2.520756 -1.662615 -1.377490     (-1.66261469102, -1.37749004179)
5 -0.154816  0.617671 -0.090484 -0.191906  (-0.0904840623396, -0.191905582481)
6 -0.705177 -1.086138 -0.629708  1.332853     (-0.629707821728, 1.33285348929)
7  0.637496 -0.643773 -0.492668 -0.777344   (-0.492667604075, -0.777344111021)
8  1.109497 -0.610165  0.260325  2.533383        (0.26032456699, 2.5333825651)
9 -1.224584  0.117668  1.304369 -0.152561     (1.30436900612, -0.152560909725)

回答 2

熊猫有itertuples方法做到这一点:

list(df[['lat', 'long']].itertuples(index=False, name=None))

Pandas has the itertuples method to do exactly this:

list(df[['lat', 'long']].itertuples(index=False, name=None))

回答 3

我想补充一下df.values.tolist()。(只要您不介意获取列表列而不是元组)

import pandas as pd
import numpy as np

size = int(1e+07)
df = pd.DataFrame({'a': np.random.rand(size), 'b': np.random.rand(size)}) 

%timeit df.values.tolist()
1.47 s ± 38.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit list(zip(df.a,df.b))
1.92 s ± 131 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

I’d like to add df.values.tolist(). (as long as you don’t mind to get a column of lists rather than tuples)

import pandas as pd
import numpy as np

size = int(1e+07)
df = pd.DataFrame({'a': np.random.rand(size), 'b': np.random.rand(size)}) 

%timeit df.values.tolist()
1.47 s ± 38.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit list(zip(df.a,df.b))
1.92 s ± 131 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Python:更改元组中的值

问题:Python:更改元组中的值

我是python的新手,所以这个问题可能有点基本。我有一个元组values,其中包含以下内容:

('275', '54000', '0.0', '5000.0', '0.0')

我想更改275此元组中的第一个值(即),但我知道元组是不可变的,因此values[0] = 200将不起作用。我该如何实现?

I’m new to python so this question might be a little basic. I have a tuple called values which contains the following:

('275', '54000', '0.0', '5000.0', '0.0')

I want to change the first value (i.e., 275) in this tuple but I understand that tuples are immutable so values[0] = 200 will not work. How can I achieve this?


回答 0

首先,您需要问,为什么要这样做?

但是可以通过:

t = ('275', '54000', '0.0', '5000.0', '0.0')
lst = list(t)
lst[0] = '300'
t = tuple(lst)

但是,如果您需要进行更改,最好将其保留为 list

First you need to ask, why you want to do this?

But it’s possible via:

t = ('275', '54000', '0.0', '5000.0', '0.0')
lst = list(t)
lst[0] = '300'
t = tuple(lst)

But if you’re going to need to change things, you probably are better off keeping it as a list


回答 1

根据您的问题,切片可以是一个非常整洁的解决方案:

>>> b = (1, 2, 3, 4, 5)
>>> b[:2] + (8,9) + b[3:]
(1, 2, 8, 9, 4, 5)
>>> b[:2] + (8,) + b[3:]
(1, 2, 8, 4, 5)

这使您可以添加多个元素或替换一些元素(尤其是在它们是“邻居”时。在上述情况下,强制转换为列表可能更合适且更易读(即使切片表示法要短得多)。

Depending on your problem slicing can be a really neat solution:

>>> b = (1, 2, 3, 4, 5)
>>> b[:2] + (8,9) + b[3:]
(1, 2, 8, 9, 4, 5)
>>> b[:2] + (8,) + b[3:]
(1, 2, 8, 4, 5)

This allows you to add multiple elements or also to replace a few elements (especially if they are “neighbours”. In the above case casting to a list is probably more appropriate and readable (even though the slicing notation is much shorter).


回答 2

好吧,正如Trufa已经显示的那样,在给定的索引上基本上有两种替换元组元素的方法。将元组转换为列表,替换元素然后再转换回去,或者通过串联构造新的元组。

In [1]: def replace_at_index1(tup, ix, val):
   ...:     lst = list(tup)
   ...:     lst[ix] = val
   ...:     return tuple(lst)
   ...:

In [2]: def replace_at_index2(tup, ix, val):
   ...:     return tup[:ix] + (val,) + tup[ix+1:]
   ...:

那么,哪种方法更好,那就是更快?

事实证明,对于短元组(在Python 3.3上),连接实际上更快!

In [3]: d = tuple(range(10))

In [4]: %timeit replace_at_index1(d, 5, 99)
1000000 loops, best of 3: 872 ns per loop

In [5]: %timeit replace_at_index2(d, 5, 99)
1000000 loops, best of 3: 642 ns per loop

但是,如果我们查看更长的元组,则列表转换是必经之路:

In [6]: k = tuple(range(1000))

In [7]: %timeit replace_at_index1(k, 500, 99)
100000 loops, best of 3: 9.08 µs per loop

In [8]: %timeit replace_at_index2(k, 500, 99)
100000 loops, best of 3: 10.1 µs per loop

对于非常长的元组,列表转换要好得多!

In [9]: m = tuple(range(1000000))

In [10]: %timeit replace_at_index1(m, 500000, 99)
10 loops, best of 3: 26.6 ms per loop

In [11]: %timeit replace_at_index2(m, 500000, 99)
10 loops, best of 3: 35.9 ms per loop

同样,串联方法的性能取决于替换元素的索引。对于列表方法,索引是不相关的。

In [12]: %timeit replace_at_index1(m, 900000, 99)
10 loops, best of 3: 26.6 ms per loop

In [13]: %timeit replace_at_index2(m, 900000, 99)
10 loops, best of 3: 49.2 ms per loop

因此:如果您的元组很短,则切片并连接。如果很长,请执行列表转换!

Well, as Trufa has already shown, there are basically two ways of replacing a tuple’s element at a given index. Either convert the tuple to a list, replace the element and convert back, or construct a new tuple by concatenation.

In [1]: def replace_at_index1(tup, ix, val):
   ...:     lst = list(tup)
   ...:     lst[ix] = val
   ...:     return tuple(lst)
   ...:

In [2]: def replace_at_index2(tup, ix, val):
   ...:     return tup[:ix] + (val,) + tup[ix+1:]
   ...:

So, which method is better, that is, faster?

It turns out that for short tuples (on Python 3.3), concatenation is actually faster!

In [3]: d = tuple(range(10))

In [4]: %timeit replace_at_index1(d, 5, 99)
1000000 loops, best of 3: 872 ns per loop

In [5]: %timeit replace_at_index2(d, 5, 99)
1000000 loops, best of 3: 642 ns per loop

Yet if we look at longer tuples, list conversion is the way to go:

In [6]: k = tuple(range(1000))

In [7]: %timeit replace_at_index1(k, 500, 99)
100000 loops, best of 3: 9.08 µs per loop

In [8]: %timeit replace_at_index2(k, 500, 99)
100000 loops, best of 3: 10.1 µs per loop

For very long tuples, list conversion is substantially better!

In [9]: m = tuple(range(1000000))

In [10]: %timeit replace_at_index1(m, 500000, 99)
10 loops, best of 3: 26.6 ms per loop

In [11]: %timeit replace_at_index2(m, 500000, 99)
10 loops, best of 3: 35.9 ms per loop

Also, performance of the concatenation method depends on the index at which we replace the element. For the list method, the index is irrelevant.

In [12]: %timeit replace_at_index1(m, 900000, 99)
10 loops, best of 3: 26.6 ms per loop

In [13]: %timeit replace_at_index2(m, 900000, 99)
10 loops, best of 3: 49.2 ms per loop

So: If your tuple is short, slice and concatenate. If it’s long, do the list conversion!


回答 3

一个衬垫是可能的:

values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])

It is possible with a one liner:

values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])

回答 4

并不是说这是优越的,但是如果有人好奇的话,可以用以下方法一行完成:

tuple = tuple([200 if i == 0 else _ for i, _ in enumerate(tuple)])

Not that this is superior, but if anyone is curious it can be done on one line with:

tuple = tuple([200 if i == 0 else _ for i, _ in enumerate(tuple)])

回答 5

我相信这从技术上讲可以回答问题,但不要在家中这样做。目前,所有答案都涉及创建新的元组,但是您可以使用它ctypes来修改内存中的元组。依靠64位系统上CPython的各种实现细节,一种实现方法如下:

def modify_tuple(t, idx, new_value):
    # `id` happens to give the memory address in CPython; you may
    # want to use `ctypes.addressof` instead.
    element_ptr = (ctypes.c_longlong).from_address(id(t) + (3 + idx)*8)
    element_ptr.value = id(new_value)
    # Manually increment the reference count to `new_value` to pretend that
    # this is not a terrible idea.
    ref_count = (ctypes.c_longlong).from_address(id(new_value))
    ref_count.value += 1

t = (10, 20, 30)
modify_tuple(t, 1, 50)   # t is now (10, 50, 30)
modify_tuple(t, -1, 50)  # Will probably crash your Python runtime

I believe this technically answers the question, but don’t do this at home. At the moment, all answers involve creating a new tuple, but you can use ctypes to modify a tuple in-memory. Relying on various implementation details of CPython on a 64-bit system, one way to do this is as follows:

def modify_tuple(t, idx, new_value):
    # `id` happens to give the memory address in CPython; you may
    # want to use `ctypes.addressof` instead.
    element_ptr = (ctypes.c_longlong).from_address(id(t) + (3 + idx)*8)
    element_ptr.value = id(new_value)
    # Manually increment the reference count to `new_value` to pretend that
    # this is not a terrible idea.
    ref_count = (ctypes.c_longlong).from_address(id(new_value))
    ref_count.value += 1

t = (10, 20, 30)
modify_tuple(t, 1, 50)   # t is now (10, 50, 30)
modify_tuple(t, -1, 50)  # Will probably crash your Python runtime

回答 6

正如Hunter McMillen在评论中所写,元组是不可变的,您需要创建一个新的元组以实现此目的。例如:

>>> tpl = ('275', '54000', '0.0', '5000.0', '0.0')
>>> change_value = 200
>>> tpl = (change_value,) + tpl[1:]
>>> tpl
(200, '54000', '0.0', '5000.0', '0.0')

As Hunter McMillen wrote in the comments, tuples are immutable, you need to create a new tuple in order to achieve this. For instance:

>>> tpl = ('275', '54000', '0.0', '5000.0', '0.0')
>>> change_value = 200
>>> tpl = (change_value,) + tpl[1:]
>>> tpl
(200, '54000', '0.0', '5000.0', '0.0')

回答 7

编辑:这不适用于具有重复条目的元组!

基于Pooya的想法

如果您打算经常执行此操作(由于元组由于某种原因是不变的,则不应该这样做),您应该执行以下操作:

def modTupByIndex(tup, index, ins):
    return tuple(tup[0:index]) + (ins,) + tuple(tup[index+1:])

print modTupByIndex((1,2,3),2,"a")

或基于乔恩的想法

def modTupByIndex(tup, index, ins):
    lst = list(tup)
    lst[index] = ins
    return tuple(lst)

print modTupByIndex((1,2,3),1,"a")

EDIT: This doesn’t work on tuples with duplicate entries yet!!

Based on Pooya’s idea:

If you are planning on doing this often (which you shouldn’t since tuples are inmutable for a reason) you should do something like this:

def modTupByIndex(tup, index, ins):
    return tuple(tup[0:index]) + (ins,) + tuple(tup[index+1:])

print modTupByIndex((1,2,3),2,"a")

Or based on Jon’s idea:

def modTupByIndex(tup, index, ins):
    lst = list(tup)
    lst[index] = ins
    return tuple(lst)

print modTupByIndex((1,2,3),1,"a")

回答 8

第一拳,问自己为什么要突变你的tuple在Ptyhon中字符串和元组是不可变的,这是有原因的,如果您想对自己的变量进行突变,tuple那么它应该是一个list替代。

其次,如果您仍然希望对元组进行突变,则可以将转换tuple为,list然后再转换回去,然后将新的元组重新分配给相同的变量。如果您只想对元组进行一次变异,那就太好了。否则,我个人认为这是违反直觉的。因为它本质上是在创建一个新的元组,并且每次您想要对元组进行突变时,都必须执行转换。另外,如果您阅读了代码,那么思考为什么不仅仅创建一个list?但这很好,因为它不需要任何库。

我建议mutabletuple(typename, field_names, default=MtNoDefault)mutabletuple 0.2使用。我个人认为这种方式是一个更直观可读性。阅读该代码的人会知道编写者打算将来更改此元组。与list上面的转换方法相比,不利之处在于,这需要您导入其他py文件。

from mutabletuple import mutabletuple

myTuple = mutabletuple('myTuple', 'v w x y z')
p = myTuple('275', '54000', '0.0', '5000.0', '0.0')
print(p.v) #print 275
p.v = '200' #mutate myTuple
print(p.v) #print 200

TL; DR:不要尝试变异tuple。如果您这样做并且是一次操作,则转换tuple为列表,对其进行变异,将其list转换为新tuple变量,然后重新分配给持有old的变量tuple。如果欲望tuple和某种原因想避免list并想变异多于一次,那就创造mutabletuple

Frist, ask yourself why you want to mutate your tuple. There is a reason why strings and tuple are immutable in Ptyhon, if you want to mutate your tuple then it should probably be a list instead.

Second, if you still wish to mutate your tuple then you can convert your tuple to a list then convert it back, and reassign the new tuple to the same variable. This is great if you are only going to mutate your tuple once. Otherwise, I personally think that is counterintuitive. Because It is essentially creating a new tuple and every time if you wish to mutate the tuple you would have to perform the conversion. Also If you read the code it would be confusing to think why not just create a list? But it is nice because it doesn’t require any library.

I suggest using mutabletuple(typename, field_names, default=MtNoDefault) from mutabletuple 0.2. I personally think this way is a more intuitive and readable. The personal reading the code would know that writer intends to mutate this tuple in the future. The downside compares to the list conversion method above is that this requires you to import additional py file.

from mutabletuple import mutabletuple

myTuple = mutabletuple('myTuple', 'v w x y z')
p = myTuple('275', '54000', '0.0', '5000.0', '0.0')
print(p.v) #print 275
p.v = '200' #mutate myTuple
print(p.v) #print 200

TL;DR: Don’t try to mutate tuple. if you do and it is a one-time operation convert tuple to list, mutate it, turn list into a new tuple, and reassign back to the variable holding old tuple. If desires tuple and somehow want to avoid listand want to mutate more than once then create mutabletuple.


回答 9

基于乔恩的思想和亲爱的特鲁法。

def modifyTuple(tup, oldval, newval):
    lst=list(tup)
    for i in range(tup.count(oldval)):
        index = lst.index(oldval)
        lst[index]=newval

    return tuple(lst)

print modTupByIndex((1, 1, 3), 1, "a")

它会改变您所有的旧价值观

based on Jon‘s Idea and dear Trufa

def modifyTuple(tup, oldval, newval):
    lst=list(tup)
    for i in range(tup.count(oldval)):
        index = lst.index(oldval)
        lst[index]=newval

    return tuple(lst)

print modTupByIndex((1, 1, 3), 1, "a")

it changes all of your old values occurrences


回答 10

你不能 如果要更改它,则需要使用列表而不是元组。

请注意,您可以改为创建一个以新值作为第一个元素的新元组。

You can’t. If you want to change it, you need to use a list instead of a tuple.

Note that you could instead make a new tuple that has the new value as its first element.


回答 11

我发现编辑元组的最佳方法是使用以前的版本作为基础来重新创建元组。

这是我用来制作较浅颜色的示例(当时我已经打开它了):

colour = tuple([c+50 for c in colour])

它的作用是遍历元组的“颜色”并读取每个项目,对其进行处理,最后将其添加到新的元组中。

因此,您想要的是:

values = ('275', '54000', '0.0', '5000.0', '0.0')

values  = (tuple(for i in values: if i = 0: i = 200 else i = values[i])

那个特定的那个不起作用,但是您需要的是概念。

tuple = (0, 1, 2)

元组=遍历元组,根据需要更改每个项目

这就是概念。

I’ve found the best way to edit tuples is to recreate the tuple using the previous version as the base.

Here’s an example I used for making a lighter version of a colour (I had it open already at the time):

colour = tuple([c+50 for c in colour])

What it does, is it goes through the tuple ‘colour’ and reads each item, does something to it, and finally adds it to the new tuple.

So what you’d want would be something like:

values = ('275', '54000', '0.0', '5000.0', '0.0')

values  = (tuple(for i in values: if i = 0: i = 200 else i = values[i])

That specific one doesn’t work, but the concept is what you need.

tuple = (0, 1, 2)

tuple = iterate through tuple, alter each item as needed

that’s the concept.


回答 12

我来晚了,但是我认为最简单,资源友好和最快的方法(取决于情况)是覆盖元组本身。由于这将消除对列表和变量创建的需要,因此将其归档在一行中。

new = 24
t = (1, 2, 3)
t = (t[0],t[1],new)

>>> (1, 2, 24)

但是:这仅适用于较小的元组,并且还会将您限制为固定的元组值,但是,无论如何,在大多数情况下,这都是元组的情况。

因此,在这种特殊情况下,它看起来像这样:

new = '200'
t = ('275', '54000', '0.0', '5000.0', '0.0')
t = (new, t[1], t[2], t[3], t[4])

>>> ('200', '54000', '0.0', '5000.0', '0.0')

I´m late to the game but I think the simplest, resource-friendliest and fastest way (depending on the situation), is to overwrite the tuple itself. Since this would remove the need for the list & variable creation and is archived in one line.

new = 24
t = (1, 2, 3)
t = (t[0],t[1],new)

>>> (1, 2, 24)

But: This is only handy for rather small tuples and also limits you to a fixed tuple value, nevertheless, this is the case for tuples most of the time anyway.

So in this particular case it would look like this:

new = '200'
t = ('275', '54000', '0.0', '5000.0', '0.0')
t = (new, t[1], t[2], t[3], t[4])

>>> ('200', '54000', '0.0', '5000.0', '0.0')

回答 13

tldr; “解决方法”是创建一个新的元组对象,而不是实际修改原始对象

尽管这是一个非常老的问题,但有人告诉我有关Python变异元组的疯狂。我非常惊讶/被它吸引,并做了一些谷歌搜索,我降落在这里(和其他在线的类似样本)

我进行了一些测试以证明我的理论

请注意==,值相等,而is引用相等(obj a与obj b相同)

a = ("apple", "canana", "cherry")
b = tuple(["apple", "canana", "cherry"])
c = a

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

d = list(a)
d[1] = "kiwi"
a = tuple(d)

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

Yield:

a: ('apple', 'canana', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: True
b == c :: True
a == c :: True
a is b :: False
b is c :: False
a is c :: True
a: ('apple', 'kiwi', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: False
b == c :: True
a == c :: False
a is b :: False
b is c :: False
a is c :: False

tldr; the “workaround” is creating a new tuple object, not actually modifying the original

While this is a very old question, someone told me about this Python mutating tuples madness. Which I was very much surprised/intrigued, and doing some googling, I landed here (and other similar samples online)

I ran some test to prove my theory

Note == does value equality while is does referential equality (is obj a the same instance as obj b)

a = ("apple", "canana", "cherry")
b = tuple(["apple", "canana", "cherry"])
c = a

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

d = list(a)
d[1] = "kiwi"
a = tuple(d)

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

Yields:

a: ('apple', 'canana', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: True
b == c :: True
a == c :: True
a is b :: False
b is c :: False
a is c :: True
a: ('apple', 'kiwi', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: False
b == c :: True
a == c :: False
a is b :: False
b is c :: False
a is c :: False

回答 14

您不能修改元组中的项目,但是可以修改元组中可变对象的属性(例如,如果这些对象是列表或实际的类对象)

例如

my_list = [1,2]
tuple_of_lists = (my_list,'hello')
print(tuple_of_lists) # ([1, 2], 'hello')
my_list[0] = 0
print(tuple_of_lists) # ([0, 2], 'hello')

You can’t modify items in tuple, but you can modify properties of mutable objects in tuples (for example if those objects are lists or actual class objects)

For example

my_list = [1,2]
tuple_of_lists = (my_list,'hello')
print(tuple_of_lists) # ([1, 2], 'hello')
my_list[0] = 0
print(tuple_of_lists) # ([0, 2], 'hello')

回答 15

我这样做:

list = [1,2,3,4,5]
tuple = (list)

要改变,只要做

list[0]=6

你可以改变一个元组:D

这是它完全从IDLE复制的

>>> list=[1,2,3,4,5,6,7,8,9]

>>> tuple=(list)

>>> print(tuple)

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

>>> list[0]=6

>>> print(tuple)

[6, 2, 3, 4, 5, 6, 7, 8, 9]

i did this:

list = [1,2,3,4,5]
tuple = (list)

and to change, just do

list[0]=6

and u can change a tuple :D

here is it copied exactly from IDLE

>>> list=[1,2,3,4,5,6,7,8,9]

>>> tuple=(list)

>>> print(tuple)

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

>>> list[0]=6

>>> print(tuple)

[6, 2, 3, 4, 5, 6, 7, 8, 9]

回答 16

您可以使用按引用复制来更改元组的值

>>> tuple1=[20,30,40]

>>> tuple2=tuple1

>>> tuple2
    [20, 30, 40]

>>> tuple2[1]=10

>>> print(tuple2)
    [20, 10, 40]

>>> print(tuple1)
    [20, 10, 40]

You can change the value of tuple using copy by reference

>>> tuple1=[20,30,40]

>>> tuple2=tuple1

>>> tuple2
    [20, 30, 40]

>>> tuple2[1]=10

>>> print(tuple2)
    [20, 10, 40]

>>> print(tuple1)
    [20, 10, 40]

从列表或元组中明确选择项目

问题:从列表或元组中明确选择项目

我有以下Python列表(也可以是元组):

myList = ['foo', 'bar', 'baz', 'quux']

我可以说

>>> myList[0:3]
['foo', 'bar', 'baz']
>>> myList[::2]
['foo', 'baz']
>>> myList[1::2]
['bar', 'quux']

如何显式挑选索引没有特定模式的项目?例如,我要选择[0,2,3]。或者,从1000个很大的清单中,我要选择[87, 342, 217, 998, 500]。是否有一些Python语法可以做到这一点?看起来像这样:

>>> myBigList[87, 342, 217, 998, 500]

I have the following Python list (can also be a tuple):

myList = ['foo', 'bar', 'baz', 'quux']

I can say

>>> myList[0:3]
['foo', 'bar', 'baz']
>>> myList[::2]
['foo', 'baz']
>>> myList[1::2]
['bar', 'quux']

How do I explicitly pick out items whose indices have no specific patterns? For example, I want to select [0,2,3]. Or from a very big list of 1000 items, I want to select [87, 342, 217, 998, 500]. Is there some Python syntax that does that? Something that looks like:

>>> myBigList[87, 342, 217, 998, 500]

回答 0

list( myBigList[i] for i in [87, 342, 217, 998, 500] )

我将答案与python 2.5.2进行了比较:

  • 19.7微秒: [ myBigList[i] for i in [87, 342, 217, 998, 500] ]

  • 20.6 USEC: map(myBigList.__getitem__, (87, 342, 217, 998, 500))

  • 22.7 USEC: itemgetter(87, 342, 217, 998, 500)(myBigList)

  • 24.6 USEC: list( myBigList[i] for i in [87, 342, 217, 998, 500] )

请注意,在Python 3中,第1个已更改为与第4个相同。


另一种选择是以a开头,numpy.array它允许通过列表或a进行索引numpy.array

>>> import numpy
>>> myBigList = numpy.array(range(1000))
>>> myBigList[(87, 342, 217, 998, 500)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> myBigList[[87, 342, 217, 998, 500]]
array([ 87, 342, 217, 998, 500])
>>> myBigList[numpy.array([87, 342, 217, 998, 500])]
array([ 87, 342, 217, 998, 500])

tuple不工作方式相同那些片。

list( myBigList[i] for i in [87, 342, 217, 998, 500] )

I compared the answers with python 2.5.2:

  • 19.7 usec: [ myBigList[i] for i in [87, 342, 217, 998, 500] ]

  • 20.6 usec: map(myBigList.__getitem__, (87, 342, 217, 998, 500))

  • 22.7 usec: itemgetter(87, 342, 217, 998, 500)(myBigList)

  • 24.6 usec: list( myBigList[i] for i in [87, 342, 217, 998, 500] )

Note that in Python 3, the 1st was changed to be the same as the 4th.


Another option would be to start out with a numpy.array which allows indexing via a list or a numpy.array:

>>> import numpy
>>> myBigList = numpy.array(range(1000))
>>> myBigList[(87, 342, 217, 998, 500)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> myBigList[[87, 342, 217, 998, 500]]
array([ 87, 342, 217, 998, 500])
>>> myBigList[numpy.array([87, 342, 217, 998, 500])]
array([ 87, 342, 217, 998, 500])

The tuple doesn’t work the same way as those are slices.


回答 1

那这个呢:

from operator import itemgetter
itemgetter(0,2,3)(myList)
('foo', 'baz', 'quux')

What about this:

from operator import itemgetter
itemgetter(0,2,3)(myList)
('foo', 'baz', 'quux')

回答 2

它不是内置的,但是如果您愿意,可以创建一个将元组作为“索引”的list的子类:

class MyList(list):

    def __getitem__(self, index):
        if isinstance(index, tuple):
            return [self[i] for i in index]
        return super(MyList, self).__getitem__(index)


seq = MyList("foo bar baaz quux mumble".split())
print seq[0]
print seq[2,4]
print seq[1::2]

印刷

foo
['baaz', 'mumble']
['bar', 'quux']

It isn’t built-in, but you can make a subclass of list that takes tuples as “indexes” if you’d like:

class MyList(list):

    def __getitem__(self, index):
        if isinstance(index, tuple):
            return [self[i] for i in index]
        return super(MyList, self).__getitem__(index)


seq = MyList("foo bar baaz quux mumble".split())
print seq[0]
print seq[2,4]
print seq[1::2]

printing

foo
['baaz', 'mumble']
['bar', 'quux']

回答 3

也许列表理解是按顺序进行的:

L = ['a', 'b', 'c', 'd', 'e', 'f']
print [ L[index] for index in [1,3,5] ]

生成:

['b', 'd', 'f']

那是您要找的东西吗?

Maybe a list comprehension is in order:

L = ['a', 'b', 'c', 'd', 'e', 'f']
print [ L[index] for index in [1,3,5] ]

Produces:

['b', 'd', 'f']

Is that what you are looking for?


回答 4

>>> map(myList.__getitem__, (2,2,1,3))
('baz', 'baz', 'bar', 'quux')

您也可以创建自己的List类,该类支持将元组用作__getitem__要执行的操作的参数myList[(2,2,1,3)]

>>> map(myList.__getitem__, (2,2,1,3))
('baz', 'baz', 'bar', 'quux')

You can also create your own List class which supports tuples as arguments to __getitem__ if you want to be able to do myList[(2,2,1,3)].


回答 5

我只想指出,即使itemgetter的语法看起来也很整洁,但是在大型列表上执行时有点慢。

import timeit
from operator import itemgetter
start=timeit.default_timer()
for i in range(1000000):
    itemgetter(0,2,3)(myList)
print ("Itemgetter took ", (timeit.default_timer()-start))

物品获取者1.065209062149279

start=timeit.default_timer()
for i in range(1000000):
    myList[0],myList[2],myList[3]
print ("Multiple slice took ", (timeit.default_timer()-start))

多个切片花费0.6225321444745759

I just want to point out, even syntax of itemgetter looks really neat, but it’s kinda slow when perform on large list.

import timeit
from operator import itemgetter
start=timeit.default_timer()
for i in range(1000000):
    itemgetter(0,2,3)(myList)
print ("Itemgetter took ", (timeit.default_timer()-start))

Itemgetter took 1.065209062149279

start=timeit.default_timer()
for i in range(1000000):
    myList[0],myList[2],myList[3]
print ("Multiple slice took ", (timeit.default_timer()-start))

Multiple slice took 0.6225321444745759


回答 6

另一个可能的解决方案:

sek=[]
L=[1,2,3,4,5,6,7,8,9,0]
for i in [2, 4, 7, 0, 3]:
   a=[L[i]]
   sek=sek+a
print (sek)

Another possible solution:

sek=[]
L=[1,2,3,4,5,6,7,8,9,0]
for i in [2, 4, 7, 0, 3]:
   a=[L[i]]
   sek=sek+a
print (sek)

回答 7

当你有一个布尔numpy数组时,就像 mask

[mylist[i] for i in np.arange(len(mask), dtype=int)[mask]]

适用于任何序列或np.array的lambda:

subseq = lambda myseq, mask : [myseq[i] for i in np.arange(len(mask), dtype=int)[mask]]

newseq = subseq(myseq, mask)

like often when you have a boolean numpy array like mask

[mylist[i] for i in np.arange(len(mask), dtype=int)[mask]]

A lambda that works for any sequence or np.array:

subseq = lambda myseq, mask : [myseq[i] for i in np.arange(len(mask), dtype=int)[mask]]

newseq = subseq(myseq, mask)


Python中“(1,)== 1”是什么意思?

问题:Python中“(1,)== 1”是什么意思?

我正在测试元组结构,当我==像这样使用运算符时发现它很奇怪:

>>>  (1,) == 1,
Out: (False,)

当我将这两个表达式分配给变量时,结果为true:

>>> a = (1,)
>>> b = 1,
>>> a==b
Out: True

在我看来,这个问题与Python元组尾随逗号语法规则不同。请问==运算符之间的表达式组。

I’m testing the tuple structure, and I found it’s strange when I use the == operator like:

>>>  (1,) == 1,
Out: (False,)

When I assign these two expressions to a variable, the result is true:

>>> a = (1,)
>>> b = 1,
>>> a==b
Out: True

This questions is different from Python tuple trailing comma syntax rule in my view. I ask the group of expressions between == operator.


回答 0

其他答案已经向您显示该行为是由于运算符的优先级所致,如此处所述

下次您遇到类似问题时,我将向您展示如何找到答案。您可以使用以下ast模块来解构表达式的解析方式:

>>> import ast
>>> source_code = '(1,) == 1,'
>>> print(ast.dump(ast.parse(source_code), annotate_fields=False))
Module([Expr(Tuple([Compare(Tuple([Num(1)], Load()), [Eq()], [Num(1)])], Load()))])

从中我们可以看到代码已按照Tim Peters的解释进行了解析:

Module([Expr(
    Tuple([
        Compare(
            Tuple([Num(1)], Load()), 
            [Eq()], 
            [Num(1)]
        )
    ], Load())
)])

Other answers have already shown you that the behaviour is due to operator precedence, as documented here.

I’m going to show you how to find the answer yourself next time you have a question similar to this. You can deconstruct how the expression parses using the ast module:

>>> import ast
>>> source_code = '(1,) == 1,'
>>> print(ast.dump(ast.parse(source_code), annotate_fields=False))
Module([Expr(Tuple([Compare(Tuple([Num(1)], Load()), [Eq()], [Num(1)])], Load()))])

From this we can see that the code gets parsed as Tim Peters explained:

Module([Expr(
    Tuple([
        Compare(
            Tuple([Num(1)], Load()), 
            [Eq()], 
            [Num(1)]
        )
    ], Load())
)])

回答 1

这只是运算符的优先级。你的第一个

(1,) == 1,

像这样的团体:

((1,) == 1),

因此,根据将一个元素的元组1,与整数1进行相等性比较的结果来构建一个具有单个元素的元组False,

This is just operator precedence. Your first

(1,) == 1,

groups like so:

((1,) == 1),

so builds a tuple with a single element from the result of comparing the one-element tuple 1, to the integer 1 for equality They’re not equal, so you get the 1-tuple False, for a result.


回答 2

当你做

>>> (1,) == 1,

它通过将元 (1,)整数进行比较并返回来生成一个元组False

相反,当您分配变量时,两个相等的元组会相互比较。

你可以试试:

>>> x = 1,
>>> x
(1,)

When you do

>>> (1,) == 1,

it builds a tuple with the result from comparing the tuple (1,) with an integer and thus returning False.

Instead when you assign to variables, the two equal tuples are compared with each other.

You can try:

>>> x = 1,
>>> x
(1,)

在元组定义中使用逗号结尾的语法规则是什么?

问题:在元组定义中使用逗号结尾的语法规则是什么?

在单个元素元组的情况下,需要尾随逗号。

a = ('foo',)

那么具有多个元素的元组呢?似乎尾随逗号是否存在,它们都有效。这样对吗?我认为使用逗号结尾更易于编辑。那是不好的编码风格吗?

a = ('foo1', 'foo2')
b = ('foo1', 'foo2',)

In the case of a single element tuple, the trailing comma is required.

a = ('foo',)

What about a tuple with multiple elements? It seems that whether the trailing comma exists or not, they are both valid. Is this correct? Having a trailing comma is easier for editing in my opinion. Is that a bad coding style?

a = ('foo1', 'foo2')
b = ('foo1', 'foo2',)

回答 0

在所有情况下,除了空的元组,逗号都是重要的事情。仅在出于其他语法原因而需要时才需要括号:将元组与一组函数参数,运算符优先级区分开或允许换行。

元组,列表或函数参数的尾部逗号是一种不错的样式,尤其是当您有一个较长的初始化并分为多行时。如果始终包含尾随逗号,则不会在末尾添加任何行,而期望添加另一个元素,而只是创建一个有效的表达式:

a = [
   "a",
   "b"
   "c"
]

假设它最初是一个2元素列表,后来又进行了扩展,那么它可能以一种可能并不立即显而易见的方式出错了。始终包含结尾逗号,这样可以避免出现陷阱。

In all cases except the empty tuple the comma is the important thing. Parentheses are only required when required for other syntactic reasons: to distinguish a tuple from a set of function arguments, operator precedence, or to allow line breaks.

The trailing comma for tuples, lists, or function arguments is good style especially when you have a long initialisation that is split over multiple lines. If you always include a trailing comma then you won’t add another line to the end expecting to add another element and instead just creating a valid expression:

a = [
   "a",
   "b"
   "c"
]

Assuming that started as a 2 element list that was later extended it has gone wrong in a perhaps not immediately obvious way. Always include the trailing comma and you avoid that trap.


回答 1

只有单项元组才需要消除定义元组或由括号包围的表达式的歧义。

(1)  # the number 1 (the parentheses are wrapping the expression `1`)
(1,) # a 1-tuple holding a number 1

对于一个以上的项目,不再需要了,因为显然它是一个元组。但是,允许使用逗号逗号来简化使用多行定义它们的过程。您可以在不破坏语法的情况下添加到末尾或重新排列项目,因为您偶然遗漏了逗号。

例如,

someBigTuple = (
                   0,
                   1,
                   2,
                   3,
                   4,
                   5,
                   6,
                   7,
                   8,
                   9,
                   10,
                   #...
                   10000000000,
               )

请注意,这也适用于其他集合(例如列表和字典),而不仅仅是元组。

It is only required for single-item tuples to disambiguate defining a tuple or an expression surrounded by parentheses.

(1)  # the number 1 (the parentheses are wrapping the expression `1`)
(1,) # a 1-tuple holding a number 1

For more than one item, it is no longer necessary since it is perfectly clear it is a tuple. However, the trailing comma is allowed to make defining them using multiple lines easier. You could add to the end or rearrange items without breaking the syntax because you left out a comma on accident.

e.g.,

someBigTuple = (
                   0,
                   1,
                   2,
                   3,
                   4,
                   5,
                   6,
                   7,
                   8,
                   9,
                   10,
                   #...
                   10000000000,
               )

Note that this applies to other collections (e.g., lists and dictionaries) too and not just tuples.


回答 2

尾随逗号的另一个优点是,它使差异看起来更好。如果您从

a = [
    1,
    2,
    3
]

并将其更改为

a = [
    1,
    2,
    3,
    4
]

差异看起来像

 a = [
     1,
     2,
-    3
+    3,
+    4
 ]

而如果您以逗号开头,例如

a = [
    1,
    2,
    3,
]

然后差异将是

 a = [
     1,
     2,
     3,
+    4,
 ]

Another advantage of trailing commas is that it makes diffs look nicer. If you started with

a = [
    1,
    2,
    3
]

and changed it to

a = [
    1,
    2,
    3,
    4
]

The diff would look like

 a = [
     1,
     2,
-    3
+    3,
+    4
 ]

Whereas if you had started with a trailing comma, like

a = [
    1,
    2,
    3,
]

Then the diff would just be

 a = [
     1,
     2,
     3,
+    4,
 ]

回答 3

它是可选的:请参阅Python Wiki

简介:单元素元组需要结尾逗号,但是对于多元素元组是可选的。

It’s optional: see the Python wiki.

Summary: single-element tuples need a trailing comma, but it’s optional for multiple-element tuples.


回答 4

另外,请考虑所需的情况:

>>> (('x','y'))*4                         # same as ('x','y')*4
('x', 'y', 'x', 'y', 'x', 'y', 'x', 'y')
#Expected = (('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

因此,在这种情况下,外部括号仅是对括号进行分组。要使它们成为元组,您需要添加尾随逗号。即

>>> (('x','y'),)*4 
(('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

Also, consider the situation where you want:

>>> (('x','y'))*4                         # same as ('x','y')*4
('x', 'y', 'x', 'y', 'x', 'y', 'x', 'y')
#Expected = (('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

So in this case the outer parentheses are nothing more than grouping parentheses. To make them tuple you need to add a trailing comma. i.e.

>>> (('x','y'),)*4 
(('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

回答 5

仅尾元素元组才需要尾随逗号。对于较大的元组,用逗号结尾是一个样式问题,并非必需。它的最大优点是对带有经常修改的多行大元组(例如配置元组)的文件进行完全比较。

Trailing comma is required for one-element tuples only. Having a trailing comma for larger tuples is a matter of style and is not required. Its greatest advantage is clean diff on files with multi-line large tuples that are often modified (e.g. configuration tuples).


回答 6

这是一个简单的答案。

a =(“ s”)是一个字符串

a =(“ s”,)是具有一个元素的元组。

对于一个元素元组,Python需要附加逗号,以区分字符串和元组。

例如,在python控制台上尝试:

a =(“ s”)

a = a +(1,2,3)

追溯(最近一次通话):

文件stdin,第1行,在模块中

TypeError:无法连接“ str”和“ tuple”对象

That’s a simple answer.

a = (“s”) is a string

and

a = (“s”,) is a tuple with one element.

Python needs an additional comma in case of one element tuple to, differentiate between string and tuple.

For example try this on python console:

a = (“s”)

a = a + (1,2,3)

Traceback (most recent call last):

File stdin, line 1, in module

TypeError: cannot concatenate ‘str’ and ‘tuple’ objects


回答 7

存在的另一个原因是它使代码生成和__repr__功能更易于编写。例如,如果您有一些构建为的对象obj(arg1, arg2, ..., argn),则可以这样写obj.__repr__

def __repr__(self):
    l = ['obj(']
    for arg in obj.args: # Suppose obj.args == (arg1, arg2, ..., argn)
        l.append(repr(arg))
        l.append(', ')
    l.append(')')
    return ''.join(l)

如果不允许使用逗号结尾,则必须对最后一个参数进行特殊处理。实际上,您可以使用列表理解将上述内容写在一行中(我将其写得更长一些,以便于阅读)。如果上学期不得不特殊情况,要做到这一点并非易事。

Another reason that this exists is that it makes code generation and __repr__ functions easier to write. For example, if you have some object that is built like obj(arg1, arg2, ..., argn), then you can just write obj.__repr__ as

def __repr__(self):
    l = ['obj(']
    for arg in obj.args: # Suppose obj.args == (arg1, arg2, ..., argn)
        l.append(repr(arg))
        l.append(', ')
    l.append(')')
    return ''.join(l)

If a trailing comma wasn’t allowed, you would have to special case the last argument. In fact, you could write the above in one line using a list comprehension (I’ve written it out longer to make it easier to read). It wouldn’t be so easy to do that if you had to special case the last term.


回答 8

PEP 8-Python代码样式指南-何时使用尾随逗号

尾部的逗号通常是可选的,但当组成一个元素的元组时它们是必需的(并且在Python 2中,它们具有print语句的语义)。为了清楚起见,建议将后者用(技术上多余的)括号括起来。

是:

FILES = ('setup.cfg',)

好的,但是令人困惑:

FILES = 'setup.cfg',

如果结尾的逗号多余,则在使用版本控制系统时,当值,参数或导入项的列表预计会随着时间扩展时,它们通常会很有用。模式是将每个值(等)单独放在一行上,始终添加尾随逗号,并在下一行上添加右括号/括号/括号。但是,在与结束定界符相同的行上使用尾随逗号是没有意义的(在上述单例元组的情况下除外)。

是:

FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

没有:

FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

PEP 8 — Style Guide for Python Code – When to Use Trailing Commas

Trailing commas are usually optional, except they are mandatory when making a tuple of one element (and in Python 2 they have semantics for the print statement). For clarity, it is recommended to surround the latter in (technically redundant) parentheses.

Yes:

FILES = ('setup.cfg',)

OK, but confusing:

FILES = 'setup.cfg',

When trailing commas are redundant, they are often helpful when a version control system is used, when a list of values, arguments or imported items is expected to be extended over time. The pattern is to put each value (etc.) on a line by itself, always adding a trailing comma, and add the close parenthesis/bracket/brace on the next line. However it does not make sense to have a trailing comma on the same line as the closing delimiter (except in the above case of singleton tuples).

Yes:

FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

No:

FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

回答 9

编码风格是您的喜好,如果您认为编码标准很重要,那么可以使用PEP-8指导您。

您如何看待以下表达的结果?

x = (3)
x = (3+2)
x = 2*(3+2)

是的,x只是一个数字。

Coding style is your taste, If you think coding standard matters there is a PEP-8 That can guide you.

What do you think of the result of following expression?

x = (3)
x = (3+2)
x = 2*(3+2)

Yep, x is just an number.


为什么在Python中“ 0,0 ==(0,0)”等于“(0,False)”?

问题:为什么在Python中“ 0,0 ==(0,0)”等于“(0,False)”?

在Python中(我仅使用Python 3.6进行过检查,但我相信它也适用于许多以前的版本):

(0, 0) == 0, 0   # results in a two element tuple: (False, 0)
0, 0 == (0, 0)   # results in a two element tuple: (0, False)
(0, 0) == (0, 0) # results in a boolean True

但:

a = 0, 0
b = (0, 0)
a == b # results in a boolean True

为什么两种方法的结果不同?相等运算符是否以不同的方式处理元组?

In Python (I checked only with Python 3.6 but I believe it should hold for many of the previous versions as well):

(0, 0) == 0, 0   # results in a two element tuple: (False, 0)
0, 0 == (0, 0)   # results in a two element tuple: (0, False)
(0, 0) == (0, 0) # results in a boolean True

But:

a = 0, 0
b = (0, 0)
a == b # results in a boolean True

Why does the result differ between the two approaches? Does the equality operator handle tuples differently?


回答 0

前两个表达式都解析为元组:

  1. (0, 0) == 0(即False),然后是0
  2. 0,其次是0 == (0, 0)(仍然False如此)。

由于逗号分隔符相对于相等运算符具有较高的优先级,因此将表达式进行拆分:Python看到一个元组包含两个表达式,其中一个恰好是一个相等测试,而不是两个元组之间的相等测试。

但是在第二组语句中,a = 0, 0 不能是元组。元组是值的集合,与相等性测试不同,赋值在Python中没有值。赋值不是表达式,而是语句。它没有可包含在元组或任何其他周围表达式中的值。如果您尝试执行类似(a = 0), 0的操作以强制将其解释为元组,则会出现语法错误。这样,将元组分配给变量(可以通过编写使其更明确)a = (0, 0)作为对的唯一有效解释a = 0, 0

因此,即使没有对的括号a,它和都b获得了赋值(0,0),因此a == b也是如此True

The first two expressions both parse as tuples:

  1. (0, 0) == 0 (which is False), followed by 0
  2. 0, followed by 0 == (0, 0) (which is still False that way around).

The expressions are split that way because of the relative precedence of the comma separator compared to the equality operator: Python sees a tuple containing two expressions, one of which happens to be an equality test, instead of an equality test between two tuples.

But in your second set of statements, a = 0, 0 cannot be a tuple. A tuple is a collection of values, and unlike an equality test, assignment has no value in Python. An assignment is not an expression, but a statement; it does not have a value that can be included into a tuple or any other surrounding expression. If you tried something like (a = 0), 0 in order to force interpretation as a tuple, you would get a syntax error. That leaves the assignment of a tuple to a variable – which could be made more explicit by writing it a = (0, 0) – as the only valid interpretation of a = 0, 0.

So even without the parentheses on the assignment to a, both it and b get assigned the value (0,0), so a == b is therefore True.


回答 1

您在所有3种情况下看到的都是语言语法规范的结果,以及如何解析源代码中遇到的标记以生成解析树。

看看这个低级代码应该可以帮助您了解幕后情况。我们可以使用以下python语句,将它们转换为字节码,然后使用以下dis模块对其进行反编译:

情况1: (0, 0) == 0, 0

>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               0 (0)
              6 COMPARE_OP               2 (==)
              9 LOAD_CONST               0 (0)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

(0, 0)首先与0第一个进行比较,然后对进行评估False。然后,使用此结果构造一个元组,最后0得到结果(False, 0)

情况2: 0, 0 == (0, 0)

>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               0 (0)
              3 LOAD_CONST               0 (0)
              6 LOAD_CONST               2 ((0, 0))
              9 COMPARE_OP               2 (==)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

将元组构造0为第一个元素。对于第二个元素,执行与第一种情况相同的检查,并求值为False,因此得到(0, False)

情况3: (0, 0) == (0, 0)

>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               3 ((0, 0))
              6 COMPARE_OP               2 (==)
              9 POP_TOP
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

如您所见,在这里,您只是比较这两个(0, 0)元组并返回True

What you see in all 3 instances is a consequence of the grammar specification of the language, and how tokens encountered in the source code are parsed to generate the parse tree.

Taking a look at this low level code should help you understand what happens under the hood. We can take these python statements, convert them into byte code and then decompile them using the dis module:

Case 1: (0, 0) == 0, 0

>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               0 (0)
              6 COMPARE_OP               2 (==)
              9 LOAD_CONST               0 (0)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

(0, 0) is first compared to 0 first and evaluated to False. A tuple is then constructed with this result and last 0, so you get (False, 0).

Case 2: 0, 0 == (0, 0)

>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               0 (0)
              3 LOAD_CONST               0 (0)
              6 LOAD_CONST               2 ((0, 0))
              9 COMPARE_OP               2 (==)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

A tuple is constructed with 0 as the first element. For the second element, the same check is done as in the first case and evaluated to False, so you get (0, False).

Case 3: (0, 0) == (0, 0)

>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               3 ((0, 0))
              6 COMPARE_OP               2 (==)
              9 POP_TOP
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

Here, as you see, you’re just comparing those two (0, 0) tuples and returning True.


回答 2

解释问题的另一种方法:您可能熟悉字典文字

{ "a": 1, "b": 2, "c": 3 }

和数组文字

[ "a", "b", "c" ]

和元组文字

( 1, 2, 3 )

但是您没有意识到的是,与字典和数组文字不同,您通常在元组文字周围看到的括号不是文字语法的一部分。元组的文字语法只是一系列用逗号分隔的表达式:

1, 2, 3

Python形式语法语言中的“ exprlist” )。

现在,您期望数组文字是什么

[ 0, 0 == (0, 0) ]

评价?看起来可能更像是应该

[ 0, (0 == (0, 0)) ]

当然是哪个[0, False]。类似地,使用显式带括号的元组文字

( 0, 0 == (0, 0) )

得到并不奇怪(0, False)。但是括号是可选的。

0, 0 == (0, 0)

是同一回事。这就是为什么你得到(0, False)


如果您想知道为什么元组文字周围的括号是可选的,那主要是因为必须以这种方式编写解构分配会很烦人:

(a, b) = (c, d) # meh
a, b = c, d     # better

Another way to explain the problem: You’re probably familiar with dictionary literals

{ "a": 1, "b": 2, "c": 3 }

and array literals

[ "a", "b", "c" ]

and tuple literals

( 1, 2, 3 )

but what you don’t realize is that, unlike dictionary and array literals, the parentheses you usually see around a tuple literal are not part of the literal syntax. The literal syntax for tuples is just a sequence of expressions separated by commas:

1, 2, 3

(an “exprlist” in the language of the formal grammar for Python).

Now, what do you expect the array literal

[ 0, 0 == (0, 0) ]

to evaluate to? That probably looks a lot more like it should be the same as

[ 0, (0 == (0, 0)) ]

which of course evaluates to [0, False]. Similarly, with an explicitly parenthesized tuple literal

( 0, 0 == (0, 0) )

it’s not surprising to get (0, False). But the parentheses are optional;

0, 0 == (0, 0)

is the same thing. And that’s why you get (0, False).


If you’re wondering why the parentheses around a tuple literal are optional, it is largely because it would be annoying to have to write destructuring assignments that way:

(a, b) = (c, d) # meh
a, b = c, d     # better

回答 3

在执行操作的顺序周围加上几个括号可以帮助您更好地理解结果:

# Build two element tuple comprising of 
# (0, 0) == 0 result and 0
>>> ((0, 0) == 0), 0
(False, 0)

# Build two element tuple comprising of
# 0 and result of (0, 0) == 0 
>>> 0, (0 == (0, 0))
(0, False)

# Create two tuples with elements (0, 0) 
# and compare them
>>> (0, 0) == (0, 0) 
True

逗号用于分隔表达式(使用括号,我们可以强制使用不同的行为)。查看您列出的代码段时,逗号,会将其分开并定义将对哪些表达式求值:

(0, 0) == 0 ,   0
#-----------|------
  expr 1      expr2

元组(0, 0)也可以类似的方式分解。逗号分隔两个包含文字的表达式0

Adding a couple of parentheses around the order in which actions are performed might help you understand the results better:

# Build two element tuple comprising of 
# (0, 0) == 0 result and 0
>>> ((0, 0) == 0), 0
(False, 0)

# Build two element tuple comprising of
# 0 and result of (0, 0) == 0 
>>> 0, (0 == (0, 0))
(0, False)

# Create two tuples with elements (0, 0) 
# and compare them
>>> (0, 0) == (0, 0) 
True

The comma is used to to separate expressions (using parentheses we can force different behavior, of course). When viewing the snippets you listed, the comma , will separate it and define what expressions will get evaluated:

(0, 0) == 0 ,   0
#-----------|------
  expr 1      expr2

The tuple (0, 0) can also be broken down in a similar way. The comma separates two expressions comprising of the literals 0.


回答 4

在第一个示例中,Python将两件事变成元组:

  1. 表达式(0, 0) == 0,其计算结果为False
  2. 常数 0

在第二个方面则相反。

In the first one Python is making a tuple of two things:

  1. The expression (0, 0) == 0, which evaluates to False
  2. The constant 0

In the second one it’s the other way around.


回答 5

看这个例子:

r = [1,0,1,0,1,1,0,0,0,1]
print(r==0,0,r,1,0)
print(r==r,0,1,0,1,0)

然后结果:

False 0 [1, 0, 1, 0, 1, 1, 0, 0, 0, 1] 1 0
True 0 1 0 1 0

然后比较就和示例中的第一个数字(0和r)进行比较。

look at this example:

r = [1,0,1,0,1,1,0,0,0,1]
print(r==0,0,r,1,0)
print(r==r,0,1,0,1,0)

then result:

False 0 [1, 0, 1, 0, 1, 1, 0, 0, 0, 1] 1 0
True 0 1 0 1 0

then comparison just does to the first number(0 and r) in the example.


如何从元组列表中提取第n个元素?

问题:如何从元组列表中提取第n个元素?

我正在尝试从元组列表中获取第n个元素。

我有类似的东西:

elements = [(1,1,1),(2,3,7),(3,5,10)]

我希望仅将每个元组的第二个元素提取到列表中:

seconds = [1, 3, 5]

我知道可以通过for循环来完成,但是我想知道是否有另一种方法,因为我有成千上万的元组。

I’m trying to obtain the n-th elements from a list of tuples.

I have something like:

elements = [(1,1,1),(2,3,7),(3,5,10)]

I wish to extract only the second elements of each tuple into a list:

seconds = [1, 3, 5]

I know that it could be done with a for loop but I wanted to know if there’s another way since I have thousands of tuples.


回答 0

n = 1 # N. . .
[x[n] for x in elements]
n = 1 # N. . .
[x[n] for x in elements]

回答 1

这也适用:

zip(*elements)[1]

(我主要是在发布此信息,以向自己证明我已经厌倦了zip……)

实际观看:

>>> help(zip)

内置模块的内置功能zip的帮助:

压缩(…)

zip(seq1 [,seq2 […]])-> [(seq1 [0],seq2 [0] …),(…)]

返回一个元组列表,其中每个元组包含每个参数序列中的第i个元素。返回的列表的长度被截断为最短参数序列的长度。

>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> zip(*elements)
[(1, 2, 3), (1, 3, 5), (1, 7, 10)]
>>> zip(*elements)[1]
(1, 3, 5)
>>>

我今天学到的整洁的东西:使用*list自变量为函数创建参数列表…

注意:在Python3中,zip返回一个迭代器,因此请使用list(zip(*elements))返回一个元组列表。

This also works:

zip(*elements)[1]

(I am mainly posting this, to prove to myself that I have groked zip…)

See it in action:

>>> help(zip)

Help on built-in function zip in module builtin:

zip(…)

zip(seq1 [, seq2 […]]) -> [(seq1[0], seq2[0] …), (…)]

Return a list of tuples, where each tuple contains the i-th element from each of the argument sequences. The returned list is truncated in length to the length of the shortest argument sequence.

>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> zip(*elements)
[(1, 2, 3), (1, 3, 5), (1, 7, 10)]
>>> zip(*elements)[1]
(1, 3, 5)
>>>

Neat thing I learned today: Use *list in arguments to create a parameter list for a function…

Note: In Python3, zip returns an iterator, so instead use list(zip(*elements)) to return a list of tuples.


回答 2

我知道可以用FOR完成,但是我想知道是否还有其他方法

还有另一种方式。您也可以使用mapitemgetter来做到这一点:

>>> from operator import itemgetter
>>> map(itemgetter(1), elements)

但是,这仍然在内部执行循环,并且比列表理解要慢一些:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))

结果:

方法1:1.25699996948
方法2:1.46600008011

如果您需要遍历列表,则可以使用a for

I know that it could be done with a FOR but I wanted to know if there’s another way

There is another way. You can also do it with map and itemgetter:

>>> from operator import itemgetter
>>> map(itemgetter(1), elements)

This still performs a loop internally though and it is slightly slower than the list comprehension:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))

Results:

Method 1: 1.25699996948
Method 2: 1.46600008011

If you need to iterate over a list then using a for is fine.


回答 3

我在寻找哪种方式最快地拉出2元组列表的第二个元素时发现了这一点。不是我想要的,但是运行了与第3种方法所示相同的测试,并测试了zip方法

setup = 'elements = [(1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'
method3 = 'dict(elements).values()'
method4 = 'zip(*elements)[1]'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup)
print('Method 3: ' + str(t.timeit(100)))
t = timeit.Timer(method4, setup)
print('Method 4: ' + str(t.timeit(100)))

Method 1: 0.618785858154
Method 2: 0.711684942245
Method 3: 0.298138141632
Method 4: 1.32586884499

因此,如果您有2个元组对,只需将其转换为dict并取值就可以快两倍。

Found this as I was searching for which way is fastest to pull the second element of a 2-tuple list. Not what I wanted but ran same test as shown with a 3rd method plus test the zip method

setup = 'elements = [(1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'
method3 = 'dict(elements).values()'
method4 = 'zip(*elements)[1]'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup)
print('Method 3: ' + str(t.timeit(100)))
t = timeit.Timer(method4, setup)
print('Method 4: ' + str(t.timeit(100)))

Method 1: 0.618785858154
Method 2: 0.711684942245
Method 3: 0.298138141632
Method 4: 1.32586884499

So over twice as fast if you have a 2 tuple pair to just convert to a dict and take the values.


回答 4

Python 3.6的计时,用于从2元组列表中提取第二个元素。

另外,添加了numpy数组方法,该方法更易于阅读(但可以说比列表理解更简单)。

from operator import itemgetter
elements = [(1,1) for _ in range(100000)]

%timeit second = [x[1] for x in elements]
%timeit second = list(map(itemgetter(1), elements))
%timeit second = dict(elements).values()
%timeit second = list(zip(*elements))[1]
%timeit second = np.array(elements)[:,1]

和时间:

list comprehension:  4.73 ms ± 206 µs per loop
list(map):           5.3 ms ± 167 µs per loop
dict:                2.25 ms ± 103 µs per loop
list(zip)            5.2 ms ± 252 µs per loop
numpy array:        28.7 ms ± 1.88 ms per loop

请注意,map()并且zip()不再返回列表,因此进行了显式转换。

Timings for Python 3.6 for extracting the second element from a 2-tuple list.

Also, added numpy array method, which is simpler to read (but arguably simpler than the list comprehension).

from operator import itemgetter
elements = [(1,1) for _ in range(100000)]

%timeit second = [x[1] for x in elements]
%timeit second = list(map(itemgetter(1), elements))
%timeit second = dict(elements).values()
%timeit second = list(zip(*elements))[1]
%timeit second = np.array(elements)[:,1]

and the timings:

list comprehension:  4.73 ms ± 206 µs per loop
list(map):           5.3 ms ± 167 µs per loop
dict:                2.25 ms ± 103 µs per loop
list(zip)            5.2 ms ± 252 µs per loop
numpy array:        28.7 ms ± 1.88 ms per loop

Note that map() and zip() do not return a list anymore, hence the explicit conversion.


回答 5

map (lambda x:(x[1]),elements)
map (lambda x:(x[1]),elements)

回答 6

使用islicechain.from_iterable

>>> from itertools import chain, islice
>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> list(chain.from_iterable(islice(item, 1, 2) for item in elements))
[1, 3, 5]

当您需要多个元素时,这可能会很有用:

>>> elements = [(0, 1, 2, 3, 4, 5), 
                (10, 11, 12, 13, 14, 15), 
                (20, 21, 22, 23, 24, 25)]
>>> list(chain.from_iterable(islice(tuple_, 2, 5) for tuple_ in elements))
[2, 3, 4, 12, 13, 14, 22, 23, 24]

Using islice and chain.from_iterable:

>>> from itertools import chain, islice
>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> list(chain.from_iterable(islice(item, 1, 2) for item in elements))
[1, 3, 5]

This can be useful when you need more than one element:

>>> elements = [(0, 1, 2, 3, 4, 5), 
                (10, 11, 12, 13, 14, 15), 
                (20, 21, 22, 23, 24, 25)]
>>> list(chain.from_iterable(islice(tuple_, 2, 5) for tuple_ in elements))
[2, 3, 4, 12, 13, 14, 22, 23, 24]

字典元组列表

问题:字典元组列表

这是我目前在Python中将元组列表转换为字典的方式:

l = [('a',1),('b',2)]
h = {}
[h.update({k:v}) for k,v in l]
> [None, None]
h
> {'a': 1, 'b': 2}

有没有更好的办法?似乎应该有一种做法。

Here’s how I’m currently converting a list of tuples to dictionary in Python:

l = [('a',1),('b',2)]
h = {}
[h.update({k:v}) for k,v in l]
> [None, None]
h
> {'a': 1, 'b': 2}

Is there a better way? It seems like there should be a one-liner to do this.


回答 0

只需dict()直接调用元组列表

>>> my_list = [('a', 1), ('b', 2)]
>>> dict(my_list)
{'a': 1, 'b': 2}

Just call dict() on the list of tuples directly

>>> my_list = [('a', 1), ('b', 2)]
>>> dict(my_list)
{'a': 1, 'b': 2}

回答 1

dict构造函数接受输入的完全一样,你把它(键/值元组)。

>>> l = [('a',1),('b',2)]
>>> d = dict(l)
>>> d
{'a': 1, 'b': 2}

文档中

例如,所有这些都返回等于{“ one”:1,“ two”:2}的字典:

dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

The dict constructor accepts input exactly as you have it (key/value tuples).

>>> l = [('a',1),('b',2)]
>>> d = dict(l)
>>> d
{'a': 1, 'b': 2}

From the documentation:

For example, these all return a dictionary equal to {“one”: 1, “two”: 2}:

dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

回答 2

具有dict理解力:

h = {k:v for k,v in l}

With dict comprehension:

h = {k:v for k,v in l}

回答 3

似乎每个人都假定元组列表在键和值之间具有一对一的映射关系(例如,它没有字典的重复键)。由于这是在该主题上搜索的第一个问题,因此我针对一个更常见的情况发布了答案,在这种情况下,我们必须处理重复项:

mylist = [(a,1),(a,2),(b,3)]    
result = {}
for i in mylist:  
   result.setdefault(i[0],[]).append(i[1])
print(result)
>>> result = {a:[1,2], b:[3]}

It seems everyone here assumes the list of tuples have one to one mapping between key and values (e.g. it does not have duplicated keys for the dictionary). As this is the first question coming up searching on this topic, I post an answer for a more general case where we have to deal with duplicates:

mylist = [(a,1),(a,2),(b,3)]    
result = {}
for i in mylist:  
   result.setdefault(i[0],[]).append(i[1])
print(result)
>>> result = {a:[1,2], b:[3]}

Python将元组转换为字符串

问题:Python将元组转换为字符串

我有一个这样的字符元组:

('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e')

我如何将其转换为字符串,使其类似于:

'abcdgxre'

I have a tuple of characters like such:

('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e')

How do I convert it to a string so that it is like:

'abcdgxre'

回答 0

用途str.join

>>> tup = ('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e')
>>> ''.join(tup)
'abcdgxre'
>>>
>>> help(str.join)
Help on method_descriptor:

join(...)
    S.join(iterable) -> str

    Return a string which is the concatenation of the strings in the
    iterable.  The separator between elements is S.

>>>

Use str.join:

>>> tup = ('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e')
>>> ''.join(tup)
'abcdgxre'
>>>
>>> help(str.join)
Help on method_descriptor:

join(...)
    S.join(iterable) -> str

    Return a string which is the concatenation of the strings in the
    iterable.  The separator between elements is S.

>>>

回答 1

这是使用联接的一种简单方法。

''.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

here is an easy way to use join.

''.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

回答 2

这有效:

''.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

它将生成:

'abcdgxre'

您还可以使用定界符(例如逗号)来生成:

'a,b,c,d,g,x,r,e'

通过使用:

','.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

This works:

''.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

It will produce:

'abcdgxre'

You can also use a delimiter like a comma to produce:

'a,b,c,d,g,x,r,e'

By using:

','.join(('a', 'b', 'c', 'd', 'g', 'x', 'r', 'e'))

回答 3

最简单的方法是像这样使用join:

>>> myTuple = ['h','e','l','l','o']
>>> ''.join(myTuple)
'hello'

之所以有效,是因为您的定界符实际上什么都没有,甚至没有空格:”。

Easiest way would be to use join like this:

>>> myTuple = ['h','e','l','l','o']
>>> ''.join(myTuple)
'hello'

This works because your delimiter is essentially nothing, not even a blank space: ”.


Python:字典列表,如果存在,则增加一个字典值,如果不增加新字典

问题:Python:字典列表,如果存在,则增加一个字典值,如果不增加新字典

我想做类似的事情。

list_of_urls = ['http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.cn/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.cn/']

urls = [{'url': 'http://www.google.fr/', 'nbr': 1}]

for url in list_of_urls:
    if url in [f['url'] for f in urls]:
         urls[??]['nbr'] += 1
    else:
         urls.append({'url': url, 'nbr': 1})

我能怎么做 ?我不知道该选择元组来编辑它还是找出元组索引?

有什么帮助吗?

I would like do something like that.

list_of_urls = ['http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.cn/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.cn/']

urls = [{'url': 'http://www.google.fr/', 'nbr': 1}]

for url in list_of_urls:
    if url in [f['url'] for f in urls]:
         urls[??]['nbr'] += 1
    else:
         urls.append({'url': url, 'nbr': 1})

How can I do ? I don’t know if I should take the tuple to edit it or figure out the tuple indices?

Any help ?


回答 0

那是组织事情的一种非常奇怪的方式。如果存储在字典中,这很容易:

# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
    if not url in urls_d:
        urls_d[url] = 1
    else:
        urls_d[url] += 1

这段更新计数字典的代码是Python中常见的“模式”。常见的是defaultdict,创建了一个特殊的数据结构,以使其变得更加容易:

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

如果您defaultdict使用键访问,而该键尚未在中defaultdict,则该键会自动添加一个默认值。将defaultdict采取调用您传递,并调用它来获得默认值。在这种情况下,我们在课堂上通过了int;当Python调用时,int()它返回零值。因此,第一次引用URL时,其计数将初始化为零,然后将一个添加到计数中。

但是充满计数的字典也是一种常见的模式,因此Python提供了一个现成的类:containers.Counter 您只需Counter通过调用该类并传递任何可迭代的类来创建实例;它会建立一个字典,其中的键是可迭代的值,而值是键在可迭代中出现的次数的计数。上面的示例变为:

from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)

如果您确实需要按照显示的方式进行操作,则最简单,最快的方法是使用这三个示例中的任何一个,然后构建所需的示例。

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]

如果您使用的是Python 2.7或更高版本,则可以单行执行:

from collections import Counter

urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]

That is a very strange way to organize things. If you stored in a dictionary, this is easy:

# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
    if not url in urls_d:
        urls_d[url] = 1
    else:
        urls_d[url] += 1

This code for updating a dictionary of counts is a common “pattern” in Python. It is so common that there is a special data structure, defaultdict, created just to make this even easier:

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

If you access the defaultdict using a key, and the key is not already in the defaultdict, the key is automatically added with a default value. The defaultdict takes the callable you passed in, and calls it to get the default value. In this case, we passed in class int; when Python calls int() it returns a zero value. So, the first time you reference a URL, its count is initialized to zero, and then you add one to the count.

But a dictionary full of counts is also a common pattern, so Python provides a ready-to-use class: containers.Counter You just create a Counter instance by calling the class, passing in any iterable; it builds a dictionary where the keys are values from the iterable, and the values are counts of how many times the key appeared in the iterable. The above example then becomes:

from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)

If you really need to do it the way you showed, the easiest and fastest way would be to use any one of these three examples, and then build the one you need.

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]

If you are using Python 2.7 or newer you can do it in a one-liner:

from collections import Counter

urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]

回答 1

使用默认值可以,但是:

urls[url] = urls.get(url, 0) + 1

使用.get,可以获取默认返回值(如果不存在)。默认情况下为None,但如果我发送给您,则为0。

Using the default works, but so does:

urls[url] = urls.get(url, 0) + 1

using .get, you can get a default return if it doesn’t exist. By default it’s None, but in the case I sent you, it would be 0.


回答 2

使用defaultdict

from collections import defaultdict

urls = defaultdict(int)

for url in list_of_urls:
    urls[url] += 1

Use defaultdict:

from collections import defaultdict

urls = defaultdict(int)

for url in list_of_urls:
    urls[url] += 1

回答 3

这对我来说总是正常的:

for url in list_of_urls:
    urls.setdefault(url, 0)
    urls[url] += 1

This always works fine for me:

for url in list_of_urls:
    urls.setdefault(url, 0)
    urls[url] += 1

回答 4

完全按照您的方式来做?您可以使用for … else结构

for url in list_of_urls:
    for url_dict in urls:
        if url_dict['url'] == url:
            url_dict['nbr'] += 1
            break
    else:
        urls.append(dict(url=url, nbr=1))

但这是很不雅观的。您是否真的必须将访问的URL存储为LIST?例如,如果将其排序为dict,并以url字符串索引,则它会更干净:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}

for url in list_of_urls:
    if url in urls:
        urls[url]['nbr'] += 1
    else:
        urls[url] = dict(url=url, nbr=1)

在第二个示例中需要注意的几件事:

  • 了解测试单个测试时如何使用dict urls消除整个urls列表的需求url。这种方法将更快。
  • 使用dict( )大括号代替您的代码
  • 使用list_of_urlsurlsurl作为变量名使代码挺难解析。这是更好地找到一些更清晰的,如urls_to_visiturls_already_visitedcurrent_url。我知道,时间更长。但这更清楚。

当然,我假设这dict(url='http://www.google.fr', nbr=1)是您自己的数据结构的简化,因为否则,urls可能只是:

urls = {'http://www.google.fr':1}

for url in list_of_urls:
    if url in urls:
        urls[url] += 1
    else:
        urls[url] = 1

使用defaultdict姿势可以很优雅:

urls = collections.defaultdict(int)
for url in list_of_urls:
    urls[url] += 1

To do it exactly your way? You could use the for…else structure

for url in list_of_urls:
    for url_dict in urls:
        if url_dict['url'] == url:
            url_dict['nbr'] += 1
            break
    else:
        urls.append(dict(url=url, nbr=1))

But it is quite inelegant. Do you really have to store the visited urls as a LIST? If you sort it as a dict, indexed by url string, for example, it would be way cleaner:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}

for url in list_of_urls:
    if url in urls:
        urls[url]['nbr'] += 1
    else:
        urls[url] = dict(url=url, nbr=1)

A few things to note in that second example:

  • see how using a dict for urls removes the need for going through the whole urls list when testing for one single url. This approach will be faster.
  • Using dict( ) instead of braces makes your code shorter
  • using list_of_urls, urls and url as variable names make the code quite hard to parse. It’s better to find something clearer, such as urls_to_visit, urls_already_visited and current_url. I know, it’s longer. But it’s clearer.

And of course I’m assuming that dict(url='http://www.google.fr', nbr=1) is a simplification of your own data structure, because otherwise, urls could simply be:

urls = {'http://www.google.fr':1}

for url in list_of_urls:
    if url in urls:
        urls[url] += 1
    else:
        urls[url] = 1

Which can get very elegant with the defaultdict stance:

urls = collections.defaultdict(int)
for url in list_of_urls:
    urls[url] += 1

回答 5

除了第一次以外,每次看到一个单词时,if语句的测试都会失败。如果您要计算大量的单词,许多单词可能会多次出现。在一个值的初始化仅发生一次且该值的增加将发生多次的情况下,使用try语句会更便宜:

urls_d = {}
for url in list_of_urls:
    try:
        urls_d[url] += 1
    except KeyError:
        urls_d[url] = 1

您可以阅读有关此内容的更多信息:https : //wiki.python.org/moin/PythonSpeed/PerformanceTips

Except for the first time, each time a word is seen the if statement’s test fails. If you are counting a large number of words, many will probably occur multiple times. In a situation where the initialization of a value is only going to occur once and the augmentation of that value will occur many times it is cheaper to use a try statement:

urls_d = {}
for url in list_of_urls:
    try:
        urls_d[url] += 1
    except KeyError:
        urls_d[url] = 1

you can read more about this: https://wiki.python.org/moin/PythonSpeed/PerformanceTips