分类目录归档:知识问答

如何确定Python变量的类型?

问题:如何确定Python变量的类型?

我如何查看变量的类型(无符号32位,带符号16位等)?

我怎么看?

How do I see the type of a variable whether it is unsigned 32 bit, signed 16 bit, etc.?

How do I view it?


回答 0

使用type()内置功能:

>>> i = 123
>>> type(i)
<type 'int'>
>>> type(i) is int
True
>>> i = 123.456
>>> type(i)
<type 'float'>
>>> type(i) is float
True

要检查变量是否属于给定类型,请使用isinstance

>>> i = 123
>>> isinstance(i, int)
True
>>> isinstance(i, (float, str, set, dict))
False

请注意,Python与C / C ++的类型不同,这似乎是您的问题。

Use the type() builtin function:

>>> i = 123
>>> type(i)
<type 'int'>
>>> type(i) is int
True
>>> i = 123.456
>>> type(i)
<type 'float'>
>>> type(i) is float
True

To check if a variable is of a given type, use isinstance:

>>> i = 123
>>> isinstance(i, int)
True
>>> isinstance(i, (float, str, set, dict))
False

Note that Python doesn’t have the same types as C/C++, which appears to be your question.


回答 1

您可能正在寻找内置功能type()

请参见下面的示例,但是Python中没有像Java这样的“无符号”类型。

正整数:

>>> v = 10
>>> type(v)
<type 'int'>

正整数:

>>> v = 100000000000000
>>> type(v)
<type 'long'>

负整数:

>>> v = -10
>>> type(v)
<type 'int'>

字符的文字顺序:

>>> v = 'hi'
>>> type(v)
<type 'str'>

浮点整数:

>>> v = 3.14159
>>> type(v)
<type 'float'>

You may be looking for the type() built-in function.

See the examples below, but there’s no “unsigned” type in Python just like Java.

Positive integer:

>>> v = 10
>>> type(v)
<type 'int'>

Large positive integer:

>>> v = 100000000000000
>>> type(v)
<type 'long'>

Negative integer:

>>> v = -10
>>> type(v)
<type 'int'>

Literal sequence of characters:

>>> v = 'hi'
>>> type(v)
<type 'str'>

Floating point integer:

>>> v = 3.14159
>>> type(v)
<type 'float'>

回答 2

很简单。你是这样做的。

print(type(variable_name))

It is so simple. You do it like this.

print(type(variable_name))

回答 3

如何在Python中确定变量类型?

因此,如果您有一个变量,例如:

one = 1

您想知道它的类型吗?

在Python中几乎所有事情都有正确的方法和错误的方法。这是正确的方法:

采用 type

>>> type(one)
<type 'int'>

您可以使用该__name__属性来获取对象的名称。(这是使用__dunder__名称获取所需的少数几个特殊属性之一- inspect模块中甚至没有方法可以使用。)

>>> type(one).__name__
'int'

不要使用 __class__

在Python中,以下划线开头的名称在语义上不属于公共API的一部分,这是用户避免使用它们的最佳实践。(除非绝对必要。)

由于type给了我们对象的类,我们应该避免直接得到它。:

>>> one.__class__

通常,这是人们在访问方法中的对象类型时首先想到的-他们已经在寻找属性,因此类型似乎很奇怪。例如:

class Foo(object):
    def foo(self):
        self.__class__

别。相反,请执行type(self):

class Foo(object):
    def foo(self):
        type(self)

int和float的实现细节

我如何查看变量的类型(无符号32位,带符号16位等)?

在Python中,这些细节是实现细节。因此,总的来说,在Python中我们通常不必担心这一点。但是,要满足您的好奇心…

在Python 2中,int通常是一个有符号整数,等于实现的宽(受系统限制)。通常在C中实现为long。当整数变得更大时,我们通常将它们转换为Python long(精度不受限制,不要与C long混淆)。

例如,在32位Python 2中,我们可以推论int是一个有符号的32位整数:

>>> import sys

>>> format(sys.maxint, '032b')
'01111111111111111111111111111111'
>>> format(-sys.maxint - 1, '032b') # minimum value, see docs.
'-10000000000000000000000000000000'

在Python 3中,旧的int消失了,而我们只使用(Python的)long int,它具有无限的精度。

我们还可以获得有关Python浮点数的信息,这些浮点数通常在C语言中以double形式实现:

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, 
min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, 
mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

结论

不要使用__class__语义上非公共的API来获取变量的类型。使用type代替。

而且不必太担心Python的实现细节。我自己不必处理这个问题。您可能也不会这样做,而且如果您确实做到了,那么您应该了解得足够多,不要去寻找该答案的答案。

How to determine the variable type in Python?

So if you have a variable, for example:

one = 1

You want to know its type?

There are right ways and wrong ways to do just about everything in Python. Here’s the right way:

Use type

>>> type(one)
<type 'int'>

You can use the __name__ attribute to get the name of the object. (This is one of the few special attributes that you need to use the __dunder__ name to get to – there’s not even a method for it in the inspect module.)

>>> type(one).__name__
'int'

Don’t use __class__

In Python, names that start with underscores are semantically not a part of the public API, and it’s a best practice for users to avoid using them. (Except when absolutely necessary.)

Since type gives us the class of the object, we should avoid getting this directly. :

>>> one.__class__

This is usually the first idea people have when accessing the type of an object in a method – they’re already looking for attributes, so type seems weird. For example:

class Foo(object):
    def foo(self):
        self.__class__

Don’t. Instead, do type(self):

class Foo(object):
    def foo(self):
        type(self)

Implementation details of ints and floats

How do I see the type of a variable whether it is unsigned 32 bit, signed 16 bit, etc.?

In Python, these specifics are implementation details. So, in general, we don’t usually worry about this in Python. However, to sate your curiosity…

In Python 2, int is usually a signed integer equal to the implementation’s word width (limited by the system). It’s usually implemented as a long in C. When integers get bigger than this, we usually convert them to Python longs (with unlimited precision, not to be confused with C longs).

For example, in a 32 bit Python 2, we can deduce that int is a signed 32 bit integer:

>>> import sys

>>> format(sys.maxint, '032b')
'01111111111111111111111111111111'
>>> format(-sys.maxint - 1, '032b') # minimum value, see docs.
'-10000000000000000000000000000000'

In Python 3, the old int goes away, and we just use (Python’s) long as int, which has unlimited precision.

We can also get some information about Python’s floats, which are usually implemented as a double in C:

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, 
min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, 
mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

Conclusion

Don’t use __class__, a semantically nonpublic API, to get the type of a variable. Use type instead.

And don’t worry too much about the implementation details of Python. I’ve not had to deal with issues around this myself. You probably won’t either, and if you really do, you should know enough not to be looking to this answer for what to do.


回答 4

print type(variable_name)

在处理此类问题时,我也强烈建议使用IPython交互式解释器。它使您可以键入内容variable_name?,并返回有关该对象的信息的完整列表,包括类型和该类型的文档字符串。

例如

In [9]: var = 123

In [10]: var?
Type:       int
Base Class: <type 'int'>
String Form:    123
Namespace:  Interactive
Docstring:
    int(x[, base]) -> integer

如果可能,将字符串或数字转换为整数。浮点参数将被截断为零(不包括浮点数的字符串表示!)在转换字符串时,请使用可选的基数。转换非字符串时提供基数是错误的。如果参数在整数范围之外,则将返回一个长对象。

print type(variable_name)

I also highly recommend the IPython interactive interpreter when dealing with questions like this. It lets you type variable_name? and will return a whole list of information about the object including the type and the doc string for the type.

e.g.

In [9]: var = 123

In [10]: var?
Type:       int
Base Class: <type 'int'>
String Form:    123
Namespace:  Interactive
Docstring:
    int(x[, base]) -> integer

Convert a string or number to an integer, if possible. A floating point argument will be truncated towards zero (this does not include a string representation of a floating point number!) When converting a string, use the optional base. It is an error to supply a base when converting a non-string. If the argument is outside the integer range a long object will be returned instead.


回答 5

a = "cool"
type(a)

//result 'str'
<class 'str'>
or 
do 
`dir(a)` 
to see the list of inbuilt methods you can have on the variable.
a = "cool"
type(a)

//result 'str'
<class 'str'>
or 
do 
`dir(a)` 
to see the list of inbuilt methods you can have on the variable.

回答 6

另一种使用方式__class__

>>> a = [1, 2, 3, 4]
>>> a.__class__
<type 'list'>
>>> b = {'key1': 'val1'}
>>> b.__class__
<type 'dict'>
>>> c = 12
>>> c.__class__
<type 'int'>

One more way using __class__:

>>> a = [1, 2, 3, 4]
>>> a.__class__
<type 'list'>
>>> b = {'key1': 'val1'}
>>> b.__class__
<type 'dict'>
>>> c = 12
>>> c.__class__
<type 'int'>

回答 7

Python中简单类型检查的示例:

assert type(variable_name) == int

assert type(variable_name) == bool

assert type(variable_name) == list

Examples of simple type checking in Python:

assert type(variable_name) == int

assert type(variable_name) == bool

assert type(variable_name) == list

回答 8

可能没什么关系。但是您可以isinstance(object, type)此处所述检查对象的类型。

It may be little irrelevant. but you can check types of an object with isinstance(object, type) as mentioned here.


回答 9

这个问题有点模棱两可-我不确定您所说的“视图”是什么意思。如果您要查询本机Python对象的类型,@ atzz的答案将引导您朝正确的方向发展。

但是,如果您尝试生成具有原始C型语义(例如uint32_tint16_t)的Python对象,请使用该struct模块。您可以这样确定给定C类型原语中的位数:

>>> struct.calcsize('c') # char
1
>>> struct.calcsize('h') # short
2
>>> struct.calcsize('i') # int
4
>>> struct.calcsize('l') # long
4

这也反映在array模块中,该模块可以创建以下较低类型的数组:

>>> array.array('c').itemsize # char
1

sys.maxintint给出了支持的最大整数(Python 2 )。

>>> import sys, math
>>> math.ceil(math.log(sys.maxint, 2)) + 1 # Signedness
32.0

还有sys.getsizeof,它返回剩余内存中Python对象的实际大小:

>>> a = 5
>>> sys.getsizeof(a) # Residual memory.
12

对于浮点数据和精度数据,请使用sys.float_info

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

The question is somewhat ambiguous — I’m not sure what you mean by “view”. If you are trying to query the type of a native Python object, @atzz‘s answer will steer you in the right direction.

However, if you are trying to generate Python objects that have the semantics of primitive C-types, (such as uint32_t, int16_t), use the struct module. You can determine the number of bits in a given C-type primitive thusly:

>>> struct.calcsize('c') # char
1
>>> struct.calcsize('h') # short
2
>>> struct.calcsize('i') # int
4
>>> struct.calcsize('l') # long
4

This is also reflected in the array module, which can make arrays of these lower-level types:

>>> array.array('c').itemsize # char
1

The maximum integer supported (Python 2’s int) is given by sys.maxint.

>>> import sys, math
>>> math.ceil(math.log(sys.maxint, 2)) + 1 # Signedness
32.0

There is also sys.getsizeof, which returns the actual size of the Python object in residual memory:

>>> a = 5
>>> sys.getsizeof(a) # Residual memory.
12

For float data and precision data, use sys.float_info:

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

回答 10

您是在Python还是使用ctypes

在第一种情况下,您根本无法-因为Python没有带符号/无符号的16/32位整数。

在第二种情况下,您可以使用type()

>>> import ctypes
>>> a = ctypes.c_uint() # unsigned int
>>> type(a)
<class 'ctypes.c_ulong'>

有关ctypes及其类型的更多参考,请参见官方文档

Do you mean in Python or using ctypes?

In the first case, you simply cannot – because Python does not have signed/unsigned, 16/32 bit integers.

In the second case, you can use type():

>>> import ctypes
>>> a = ctypes.c_uint() # unsigned int
>>> type(a)
<class 'ctypes.c_ulong'>

For more reference on ctypes, an its type, see the official documentation.


回答 11

Python没有您描述的类型。有两种类型用于表示整数值:int,对应于C中平台的int类型,以及long,它是任意精度的整数(即,它可以根据需要增长并且没有上限)。如果表达式产生的结果无法存储在中intlong则将s静默转换为int

Python doesn’t have such types as you describe. There are two types used to represent integral values: int, which corresponds to platform’s int type in C, and long, which is an arbitrary precision integer (i.e. it grows as needed and doesn’t have an upper limit). ints are silently converted to long if an expression produces result which cannot be stored in int.


回答 12

简单,适用于python 3.4及更高版本

print (type(variable_name))

Python 2.7及更高版本

print type(variable_name)

Simple, for python 3.4 and above

print (type(variable_name))

Python 2.7 and above

print type(variable_name)

回答 13

这实际上取决于您的意思。在Python 2.x中,出于历史原因,存在两种整数类型,int(限制为sys.maxint)和long(精度不受限制)。在Python代码中,这没有什么区别,因为当数字太大时,解释器会自动转换为long。如果您想了解底层解释器中使用的实际数据类型,则取决于实现。(CPython位于Objects / intobject.c和Objects / longobject.c中。)要了解系统类型,请查看使用struct模块的答案。

It really depends on what level you mean. In Python 2.x, there are two integer types, int (constrained to sys.maxint) and long (unlimited precision), for historical reasons. In Python code, this shouldn’t make a bit of difference because the interpreter automatically converts to long when a number is too large. If you want to know about the actual data types used in the underlying interpreter, that’s implementation dependent. (CPython’s are located in Objects/intobject.c and Objects/longobject.c.) To find out about the systems types look at cdleary answer for using the struct module.


回答 14

对于python2.x,请使用

print type(variable_name)

对于python3.x,请使用

print(type(variable_name))

For python2.x, use

print type(variable_name)

For python3.x, use

print(type(variable_name))

回答 15

只是不要这样做。要求某种类型本身是错误的。而是使用多态。查找或根据需要自己定义对任何可能的输入类型都可以执行所需操作的方法,然后直接调用它而无需询问任何内容。如果需要使用内置类型或第三方库定义的类型,则始终可以从它们继承并使用自己的派生类。或者,您也可以将它们包装在自己的类中。这是解决此类问题的面向对象的方法。

如果您坚持检查确切的类型并在各处乱放一些ifs,则可以使用__class__property或typefunction来做到这一点,但是很快您将发现自己if每隔两到三次提交就用所有其他情况来更新所有这些s。OO方法可以防止这种情况的发生,而只能让您为新的输入类型定义新的类。

Just do not do it. Asking for something’s type is wrong in itself. Instead use polymorphism. Find or if necessary define by yourself the method that does what you want for any possible type of input and just call it without asking about anything. If you need to work with built-in types or types defined by a third-party library, you can always inherit from them and use your own derivatives instead. Or you can wrap them inside your own class. This is the object-oriented way to resolve such problems.

If you insist on checking exact type and placing some dirty ifs here and there, you can use __class__ property or type function to do it, but soon you will find yourself updating all these ifs with additional cases every two or three commits. Doing it the OO way prevents that and lets you only define a new class for a new type of input instead.


如何计算列表项的出现?

问题:如何计算列表项的出现?

给定一个项目,我如何计算它在Python列表中的出现次数?

Given an item, how can I count its occurrences in a list in Python?


回答 0

如果只需要一项的计数,请使用以下count方法:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3

如果您要计算多个项目,请不要使用它。count循环调用需要为每个count调用单独遍历列表,这可能会对性能造成灾难性影响。如果您要计算所有项目,甚至只是多个项目,请使用Counter,如其他答案中所述。

If you only want one item’s count, use the count method:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3

Don’t use this if you want to count multiple items. Calling count in a loop requires a separate pass over the list for every count call, which can be catastrophic for performance. If you want to count all items, or even just multiple items, use Counter, as explained in the other answers.


回答 1

使用Counter如果你正在使用Python 2.7或3.x和你想出现的每个元素的数量:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})

Use Counter if you are using Python 2.7 or 3.x and you want the number of occurrences for each element:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})

回答 2

计算列表中一项的出现

仅计算一个列表项的出现次数即可 count()

>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2

计算列表中所有项目的出现次数也称为“对列表进行计数”或创建计数计数器。

用count()计算所有项目

要计算l一个项目的出现次数,只需使用列表理解和count()方法

[[x,l.count(x)] for x in set(l)]

(或类似的字典dict((x,l.count(x)) for x in set(l))

例:

>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}

用Counter()计算所有项目

或者,库中有更快的Countercollections

Counter(l)

例:

>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})

计数器快多少?

我检查Counter了清单的计算速度。我尝试了两种方法的几个值,n并且看起来Counter快了大约2的常数。

这是我使用的脚本:

from __future__ import print_function
import timeit

t1=timeit.Timer('Counter(l)', \
                'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
                'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count():   ", t2.repeat(repeat=3,number=10000)

并输出:

Counter():  [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count():    [7.779430688009597, 7.962715800967999, 8.420845870045014]

Counting the occurrences of one item in a list

For counting the occurrences of just one list item you can use count()

>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2

Counting the occurrences of all items in a list is also known as “tallying” a list, or creating a tally counter.

Counting all items with count()

To count the occurrences of items in l one can simply use a list comprehension and the count() method

[[x,l.count(x)] for x in set(l)]

(or similarly with a dictionary dict((x,l.count(x)) for x in set(l)))

Example:

>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}

Counting all items with Counter()

Alternatively, there’s the faster Counter class from the collections library

Counter(l)

Example:

>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})

How much faster is Counter?

I checked how much faster Counter is for tallying lists. I tried both methods out with a few values of n and it appears that Counter is faster by a constant factor of approximately 2.

Here is the script I used:

from __future__ import print_function
import timeit

t1=timeit.Timer('Counter(l)', \
                'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
                'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count():   ", t2.repeat(repeat=3,number=10000)

And the output:

Counter():  [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count():    [7.779430688009597, 7.962715800967999, 8.420845870045014]

回答 3

获取字典中每个项目出现次数的另一种方法是:

dict((i, a.count(i)) for i in a)

Another way to get the number of occurrences of each item, in a dictionary:

dict((i, a.count(i)) for i in a)

回答 4

list.count(x)返回x出现在列表中的次数

请参阅:http : //docs.python.org/tutorial/datastructures.html#more-on-lists

list.count(x) returns the number of times x appears in a list

see: http://docs.python.org/tutorial/datastructures.html#more-on-lists


回答 5

给定一个项目,我如何计算它在Python列表中的出现次数?

这是一个示例列表:

>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']

list.count

list.count方法

>>> l.count('b')
4

这适用于任何列表。元组也有这种方法:

>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6

collections.Counter

然后是collections.Counter。您可以将任何可迭代的对象转储到Counter中,而不仅仅是列表,并且Counter将保留元素计数的数据结构。

用法:

>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4

计数器基于Python字典,它们的键是元素,因此键必须是可哈希的。它们基本上就像允许多余元素进入的集合。

的进一步使用 collections.Counter

您可以从计数器中添加或减去可迭代项:

>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4

您还可以使用计数器进行多组操作:

>>> c2 = Counter(list('aabbxyz'))
>>> c - c2                   # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2                   # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2                   # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2                   # set intersection
Counter({'a': 2, 'b': 2})

为什么不熊猫呢?

另一个答案表明:

为什么不使用熊猫?

熊猫是一个公共库,但不在标准库中。根据需要添加它并非易事。

在列表对象本身以及标准库中都有针对此用例的内置解决方案。

如果您的项目不再需要熊猫,那么仅将其作为此功能的要求是愚蠢的。

Given an item, how can I count its occurrences in a list in Python?

Here’s an example list:

>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']

list.count

There’s the list.count method

>>> l.count('b')
4

This works fine for any list. Tuples have this method as well:

>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6

collections.Counter

And then there’s collections.Counter. You can dump any iterable into a Counter, not just a list, and the Counter will retain a data structure of the counts of the elements.

Usage:

>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4

Counters are based on Python dictionaries, their keys are the elements, so the keys need to be hashable. They are basically like sets that allow redundant elements into them.

Further usage of collections.Counter

You can add or subtract with iterables from your counter:

>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4

And you can do multi-set operations with the counter as well:

>>> c2 = Counter(list('aabbxyz'))
>>> c - c2                   # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2                   # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2                   # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2                   # set intersection
Counter({'a': 2, 'b': 2})

Why not pandas?

Another answer suggests:

Why not use pandas?

Pandas is a common library, but it’s not in the standard library. Adding it as a requirement is non-trivial.

There are builtin solutions for this use-case in the list object itself as well as in the standard library.

If your project does not already require pandas, it would be foolish to make it a requirement just for this functionality.


回答 6

我已经将所有建议的解决方案(以及一些新的解决方案)与perfplot(我的一个小项目)进行了比较。

计数一个项目

对于足够大的阵列,事实证明

numpy.sum(numpy.array(a) == 1) 

比其他解决方案快一点。

在此处输入图片说明

计算所有项目

由于之前建立的

numpy.bincount(a)

是你想要的。

在此处输入图片说明


复制代码的代码:

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

2。

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

I’ve compared all suggested solutions (and a few new ones) with perfplot (a small project of mine).

Counting one item

For large enough arrays, it turns out that

numpy.sum(numpy.array(a) == 1) 

is slightly faster than the other solutions.

enter image description here

Counting all items

As established before,

numpy.bincount(a)

is what you want.

enter image description here


Code to reproduce the plots:

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

2.

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

回答 7

如果您想一次计算所有值,则可以使用numpy数组快速完成bincount,如下所示

import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)

这使

>>> array([0, 3, 1, 1, 2])

If you want to count all values at once you can do it very fast using numpy arrays and bincount as follows

import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)

which gives

>>> array([0, 3, 1, 1, 2])

回答 8

如果可以使用pandas,则value_counts可以在那里进行救援。

>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1    3
4    2
3    1
2    1
dtype: int64

它还会根据频率自动对结果进行排序。

如果您希望结果在列表列表中,请执行以下操作

>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]

If you can use pandas, then value_counts is there for rescue.

>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1    3
4    2
3    1
2    1
dtype: int64

It automatically sorts the result based on frequency as well.

If you want the result to be in a list of list, do as below

>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]

回答 9

为什么不使用熊猫呢?

import pandas as pd

l = ['a', 'b', 'c', 'd', 'a', 'd', 'a']

# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count

输出:

a    3
d    2
b    1
c    1
dtype: int64

如果要查找特定元素的数量,请说a,请尝试:

my_count['a']

输出:

3

Why not using Pandas?

import pandas as pd

l = ['a', 'b', 'c', 'd', 'a', 'd', 'a']

# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count

Output:

a    3
d    2
b    1
c    1
dtype: int64

If you are looking for a count of a particular element, say a, try:

my_count['a']

Output:

3

回答 10

我今天遇到了这个问题,在考虑检查SO之前推出了自己的解决方案。这个:

dict((i,a.count(i)) for i in a)

对于大型列表,真的非常慢。我的解决方案

def occurDict(items):
    d = {}
    for i in items:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
return d

实际上比Counter解决方案要快一点,至少对于Python 2.7而言。

I had this problem today and rolled my own solution before I thought to check SO. This:

dict((i,a.count(i)) for i in a)

is really, really slow for large lists. My solution

def occurDict(items):
    d = {}
    for i in items:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
return d

is actually a bit faster than the Counter solution, at least for Python 2.7.


回答 11

# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
    """
    :param items: iterable of hashable items to count
    :type items: iterable

    :returns: dict of counts like Py2.7 Counter
    :rtype: dict
    """
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


# Python >= 2.2 (generators)
def count_sorted_list_items(items):
    """
    :param items: sorted iterable of items to count
    :type items: sorted iterable

    :returns: generator of (item, count) tuples
    :rtype: generator
    """
    if not items:
        return
    elif len(items) == 1:
        yield (items[0], 1)
        return
    prev_item = items[0]
    count = 1
    for item in items[1:]:
        if prev_item == item:
            count += 1
        else:
            yield (prev_item, count)
            count = 1
            prev_item = item
    yield (item, count)
    return


import unittest
class TestListCounters(unittest.TestCase):
    def test_count_unsorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = count_unsorted_list_items(inp) 
            print inp, exp_outp, counts
            self.assertEqual(counts, dict( exp_outp ))

        inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )


    def test_count_sorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = list( count_sorted_list_items(inp) )
            print inp, exp_outp, counts
            self.assertEqual(counts, exp_outp)

        inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
        # ... [(2,2), (4,1), (2,1)]
# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
    """
    :param items: iterable of hashable items to count
    :type items: iterable

    :returns: dict of counts like Py2.7 Counter
    :rtype: dict
    """
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


# Python >= 2.2 (generators)
def count_sorted_list_items(items):
    """
    :param items: sorted iterable of items to count
    :type items: sorted iterable

    :returns: generator of (item, count) tuples
    :rtype: generator
    """
    if not items:
        return
    elif len(items) == 1:
        yield (items[0], 1)
        return
    prev_item = items[0]
    count = 1
    for item in items[1:]:
        if prev_item == item:
            count += 1
        else:
            yield (prev_item, count)
            count = 1
            prev_item = item
    yield (item, count)
    return


import unittest
class TestListCounters(unittest.TestCase):
    def test_count_unsorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = count_unsorted_list_items(inp) 
            print inp, exp_outp, counts
            self.assertEqual(counts, dict( exp_outp ))

        inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )


    def test_count_sorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = list( count_sorted_list_items(inp) )
            print inp, exp_outp, counts
            self.assertEqual(counts, exp_outp)

        inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
        # ... [(2,2), (4,1), (2,1)]

回答 12

以下是三种解决方案:

最快的是使用for循环并将其存储在Dict中。

import time
from collections import Counter


def countElement(a):
    g = {}
    for i in a:
        if i in g: 
            g[i] +=1
        else: 
            g[i] =1
    return g


z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]


#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
    b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))

#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
    a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))

#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
    g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))

结果

#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0

Below are the three solutions:

Fastest is using a for loop and storing it in a Dict.

import time
from collections import Counter


def countElement(a):
    g = {}
    for i in a:
        if i in g: 
            g[i] +=1
        else: 
            g[i] =1
    return g


z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]


#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
    b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))

#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
    a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))

#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
    g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))

Result

#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0

回答 13

所有元素的计数 itertools.groupby()

获取列表中所有元素的计数的另一种可能性是使用itertools.groupby()

具有“重复”计数

from itertools import groupby

L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c']  # Input list

counts = [(i, len(list(c))) for i,c in groupby(L)]      # Create value-count pairs as list of tuples 
print(counts)

退货

[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]

请注意,它是如何将前三个组合在一起a作为第一组的,而其他组合a则位于列表的下方。发生这种情况是因为未对输入列表L进行排序。如果组实际上应该分开,那么有时这可能是一个好处。

具有独特的计数

如果需要唯一的组计数,只需对输入列表进行排序:

counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)

退货

[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]

注意:为了创建唯一计数,与groupby解决方案相比,许多其他答案都提供了更轻松,更易读的代码。但是这里显示它与重复计数示例相似。

Count of all elements with itertools.groupby()

Antoher possiblity for getting the count of all elements in the list could be by means of itertools.groupby().

With “duplicate” counts

from itertools import groupby

L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c']  # Input list

counts = [(i, len(list(c))) for i,c in groupby(L)]      # Create value-count pairs as list of tuples 
print(counts)

Returns

[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]

Notice how it combined the first three a‘s as the first group, while other groups of a are present further down the list. This happens because the input list L was not sorted. This can be a benefit sometimes if the groups should in fact be separate.

With unique counts

If unique group counts are desired, just sort the input list:

counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)

Returns

[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]

Note: For creating unique counts, many of the other answers provide easier and more readable code compared to the groupby solution. But it is shown here to draw a parallel to the duplicate count example.


回答 14

建议使用numpy的bincount,但是它仅适用于具有非负整数的一维数组。此外,结果数组可能会造成混淆(它包含原始列表的最小值到最大值的整数的出现,并将丢失的整数设置为0)。

使用numpy更好的方法是使用属性设置为True 的唯一函数return_counts。它返回一个元组,该元组具有唯一值的数组和每个唯一值的出现的数组。

# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True)  # array([0, 1, 2, 3]), array([2, 3, 1, 2]

然后我们可以将它们配对为

dict(zip(a_uniq, counts))  # {0: 2, 1: 3, 2: 1, 3: 2}

它还可以与其他数据类型和“ 2d列表”一起使用,例如

>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}

It was suggested to use numpy’s bincount, however it works only for 1d arrays with non-negative integers. Also, the resulting array might be confusing (it contains the occurrences of the integers from min to max of the original list, and sets to 0 the missing integers).

A better way to do it with numpy is to use the unique function with the attribute return_counts set to True. It returns a tuple with an array of the unique values and an array of the occurrences of each unique value.

# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True)  # array([0, 1, 2, 3]), array([2, 3, 1, 2]

and then we can pair them as

dict(zip(a_uniq, counts))  # {0: 2, 1: 3, 2: 1, 3: 2}

It also works with other data types and “2d lists”, e.g.

>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}

回答 15

计算具有共同类型的各种元素的数量:

li = ['A0','c5','A8','A2','A5','c2','A3','A9']

print sum(1 for el in li if el[0]=='A' and el[1] in '01234')

3 ,而不是6

To count the number of diverse elements having a common type:

li = ['A0','c5','A8','A2','A5','c2','A3','A9']

print sum(1 for el in li if el[0]=='A' and el[1] in '01234')

gives

3 , not 6


回答 16

虽然这是一个非常古老的问题,但是由于我没有找到一支,所以我做了一支。

# original numbers in list
l = [1, 2, 2, 3, 3, 3, 4]

# empty dictionary to hold pair of number and its count
d = {}

# loop through all elements and store count
[ d.update( {i:d.get(i, 0)+1} ) for i in l ]

print(d)

Although it is very old question, but as i didn’t find a one liner, i made one.

# original numbers in list
l = [1, 2, 2, 3, 3, 3, 4]

# empty dictionary to hold pair of number and its count
d = {}

# loop through all elements and store count
[ d.update( {i:d.get(i, 0)+1} ) for i in l ]

print(d)

回答 17

您也可以使用countOf内置模块的方法operator

>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3

You can also use countOf method of a built-in module operator.

>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3

回答 18

可能不是最有效的,需要额外的通行证才能删除重复项。

功能实现:

arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x  : (x , list(arr).count(x)) , arr)))

返回:

{('c', 1), ('b', 3), ('a', 2)}

或返回为dict

print(dict(map(lambda x  : (x , list(arr).count(x)) , arr)))

返回:

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

May not be the most efficient, requires an extra pass to remove duplicates.

Functional implementation :

arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x  : (x , list(arr).count(x)) , arr)))

returns :

{('c', 1), ('b', 3), ('a', 2)}

or return as dict :

print(dict(map(lambda x  : (x , list(arr).count(x)) , arr)))

returns :

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

回答 19

sum([1 for elem in <yourlist> if elem==<your_value>])

这将返回your_value的出现次数

sum([1 for elem in <yourlist> if elem==<your_value>])

This will return the amount of occurences of your_value


回答 20

我将使用filter()Lukasz的示例:

>>> lst = [1, 2, 3, 4, 1, 4, 1]
>>> len(filter(lambda x: x==1, lst))
3

I would use filter(), take Lukasz’s example:

>>> lst = [1, 2, 3, 4, 1, 4, 1]
>>> len(filter(lambda x: x==1, lst))
3

回答 21

如果您希望特定元素出现多次:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])

if you want a number of occurrences for the particular element:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])

回答 22

def countfrequncyinarray(arr1):
    r=len(arr1)
    return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)
def countfrequncyinarray(arr1):
    r=len(arr1)
    return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)

回答 23

l2=[1,"feto",["feto",1,["feto"]],['feto',[1,2,3,['feto']]]]
count=0
 def Test(l):   
        global count 
        if len(l)==0:
             return count
        count=l.count("feto")
        for i in l:
             if type(i) is list:
                count+=Test(i)
        return count   
    print(Test(l2))

这将递归计数或搜索列表中的项目,即使它在列表列表中

l2=[1,"feto",["feto",1,["feto"]],['feto',[1,2,3,['feto']]]]
count=0
 def Test(l):   
        global count 
        if len(l)==0:
             return count
        count=l.count("feto")
        for i in l:
             if type(i) is list:
                count+=Test(i)
        return count   
    print(Test(l2))

this will recursive count or search for the item in the list even if it in list of lists


如何在python字符串中打印文字大括号字符并在其上使用.format?

问题:如何在python字符串中打印文字大括号字符并在其上使用.format?

x = " \{ Hello \} {0} "
print(x.format(42))

给我 : Key Error: Hello\\

我想打印输出: {Hello} 42

x = " \{ Hello \} {0} "
print(x.format(42))

gives me : Key Error: Hello\\

I want to print the output: {Hello} 42


回答 0

您需要将{{和加倍}}

>>> x = " {{ Hello }} {0} "
>>> print(x.format(42))
' { Hello } 42 '

这是Python文档中有关格式字符串语法的相关部分:

格式字符串包含用花括号括起来的“替换字段” {}。花括号中不包含的所有内容均视为文字文本,该文本原样复制到输出中。如果需要在文字文本中包含大括号字符,可以通过加倍:{{和来对其进行转义}}

You need to double the {{ and }}:

>>> x = " {{ Hello }} {0} "
>>> print(x.format(42))
' { Hello } 42 '

Here’s the relevant part of the Python documentation for format string syntax:

Format strings contain “replacement fields” surrounded by curly braces {}. Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.


回答 1

您可以通过将花括号加倍来逃脱它。

例如:

x = "{{ Hello }} {0}"
print(x.format(42))

You escape it by doubling the braces.

Eg:

x = "{{ Hello }} {0}"
print(x.format(42))

回答 2

Python 3.6+(2017年)

在最新版本的Python中,将使用f字符串(另请参阅PEP498)。

对于f弦,应使用double {{}}

n = 42  
print(f" {{Hello}} {n} ")

产生所需的

 {Hello} 42

如果您需要在方括号中解析表达式而不是使用文字文本,则需要三组方括号:

hello = "HELLO"
print(f"{{{hello.lower()}}}")

产生

{hello}

Python 3.6+ (2017)

In the recent versions of Python one would use f-strings (see also PEP498).

With f-strings one should use double {{ or }}

n = 42  
print(f" {{Hello}} {n} ")

produces the desired

 {Hello} 42

If you need to resolve an expression in the brackets instead of using literal text you’ll need three sets of brackets:

hello = "HELLO"
print(f"{{{hello.lower()}}}")

produces

{hello}

回答 3

OP写了这个评论:

我正在尝试出于某种目的格式化小型JSON,例如:'{"all": false, "selected": "{}"}'.format(data)获得类似{"all": false, "selected": "1,2"}

在处理JSON时经常会出现“转义括号”问题。

我建议这样做:

import json
data = "1,2"
mydict = {"all": "false", "selected": data}
json.dumps(mydict)

它比替代方案更清洁,替代方案是:

'{{"all": false, "selected": "{}"}}'.format(data)

json当JSON字符串比示例复杂时,最好使用该库。

The OP wrote this comment:

I was trying to format a small JSON for some purposes, like this: '{"all": false, "selected": "{}"}'.format(data) to get something like {"all": false, "selected": "1,2"}

It’s pretty common that the “escaping braces” issue comes up when dealing with JSON.

I suggest doing this:

import json
data = "1,2"
mydict = {"all": "false", "selected": data}
json.dumps(mydict)

It’s cleaner than the alternative, which is:

'{{"all": false, "selected": "{}"}}'.format(data)

Using the json library is definitely preferable when the JSON string gets more complicated than the example.


回答 4

尝试这样做:

x = " {{ Hello }} {0} "
print x.format(42)

Try doing this:

x = " {{ Hello }} {0} "
print x.format(42)

回答 5

尝试这个:

x = "{{ Hello }} {0}"

Try this:

x = "{{ Hello }} {0}"


回答 6

尽管没有更好的效果,但仅供参考,您也可以这样做:

>>> x = '{}Hello{} {}'
>>> print x.format('{','}',42)
{Hello} 42

例如,当有人要打印时,此功能很有用{argument}。它可能比'{{{}}}'.format('argument')

请注意,您在Python 2.7之后省略了参数位置(例如{}而不是{0}

Although not any better, just for the reference, you can also do this:

>>> x = '{}Hello{} {}'
>>> print x.format('{','}',42)
{Hello} 42

It can be useful for example when someone wants to print {argument}. It is maybe more readable than '{{{}}}'.format('argument')

Note that you omit argument positions (e.g. {} instead of {0}) after Python 2.7


回答 7

如果您打算做很多事情,最好定义一个实用函数,让您使用任意大括号替代项,例如

def custom_format(string, brackets, *args, **kwargs):
    if len(brackets) != 2:
        raise ValueError('Expected two brackets. Got {}.'.format(len(brackets)))
    padded = string.replace('{', '{{').replace('}', '}}')
    substituted = padded.replace(brackets[0], '{').replace(brackets[1], '}')
    formatted = substituted.format(*args, **kwargs)
    return formatted

>>> custom_format('{{[cmd]} process 1}', brackets='[]', cmd='firefox.exe')
'{{firefox.exe} process 1}'

请注意,这将适用于括号为长度为2的字符串或两个字符串为可迭代的字符串(对于多字符定界符)。

If you are going to be doing this a lot, it might be good to define a utility function that will let you use arbitrary brace substitutes instead, like

def custom_format(string, brackets, *args, **kwargs):
    if len(brackets) != 2:
        raise ValueError('Expected two brackets. Got {}.'.format(len(brackets)))
    padded = string.replace('{', '{{').replace('}', '}}')
    substituted = padded.replace(brackets[0], '{').replace(brackets[1], '}')
    formatted = substituted.format(*args, **kwargs)
    return formatted

>>> custom_format('{{[cmd]} process 1}', brackets='[]', cmd='firefox.exe')
'{{firefox.exe} process 1}'

Note that this will work either with brackets being a string of length 2 or an iterable of two strings (for multi-character delimiters).


回答 8

我最近遇到了这个问题,因为我想将字符串注入预先格式化的JSON中。我的解决方案是创建一个辅助方法,如下所示:

def preformat(msg):
    """ allow {{key}} to be used for formatting in text
    that already uses curly braces.  First switch this into
    something else, replace curlies with double curlies, and then
    switch back to regular braces
    """
    msg = msg.replace('{{', '<<<').replace('}}', '>>>')
    msg = msg.replace('{', '{{').replace('}', '}}')
    msg = msg.replace('<<<', '{').replace('>>>', '}')
    return msg

然后,您可以执行以下操作:

formatted = preformat("""
    {
        "foo": "{{bar}}"
    }""").format(bar="gas")

如果性能不成问题,则完成工作。

I recently ran into this, because I wanted to inject strings into preformatted JSON. My solution was to create a helper method, like this:

def preformat(msg):
    """ allow {{key}} to be used for formatting in text
    that already uses curly braces.  First switch this into
    something else, replace curlies with double curlies, and then
    switch back to regular braces
    """
    msg = msg.replace('{{', '<<<').replace('}}', '>>>')
    msg = msg.replace('{', '{{').replace('}', '}}')
    msg = msg.replace('<<<', '{').replace('>>>', '}')
    return msg

You can then do something like:

formatted = preformat("""
    {
        "foo": "{{bar}}"
    }""").format(bar="gas")

Gets the job done if performance is not an issue.


回答 9

如果需要在字符串中保留两个大括号,则变量的每一侧都需要5个大括号。

>>> myvar = 'test'
>>> "{{{{{0}}}}}".format(myvar)
'{{test}}'

If you need to keep two curly braces in the string, you need 5 curly braces on each side of the variable.

>>> myvar = 'test'
>>> "{{{{{0}}}}}".format(myvar)
'{{test}}'

回答 10

原因是,{}.format()您的情况下的语法,因此.format()无法识别,{Hello}因此引发了错误。

您可以使用双大括号{{}}覆盖它,

x = " {{ Hello }} {0} "

要么

尝试%s格式化文本,

x = " { Hello } %s"
print x%(42)  

Reason is , {} is the syntax of .format() so in your case .format() doesn’t recognize {Hello} so it threw an error.

you can override it by using double curly braces {{}},

x = " {{ Hello }} {0} "

or

try %s for text formatting,

x = " { Hello } %s"
print x%(42)  

回答 11

我在尝试打印文本时偶然发现了这个问题,可以将其复制粘贴到Latex文档中。我扩展这个答案,并使用命名的替换字段:

假设您要打印出带有诸如的索引的多个变量的乘积 在此处输入图片说明,在Latex中将是$A_{ 0042 }*A_{ 3141 }*A_{ 2718 }*A_{ 0042 }$ 这样的代码。以下代码使用命名字段完成工作,因此对于许多索引而言,它仍然可读:

idx_mapping = {'i1':42, 'i2':3141, 'i3':2178 }
print('$A_{{ {i1:04d} }} * A_{{ {i2:04d} }} * A_{{ {i3:04d} }} * A_{{ {i1:04d} }}$'.format(**idx_mapping))

I stumbled upon this problem when trying to print text, which I can copy paste into a Latex document. I extend on this answer and make use of named replacement fields:

Lets say you want to print out a product of mulitple variables with indices such as enter image description here, which in Latex would be $A_{ 0042 }*A_{ 3141 }*A_{ 2718 }*A_{ 0042 }$ The following code does the job with named fields so that for many indices it stays readable:

idx_mapping = {'i1':42, 'i2':3141, 'i3':2178 }
print('$A_{{ {i1:04d} }} * A_{{ {i2:04d} }} * A_{{ {i3:04d} }} * A_{{ {i1:04d} }}$'.format(**idx_mapping))

回答 12

如果你想打印一个大括号(例如{),您可以使用{{,如果你愿意,你可以在后面的字符串添加多个支架。例如:

>>> f'{{ there is a curly brace on the left. Oh, and 1 + 1 is {1 + 1}'
'{ there is a curly brace on the left. Oh, and 1 + 1 is 2'

If you want to only print one curly brace (for example {) you can use {{, and you can add more braces later in the string if you want. For example:

>>> f'{{ there is a curly brace on the left. Oh, and 1 + 1 is {1 + 1}'
'{ there is a curly brace on the left. Oh, and 1 + 1 is 2'

回答 13

当您只是想插入代码字符串时,我建议您使用jinja2,它是Python的全功能模板引擎,即:

from jinja2 import Template

foo = Template('''
#include <stdio.h>

void main() {
    printf("hello universe number {{number}}");
}
''')

for i in range(2):
    print(foo.render(number=i))

因此,您不会因为其他答案而被迫复制花括号

When you’re just trying to interpolate code strings I’d suggest using jinja2 which is a full-featured template engine for Python, ie:

from jinja2 import Template

foo = Template('''
#include <stdio.h>

void main() {
    printf("hello universe number {{number}}");
}
''')

for i in range(2):
    print(foo.render(number=i))

So you won’t be enforced to duplicate curly braces as the whole bunch of other answers suggest


回答 14

您可以通过使用原始字符串方法来实现此目的,只需在字符串前添加不带引号的字符’r’。

# to print '{I am inside braces}'
print(r'{I am inside braces}')

You can do this by using raw string method by simply adding character ‘r’ without quotes before the string.

# to print '{I am inside braces}'
print(r'{I am inside braces}')

如何通过索引从列表中删除元素

问题:如何通过索引从列表中删除元素

如何在Python中按索引从列表中删除元素?

我找到了list.remove方法,但是说我要删除最后一个元素,该怎么做?似乎默认的remove搜索列表,但是我不希望执行任何搜索。

How do I remove an element from a list by index in Python?

I found the list.remove method, but say I want to remove the last element, how do I do this? It seems like the default remove searches the list, but I don’t want any search to be performed.


回答 0

使用del并指定要删除的元素的索引:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

还支持切片:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

是教程中的部分。

Use del and specify the index of the element you want to delete:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Also supports slices:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

Here is the section from the tutorial.


回答 1

您可能想要pop

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

默认情况下,pop不带任何参数将删除最后一项:

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

You probably want pop:

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

By default, pop without any arguments removes the last item:

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

回答 2

像其他提到的一样,pop和del是删除给定索引项有效方法。只是为了完成(因为可以通过Python中的许多方法来完成同一件事):

使用切片(这并不能代替从原始列表中删除项目):

(这也是使用Python列表时效率最低的方法,但是在使用不支持pop但却定义了a的用户定义对象时,这可能会很有用(但无效,我重申__getitem__)。

>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index

>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]

注意:请注意,此方法不会像pop和那样修改列表del。相反,它制作了两个列表副本(一个从开始到索引,但没有索引(a[:index]),一个在索引后,直到最后一个元素(a[index+1:])),并通过添加两个副本来创建新的列表对象。然后将其重新分配给列表变量(a)。因此,旧列表对象被取消引用并因此被垃圾回收(前提是原始列表对象未被a以外的任何变量引用)。

这使该方法非常低效,并且还可能产生不良的副作用(尤其是当其他变量指向未修改的原始列表对象时)。

感谢@MarkDickinson指出这一点…

堆栈溢出答案说明了切片的概念。

另请注意,这仅适用于正指数。

与对象一起使用时,__getitem__必须已定义该__add__方法,更重要的是,必须已定义该方法以从两个操作数返回包含项的对象。

本质上,这适用于类定义如下的任何对象:

class foo(object):
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return foo(self.items[index])

    def __add__(self, right):
        return foo( self.items + right.items )

这与list定义__getitem____add__方法一起使用。

三种方式的效率比较:

假设以下是预定义的:

a = range(10)
index = 3

del object[index]方法:

迄今为止最有效的方法。所有定义__del__方法的对象都可以使用。

拆卸如下:

码:

def del_method():
    global a
    global index
    del a[index]

拆卸:

 10    0 LOAD_GLOBAL     0 (a)
       3 LOAD_GLOBAL     1 (index)
       6 DELETE_SUBSCR   # This is the line that deletes the item
       7 LOAD_CONST      0 (None)
      10 RETURN_VALUE
None

pop 方法:

它比del方法效率低,在需要获取已删除项目时使用。

码:

def pop_method():
    global a
    global index
    a.pop(index)

拆卸:

 17     0 LOAD_GLOBAL     0 (a)
        3 LOAD_ATTR       1 (pop)
        6 LOAD_GLOBAL     2 (index)
        9 CALL_FUNCTION   1
       12 POP_TOP
       13 LOAD_CONST      0 (None)
       16 RETURN_VALUE

slice和add方法。

效率最低。

码:

def slice_method():
    global a
    global index
    a = a[:index] + a[index+1:]

拆卸:

 24     0 LOAD_GLOBAL    0 (a)
        3 LOAD_GLOBAL    1 (index)
        6 SLICE+2
        7 LOAD_GLOBAL    0 (a)
       10 LOAD_GLOBAL    1 (index)
       13 LOAD_CONST     1 (1)
       16 BINARY_ADD
       17 SLICE+1
       18 BINARY_ADD
       19 STORE_GLOBAL   0 (a)
       22 LOAD_CONST     0 (None)
       25 RETURN_VALUE
None

注意:在所有三个反汇编中,忽略最后两行,基本上是return None。同样,前两行正在加载全局值aindex

Like others mentioned pop and del are the efficient ways to remove an item of given index. Yet just for the sake of completion (since the same thing can be done via many ways in Python):

Using slices (this does not do in place removal of item from original list):

(Also this will be the least efficient method when working with Python list, but this could be useful (but not efficient, I reiterate) when working with user defined objects that do not support pop, yet do define a __getitem__ ):

>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index

>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]

Note: Please note that this method does not modify the list in place like pop and del. It instead makes two copies of lists (one from the start until the index but without it (a[:index]) and one after the index till the last element (a[index+1:])) and creates a new list object by adding both. This is then reassigned to the list variable (a). The old list object is hence dereferenced and hence garbage collected (provided the original list object is not referenced by any variable other than a).

This makes this method very inefficient and it can also produce undesirable side effects (especially when other variables point to the original list object which remains un-modified).

Thanks to @MarkDickinson for pointing this out …

This Stack Overflow answer explains the concept of slicing.

Also note that this works only with positive indices.

While using with objects, the __getitem__ method must have been defined and more importantly the __add__ method must have been defined to return an object containing items from both the operands.

In essence, this works with any object whose class definition is like:

class foo(object):
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return foo(self.items[index])

    def __add__(self, right):
        return foo( self.items + right.items )

This works with list which defines __getitem__ and __add__ methods.

Comparison of the three ways in terms of efficiency:

Assume the following is predefined:

a = range(10)
index = 3

The del object[index] method:

By far the most efficient method. It works will all objects that define a __del__ method.

The disassembly is as follows:

Code:

def del_method():
    global a
    global index
    del a[index]

Disassembly:

 10    0 LOAD_GLOBAL     0 (a)
       3 LOAD_GLOBAL     1 (index)
       6 DELETE_SUBSCR   # This is the line that deletes the item
       7 LOAD_CONST      0 (None)
      10 RETURN_VALUE
None

pop method:

It is less efficient than the del method and is used when you need to get the deleted item.

Code:

def pop_method():
    global a
    global index
    a.pop(index)

Disassembly:

 17     0 LOAD_GLOBAL     0 (a)
        3 LOAD_ATTR       1 (pop)
        6 LOAD_GLOBAL     2 (index)
        9 CALL_FUNCTION   1
       12 POP_TOP
       13 LOAD_CONST      0 (None)
       16 RETURN_VALUE

The slice and add method.

The least efficient.

Code:

def slice_method():
    global a
    global index
    a = a[:index] + a[index+1:]

Disassembly:

 24     0 LOAD_GLOBAL    0 (a)
        3 LOAD_GLOBAL    1 (index)
        6 SLICE+2
        7 LOAD_GLOBAL    0 (a)
       10 LOAD_GLOBAL    1 (index)
       13 LOAD_CONST     1 (1)
       16 BINARY_ADD
       17 SLICE+1
       18 BINARY_ADD
       19 STORE_GLOBAL   0 (a)
       22 LOAD_CONST     0 (None)
       25 RETURN_VALUE
None

Note: In all three disassembles ignore the last two lines which basically are return None. Also the first two lines are loading the global values a and index.


回答 3

pop从列表中删除并保留项目也很有用。del实际在哪里丢弃物品。

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2

pop is also useful to remove and keep an item from a list. Where del actually trashes the item.

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2

回答 4

如果要删除列表中的特定位置元素,例如2th,3th和7th。你不能使用

del my_list[2]
del my_list[3]
del my_list[7]

由于删除第二个元素后,实际上删除的第三个元素是原始列表中的第四个元素。您可以过滤原始列表中的2th,3th和7th元素并获得一个新列表,如下所示:

new list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

If you want to remove the specific position element in a list, like the 2th, 3th and 7th. you can’t use

del my_list[2]
del my_list[3]
del my_list[7]

Since after you delete the second element, the third element you delete actually is the fourth element in the original list. You can filter the 2th, 3th and 7th element in the original list and get a new list, like below:

new list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

回答 5

这取决于您要做什么。

如果要返回删除的元素,请使用pop()

>>> l = [1, 2, 3, 4, 5]
>>> l.pop(2)
3
>>> l
[1, 2, 4, 5]

但是,如果您只想删除一个元素,请使用del

>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]

另外,del允许您使用切片(例如del[2:])。

This depends on what you want to do.

If you want to return the element you removed, use pop():

>>> l = [1, 2, 3, 4, 5]
>>> l.pop(2)
3
>>> l
[1, 2, 4, 5]

However, if you just want to delete an element, use del:

>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]

Additionally, del allows you to use slices (e.g. del[2:]).


回答 6

通常,我使用以下方法:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]

Generally, I am using the following method:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]

回答 7

通过索引从列表中删除元素的另一种方法。

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

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a [x:y]指向索引中的元素 xy-1。当我们将列表的该部分声明为空列表([])时,这些元素将被删除。

Yet another way to remove an element(s) from a list by index.

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

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a[x:y] points to the elements from index x to y-1. When we declare that portion of the list as an empty list ([]), those elements are removed.


回答 8

您可以只搜索要删除的项目。真的很简单。例:

    letters = ["a", "b", "c", "d", "e"]
    letters.remove(letters[1])
    print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)

输出:acde

You could just search for the item you want to delete. It is really simple. Example:

    letters = ["a", "b", "c", "d", "e"]
    letters.remove(letters[1])
    print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)

Output: a c d e


回答 9

使用以下代码从列表中删除元素:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

如果要从列表中删除索引元素数据,请使用:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

Use the following code to remove element from the list:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

If you want to remove index element data from the list use:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

回答 10

如前所述,最佳实践是del(); 或pop()如果您需要知道该值。

另一种解决方案是仅重新堆叠所需的那些元素:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

eta:嗯…不适用于负索引值,会思考和更新

我想

if index_<0:index_=len(list_)+index_

会修补它…但是突然之间,这个想法似乎很脆弱。有趣的思想实验。似乎应该有一个“正确”的方法来执行append()/列表理解。

思考

As previously mentioned, best practice is del(); or pop() if you need to know the value.

An alternate solution is to re-stack only those elements you want:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

eta: hmm… will not work on negative index values, will ponder and update

I suppose

if index_<0:index_=len(list_)+index_

would patch it… but suddenly this idea seems very brittle. Interesting thought experiment though. Seems there should be a ‘proper’ way to do this with append() / list comprehension.

pondering


回答 11

听起来好像您不是在使用列表列表,所以我将简短说明。您要使用pop,因为它将删除元素而不是列表元素,因此应使用del。要调用python中的最后一个元素,它是“ -1”

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

It doesn’t sound like you’re working with a list of lists, so I’ll keep this short. You want to use pop since it will remove elements not elements that are lists, you should use del for that. To call the last element in python it’s “-1”

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

回答 12

l-值列表;我们必须从inds2rem列表中删除索引。

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

l – list of values; we have to remove indexes from inds2rem list.

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

回答 13

使用“ del”功能:

del listName[-N]

例如,如果要删除最后3个项目,则代码应为:

del listName[-3:]

例如,如果要删除最后8个项目,则代码应为:

del listName[-8:]

Use the “del” function:

del listName[-N]

For example, if you want to remove the last 3 items, your code should be:

del listName[-3:]

For example, if you want to remove the last 8 items, your code should be:

del listName[-8:]

回答 14

已经提到了如何从列表中删除单个元素以及不同方法具有哪些优点。但是请注意,删除多个元素可能会导致错误:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

原始列表的元素3和8(不是3和7)已被删除(因为列表在循环中被缩短了),这可能不是本意。如果要安全删除多个索引,则应首先删除索引最高的元素,例如:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]

It has already been mentioned how to remove a single element from a list and which advantages the different methods have. Note, however, that removing multiple elements has some potential for errors:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

Elements 3 and 8 (not 3 and 7) of the original list have been removed (as the list was shortened during the loop), which might not have been the intention. If you want to safely remove multiple indices you should instead delete the elements with highest index first, e.g. like this:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]

回答 15

或者,如果应删除多个索引:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

然后当然也可以这样做:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

Or if multiple indexes should be removed:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

Of course then could also do:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

回答 16

您可以使用del或pop来基于索引从列表中删除元素。Pop将打印从列表中删除的成员,而列表删除该成员而不打印它。

>>> a=[1,2,3,4,5]
>>> del a[1]
>>> a
[1, 3, 4, 5]
>>> a.pop(1)
 3
>>> a
[1, 4, 5]
>>> 

You can use either del or pop to remove element from list based on index. Pop will print member it is removing from list, while list delete that member without printing it.

>>> a=[1,2,3,4,5]
>>> del a[1]
>>> a
[1, 3, 4, 5]
>>> a.pop(1)
 3
>>> a
[1, 4, 5]
>>> 

回答 17

可以使用del或pop,但我更喜欢del,因为您可以指定索引和切片,从而使用户可以更好地控制数据。

例如,从所示的列表开始,可以使用删除其最后一个元素del作为切片,然后可以使用从结果中删除最后一个元素pop

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]

One can either use del or pop, but I prefer del, since you can specify index and slices, giving the user more control over the data.

For example, starting with the list shown, one can remove its last element with del as a slice, and then one can remove the last element from the result using pop.

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]

您如何从stdin阅读?

问题:您如何从stdin阅读?

我正在尝试挑战一些代码挑战,但是所有这些挑战都需要从输入stdin。我如何在Python中得到它?

I’m trying to do some of the code golf challenges, but they all require the input to be taken from stdin. How do I get that in Python?


回答 0

您可以使用以下fileinput模块:

import fileinput

for line in fileinput.input():
    pass

fileinput 将在输入中指定为命令行参数中指定的文件名的所有行,如果没有提供参数则返回标准输入。

注意:line将包含尾随换行符;删除它使用line.rstrip()

You could use the fileinput module:

import fileinput

for line in fileinput.input():
    pass

fileinput will loop through all the lines in the input specified as file names given in command-line arguments, or the standard input if no arguments are provided.

Note: line will contain a trailing newline; to remove it use line.rstrip()


回答 1

有几种方法可以做到。

  • sys.stdin是一个类似于文件的对象,可以在其上调用函数,read或者readlines如果要读取所有内容,或者要读取所有内容并自动按换行符将其拆分,则可以在其上调用。(您需要使它import sys起作用。)

  • 如果要提示用户输入,则可以raw_input在Python 2.X和inputPython 3中使用。

  • 如果您实际上只想阅读命令行选项,则可以通过sys.argv列表访问它们。

您可能还会发现有关I / O和Python的Wikibook这篇文章也是有用的参考。

There’s a few ways to do it.

  • sys.stdin is a file-like object on which you can call functions read or readlines if you want to read everything or you want to read everything and split it by newline automatically. (You need to import sys for this to work.)

  • If you want to prompt the user for input, you can use raw_input in Python 2.X, and just input in Python 3.

  • If you actually just want to read command-line options, you can access them via the sys.argv list.

You will probably find this Wikibook article on I/O in Python to be a useful reference as well.


回答 2

import sys

for line in sys.stdin:
    print(line)

请注意,这将在末尾包含换行符。要最后删除换行符,请使用line.rstrip()@brittohalloran所说的。

import sys

for line in sys.stdin:
    print(line)

Note that this will include a newline character at the end. To remove the newline at the end, use line.rstrip() as @brittohalloran said.


回答 3

Python还具有内置函数input()raw_input()。请参阅“ 内置函数”下的Python文档。

例如,

name = raw_input("Enter your name: ")   # Python 2.x

要么

name = input("Enter your name: ")   # Python 3

Python also has built-in functions input() and raw_input(). See the Python documentation under Built-in Functions.

For example,

name = raw_input("Enter your name: ")   # Python 2.x

or

name = input("Enter your name: ")   # Python 3

回答 4

来自学习Python

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."

在Unix上,您可以通过执行以下操作对其进行测试:

% cat countlines.py | python countlines.py 
Counted 3 lines.

在Windows或DOS上,您可以执行以下操作:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.

Here’s from Learning Python:

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."

On Unix, you could test it by doing something like:

% cat countlines.py | python countlines.py 
Counted 3 lines.

On Windows or DOS, you’d do:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.

回答 5

您如何从Python的stdin中读取信息?

我正在尝试进行一些代码挑战,但是它们都要求输入来自stdin。我如何在Python中得到它?

您可以使用:

  • sys.stdin-类似于文件的对象-调用sys.stdin.read()以读取所有内容。
  • input(prompt)-向其传递一个可选的提示以输出,它从stdin读取直到第一个换行符,然后将其剥离。您必须重复执行此操作才能获得更多行,在输入结束时会引发EOFError。(可能不适用于打高尔夫球。)在Python 2中,这是rawinput(prompt)
  • open(0).read()-在Python 3中,内置函数open接受文件描述符(代表操作系统IO资源的整数),而0是的描述符stdin。它返回类似文件的对象sys.stdin-可能是打高尔夫球的最佳选择。在Python 2中,这是io.open
  • open('/dev/stdin').read()-与相似open(0),适用于Python 2和3,但不适用于Windows(甚至Cygwin)。
  • fileinput.input()-在中列出的所有文件中的行上返回迭代器sys.argv[1:],如果未指定,则返回stdin。使用''.join(fileinput.input())

双方sysfileinput必须进口的,分别的,当然。

sys.stdin与Python 2和3,Windows,Unix兼容的快速示例

例如,如果您将数据通过管道传输到stdin,则只需要readfrom sys.stdin

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

我们可以看到它sys.stdin处于默认文本模式:

>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>

文件示例

假设您有一个文件,inputs.txt我们可以接受该文件并将其写回:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

更长的答案

这是一个完整的,易于复制的演示,使用两种方法,内建函数inputraw_input在Python 2中使用)和sys.stdin。数据未修改,因此处理是非操作。

首先,让我们为输入创建一个文件:

$ python -c "print('foo\nbar\nbaz')" > inputs.txt

并使用我们已经看到的代码,我们可以检查是否已创建文件:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt 
foo
bar
baz

这是sys.stdin.readPython 3 的帮助:

read(size=-1, /) method of _io.TextIOWrapper instance
    Read at most n characters from stream.

    Read from underlying buffer until we have n characters or we hit EOF.
    If n is negative or omitted, read until EOF.

内置函数inputraw_input在Python 2中)

内置函数input从标准输入读取到换行符,然后将其剥离(补码print,默认情况下会添加换行符)。此过程一直持续到得到EOF(文件结束)为止,此时它引发EOFError

因此,这是input在Python 3(或raw_inputPython 2)中用于从stdin读取的方法-因此我们创建了一个称为stdindemo.py的Python模块:

$ python -c "print('try:\n    while True:\n        print(input())\nexcept EOFError:\n    pass')" > stdindemo.py 

让我们将其打印出来,以确保它符合我们的预期:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

再次,input读取直到换行符,并从行中删除它。print添加换行符。因此,尽管它们都修改了输入,但它们的修改被取消了。(因此,它们本质上是彼此的补充。)

input获取文件结尾字符时,它将引发EOFError,我们将其忽略,然后从程序退出。

在Linux / Unix上,我们可以通过cat进行管道传输:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

或者我们可以从stdin重定向文件:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

我们还可以将模块作为脚本执行:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

这是inputPython 3 内置函数的帮助:

input(prompt=None, /)
    Read a string from standard input.  The trailing newline is stripped.

    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.

    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.

sys.stdin

在这里,我们使用编写演示脚本sys.stdin。迭代类似文件的对象的有效方法是使用类似文件的对象作为迭代器。从此输入写入stdout的补充方法是简单地使用sys.stdout.write

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

重新打印出来以确保它看起来正确:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

并将输入重定向到文件中:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

打入命令:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz

高尔夫的文件描述符

由于文件描述符stdinstdout为0和1分别,我们也可以通过那些open在Python 3(而不是2,请注意,我们仍然需要“W”写到标准输出)。

如果这在您的系统上有效,它将删除更多字符。

$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo

Python 2 io.open也可以这样做,但是导入需要更多空间:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

解决其他意见和答案

有一条评论建议''.join(sys.stdin)打高尔夫球,但是实际上比sys.stdin.read()长-再加上Python必须在内存中创建一个额外的列表(str.join如果没有给出列表,这是如何工作的)-对比一下:

''.join(sys.stdin)
sys.stdin.read()

最高答案表明:

import fileinput

for line in fileinput.input():
    pass

但是,由于sys.stdin实现了文件API,包括迭代器协议,因此与此相同:

import sys

for line in sys.stdin:
    pass

另一个答案确实表明了这一点。只要记住,如果你在解释这样做,你需要做的Ctrld如果你在Linux或Mac,或者Ctrlz在Windows上(后Enter),以结束文件的字符发送给该进程。此外,该答案还建议使用print(line)-最终会增加a-的'\n'使用print(line, end='')(如果在Python 2中,则需要from __future__ import print_function)。

真正的用例fileinput是读取一系列文件。

How do you read from stdin in Python?

I’m trying to do some of the code golf challenges, but they all require the input to be taken from stdin. How do I get that in Python?

You can use:

  • sys.stdin – A file-like object – call sys.stdin.read() to read everything.
  • input(prompt) – pass it an optional prompt to output, it reads from stdin up to the first newline, which it strips. You’d have to do this repeatedly to get more lines, at the end of the input it raises EOFError. (Probably not great for golfing.) In Python 2, this is rawinput(prompt).
  • open(0).read() – In Python 3, the builtin function open accepts file descriptors (integers representing operating system IO resources), and 0 is the descriptor of stdin. It returns a file-like object like sys.stdin – probably your best bet for golfing. In Python 2, this is io.open.
  • open('/dev/stdin').read() – similar to open(0), works on Python 2 and 3, but not on Windows (or even Cygwin).
  • fileinput.input() – returns an iterator over lines in all files listed in sys.argv[1:], or stdin if not given. Use like ''.join(fileinput.input()).

Both sys and fileinput must be imported, respectively, of course.

Quick sys.stdin examples compatible with Python 2 and 3, Windows, Unix

You just need to read from sys.stdin, for example, if you pipe data to stdin:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

We can see that sys.stdin is in default text mode:

>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>

file example

Say you have a file, inputs.txt, we can accept that file and write it back out:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

Longer answer

Here’s a complete, easily replicable demo, using two methods, the builtin function, input (use raw_input in Python 2), and sys.stdin. The data is unmodified, so the processing is a non-operation.

To begin with, let’s create a file for inputs:

$ python -c "print('foo\nbar\nbaz')" > inputs.txt

And using the code we’ve already seen, we can check that we’ve created the file:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt 
foo
bar
baz

Here’s the help on sys.stdin.read from Python 3:

read(size=-1, /) method of _io.TextIOWrapper instance
    Read at most n characters from stream.

    Read from underlying buffer until we have n characters or we hit EOF.
    If n is negative or omitted, read until EOF.

Builtin function, input (raw_input in Python 2)

The builtin function input reads from standard input up to a newline, which is stripped (complementing print, which adds a newline by default.) This occurs until it gets EOF (End Of File), at which point it raises EOFError.

Thus, here’s how you can use input in Python 3 (or raw_input in Python 2) to read from stdin – so we create a Python module we call stdindemo.py:

$ python -c "print('try:\n    while True:\n        print(input())\nexcept EOFError:\n    pass')" > stdindemo.py 

And let’s print it back out to ensure it’s as we expect:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

Again, input reads up until the newline and essentially strips it from the line. print adds a newline. So while they both modify the input, their modifications cancel. (So they are essentially each other’s complement.)

And when input gets the end-of-file character, it raises EOFError, which we ignore and then exit from the program.

And on Linux/Unix, we can pipe from cat:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

Or we can just redirect the file from stdin:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

We can also execute the module as a script:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

Here’s the help on the builtin input from Python 3:

input(prompt=None, /)
    Read a string from standard input.  The trailing newline is stripped.

    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.

    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.

sys.stdin

Here we make a demo script using sys.stdin. The efficient way to iterate over a file-like object is to use the file-like object as an iterator. The complementary method to write to stdout from this input is to simply use sys.stdout.write:

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

Print it back out to make sure it looks right:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

And redirecting the inputs into the file:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

Golfed into a command:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz

File Descriptors for Golfing

Since the file descriptors for stdin and stdout are 0 and 1 respectively, we can also pass those to open in Python 3 (not 2, and note that we still need the ‘w’ for writing to stdout).

If this works on your system, it will shave off more characters.

$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo

Python 2’s io.open does this as well, but the import takes a lot more space:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

Addressing other comments and answers

One comment suggests ''.join(sys.stdin) for golfing but that’s actually longer than sys.stdin.read() – plus Python must create an extra list in memory (that’s how str.join works when not given a list) – for contrast:

''.join(sys.stdin)
sys.stdin.read()

The top answer suggests:

import fileinput

for line in fileinput.input():
    pass

But, since sys.stdin implements the file API, including the iterator protocol, that’s just the same as this:

import sys

for line in sys.stdin:
    pass

Another answer does suggest this. Just remember that if you do it in an interpreter, you’ll need to do Ctrld if you’re on Linux or Mac, or Ctrlz on Windows (after Enter) to send the end-of-file character to the process. Also, that answer suggests print(line) – which adds a '\n' to the end – use print(line, end='') instead (if in Python 2, you’ll need from __future__ import print_function).

The real use-case for fileinput is for reading in a series of files.


回答 6

其他人提出的答案:

for line in sys.stdin:
  print line

是非常简单且具有Python风格的代码,但必须注意,脚本将等到EOF才开始对输入行进行迭代。

这意味着tail -f error_log | myscript.py将不会按预期处理行。

这种用例的正确脚本是:

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

更新
从注释中可以看出,在python 2上仅可能涉及缓冲,因此您最终要在发出打印调用之前等待缓冲区填充或EOF。

The answer proposed by others:

for line in sys.stdin:
  print line

is very simple and pythonic, but it must be noted that the script will wait until EOF before starting to iterate on the lines of input.

This means that tail -f error_log | myscript.py will not process lines as expected.

The correct script for such a use case would be:

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

UPDATE
From the comments it has been cleared that on python 2 only there might be buffering involved, so that you end up waiting for the buffer to fill or EOF before the print call is issued.


回答 7

这会将标准输入回显到标准输出:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()

This will echo standard input to standard output:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()

回答 8

如果使用sys.stdin,则还可以在所有变量上进行构建,如果至少存在一个自变量,则还可以执行以下操作从一个自变量文件中读取,否则返回标准输入:

import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin    
for line in f:
#     Do your stuff

并将其用作

$ python do-my-stuff.py infile.txt

要么

$ cat infile.txt | python do-my-stuff.py

甚至

$ python do-my-stuff.py < infile.txt

这将使你的Python脚本的行为像许多GNU / Unix程序,例如catgrepsed

Building on all the anwers using sys.stdin, you can also do something like the following to read from an argument file if at least one argument exists, and fall back to stdin otherwise:

import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin    
for line in f:
#     Do your stuff

and use it as either

$ python do-my-stuff.py infile.txt

or

$ cat infile.txt | python do-my-stuff.py

or even

$ python do-my-stuff.py < infile.txt

That would make your Python script behave like many GNU/Unix programs such as cat, grep and sed.


回答 9

argparse 是一个简单的解决方案

与Python第2版和第3版兼容的示例:

#!/usr/bin/python

import argparse
import sys

parser = argparse.ArgumentParser()

parser.add_argument('infile',
                    default=sys.stdin,
                    type=argparse.FileType('r'),
                    nargs='?')

args = parser.parse_args()

data = args.infile.read()

您可以通过多种方式运行此脚本:

1.使用 stdin

echo 'foo bar' | ./above-script.py

  或更短一些,只需替换echo此处的 字符串

./above-script.py <<< 'foo bar'

2.使用文件名参数

echo 'foo bar' > my-file.data
./above-script.py my-file.data

3. stdin通过特殊文件名使用-

echo 'foo bar' | ./above-script.py -

argparse is an easy solution

Example compatible with both Python versions 2 and 3:

#!/usr/bin/python

import argparse
import sys

parser = argparse.ArgumentParser()

parser.add_argument('infile',
                    default=sys.stdin,
                    type=argparse.FileType('r'),
                    nargs='?')

args = parser.parse_args()

data = args.infile.read()

You can run this script in many ways:

1. Using stdin

echo 'foo bar' | ./above-script.py

  or shorter by replacing echo by here string:

./above-script.py <<< 'foo bar'

2. Using a filename argument

echo 'foo bar' > my-file.data
./above-script.py my-file.data

3. Using stdin through the special filename -

echo 'foo bar' | ./above-script.py -

回答 10

以下代码芯片将为您提供帮助(它将把所有的stdin阻塞读EOF入到一个字符串中):

import sys
input_str = sys.stdin.read()
print input_str.split()

The following chip of code will help you (it will read all of stdin blocking unto EOF, into one string):

import sys
input_str = sys.stdin.read()
print input_str.split()

回答 11

令我惊讶的是,到目前为止,还没有人提到此黑客:

python -c "import sys; set(map(sys.stdout.write,sys.stdin))"

在python2中,您可以删除set()呼叫,但是它将以任何一种方式发出提示

I am pretty amazed no one had mentioned this hack so far:

python -c "import sys; set(map(sys.stdout.write,sys.stdin))"

in python2 you can drop the set() call, but it would word either way


回答 12

尝试这个:

import sys

print sys.stdin.read().upper()

并使用以下命令进行检查:

$ echo "Hello World" | python myFile.py

Try this:

import sys

print sys.stdin.read().upper()

and check it with:

$ echo "Hello World" | python myFile.py

回答 13

您可以从stdin读取内容,然后将输入存储到“数据”中,如下所示:

data = ""
for line in sys.stdin:
    data += line

You can read from stdin and then store inputs into “data” as follows:

data = ""
for line in sys.stdin:
    data += line

回答 14

Windows读取sys.stdin,但是要读取Windows上的二进制数据,您需要格外小心,因为sys.stdin在文本模式下打开了二进制数据\r\n用替换它们会损坏\n

解决方案是,如果检测到Windows + Python 2,则将模式设置为二进制,并在Python 3上使用sys.stdin.buffer

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

Read from sys.stdin, but to read binary data on Windows, you need to be extra careful, because sys.stdin there is opened in text mode and it will corrupt \r\n replacing them with \n.

The solution is to set mode to binary if Windows + Python 2 is detected, and on Python 3 use sys.stdin.buffer.

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

回答 15

我使用以下方法,它从stdin返回一个字符串(我将其用于json解析)。它适用于Windows上的管道和提示(尚未在Linux上进行测试)。提示时,两个换行符指示输入结束。

def get_from_stdin():

  lb = 0
  stdin = ''

  for line in sys.stdin:
    if line == "\n":
        lb += 1
        if lb == 2:
            break
    else:
        lb = 0
        stdin += line

  return stdin

I use the following method, it returns a string from stdin (I use it for json parsing). It works with pipe and prompt on Windows (not tested on Linux yet). When prompting, two line breaks indicate end of input.

def get_from_stdin():

  lb = 0
  stdin = ''

  for line in sys.stdin:
    if line == "\n":
        lb += 1
        if lb == 2:
            break
    else:
        lb = 0
        stdin += line

  return stdin

回答 16

我的解决方案有问题

import sys

for line in sys.stdin:
    print(line)

如果您不向stdin传递任何数据,它将永远阻塞。这就是为什么我喜欢这个答案:为什么先检查stdin上是否有一些数据,然后再读取它。这就是我最终要做的事情:

import sys
import select

# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
    help_file_fragment = sys.stdin.read()
else:
    print("No data passed to stdin", file=sys.stderr)
    sys.exit(2)

The problem I have with solution

import sys

for line in sys.stdin:
    print(line)

is that if you don’t pass any data to stdin, it will block forever. That’s why I love this answer: check if there is some data on stdin first, and then read it. This is what I ended up doing:

import sys
import select

# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
    help_file_fragment = sys.stdin.read()
else:
    print("No data passed to stdin", file=sys.stderr)
    sys.exit(2)

回答 17

使它工作以读取通过管道连接到它的套接字时,我遇到了一些问题。当套接字关闭时,它开始在活动循环中返回空字符串。因此,这就是我的解决方案(我仅在linux上进行了测试,但希望它能在所有其他系统上运行)

import sys, os
sep=os.linesep

while sep == os.linesep:
    data = sys.stdin.readline()               
    sep = data[-len(os.linesep):]
    print '> "%s"' % data.strip()

因此,如果您开始在套接字上侦听,它将可以正常工作(例如在bash中):

while :; do nc -l 12345 | python test.py ; done

您可以使用telnet调用它,也可以将浏览器指向localhost:12345

I had some issues when getting this to work for reading over sockets piped to it. When the socket got closed it started returning empty string in an active loop. So this is my solution to it (which I only tested in linux, but hope it works in all other systems)

import sys, os
sep=os.linesep

while sep == os.linesep:
    data = sys.stdin.readline()               
    sep = data[-len(os.linesep):]
    print '> "%s"' % data.strip()

So if you start listening on a socket it will work properly (e.g. in bash):

while :; do nc -l 12345 | python test.py ; done

And you can call it with telnet or just point a browser to localhost:12345


回答 18

关于此:

for line in sys.stdin:

我只是在python 2.7上尝试了一个很大的文件(遵循别人的建议),但出于上述原因(长时间未发生任何事情),我不建议这样做。

我最终得到了一个稍微多一点的pythonic解决方案(它适用于更大的文件):

with open(sys.argv[1], 'r') as f:
    for line in f:

然后,我可以按以下方式在本地运行脚本:

python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work

Regarding this:

for line in sys.stdin:

I just tried it on python 2.7 (following someone else’s suggestion) for a very large file, and I don’t recommend it, precisely for the reasons mentioned above (nothing happens for a long time).

I ended up with a slightly more pythonic solution (and it works on bigger files):

with open(sys.argv[1], 'r') as f:
    for line in f:

Then I can run the script locally as:

python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work

回答 19

对于Python 3,应为:

# Filename e.g. cat.py
import sys

for line in sys.stdin:
    print(line, end="")

这基本上是cat(1)的一种简单形式,因为它不会在每行之后添加换行符。您可以使用它(在将文件标记为可执行文件后,使用chmod +x cat.py诸如:

echo Hello | ./cat.py

For Python 3 that would be:

# Filename e.g. cat.py
import sys

for line in sys.stdin:
    print(line, end="")

This is basically a simple form of cat(1), since it doesn’t add a newline after each line. You can use this (after You marked the file executable using chmod +x cat.py such as:

echo Hello | ./cat.py

回答 20

os.read(0, x) 从0表示标准输入读取xbytes。这是一个无缓冲的读取,比sys.stdin.read()的级别低。

There is os.read(0, x) which reads xbytes from 0 which represents stdin. This is an unbuffered read, more low level than sys.stdin.read()


回答 21

使用-c命令时,以一种棘手的方式,您无需阅读stdin(在某些情况下更为灵活),就可以通过将sell命令放在以引号开头的括号内的引号中来将Shell脚本命令传递给python命令$

例如

python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"

这将计算goldendict的历史记录文件中的行数。

When using -c command, as a tricky way, instead of reading the stdin (and more flexible in some cases) you can pass a shell script command as well to your python command by putting the sell command in quotes within a parenthesis started by $ sign.

e.g.

python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"

This will count the number of lines from goldendict’s history file.


如何将零填充到字符串?

问题:如何将零填充到字符串?

用Python的方法将数字字符串填充到左侧的零(即数字字符串具有特定的长度)是什么?

What is a Pythonic way to pad a numeric string with zeroes to the left, i.e. so the numeric string has a specific length?


回答 0

字串:

>>> n = '4'
>>> print(n.zfill(3))
004

对于数字:

>>> n = 4
>>> print(f'{n:03}') # Preferred method, python >= 3.6
004
>>> print('%03d' % n)
004
>>> print(format(n, '03')) # python >= 2.6
004
>>> print('{0:03d}'.format(n))  # python >= 2.6 + python 3
004
>>> print('{foo:03d}'.format(foo=n))  # python >= 2.6 + python 3
004
>>> print('{:03d}'.format(n))  # python >= 2.7 + python3
004

字符串格式化文档

Strings:

>>> n = '4'
>>> print(n.zfill(3))
004

And for numbers:

>>> n = 4
>>> print(f'{n:03}') # Preferred method, python >= 3.6
004
>>> print('%03d' % n)
004
>>> print(format(n, '03')) # python >= 2.6
004
>>> print('{0:03d}'.format(n))  # python >= 2.6 + python 3
004
>>> print('{foo:03d}'.format(foo=n))  # python >= 2.6 + python 3
004
>>> print('{:03d}'.format(n))  # python >= 2.7 + python3
004

String formatting documentation.


回答 1

只需使用字符串对象的rjust方法即可。

本示例将使一个10个字符长的字符串,必要时进行填充。

>>> t = 'test'
>>> t.rjust(10, '0')
>>> '000000test'

Just use the rjust method of the string object.

This example will make a string of 10 characters long, padding as necessary.

>>> t = 'test'
>>> t.rjust(10, '0')
>>> '000000test'

回答 2

此外zfill,您可以使用常规的字符串格式:

print(f'{number:05d}') # (since Python 3.6), or
print('{:05d}'.format(number)) # or
print('{0:05d}'.format(number)) # or (explicit 0th positional arg. selection)
print('{n:05d}'.format(n=number)) # or (explicit `n` keyword arg. selection)
print(format(number, '05d'))

字符串格式f-strings的文档。

Besides zfill, you can use general string formatting:

print(f'{number:05d}') # (since Python 3.6), or
print('{:05d}'.format(number)) # or
print('{0:05d}'.format(number)) # or (explicit 0th positional arg. selection)
print('{n:05d}'.format(n=number)) # or (explicit `n` keyword arg. selection)
print(format(number, '05d'))

Documentation for string formatting and f-strings.


回答 3

对于使用f字符串的Python 3.6+:

>>> i = 1
>>> f"{i:0>2}"  # Works for both numbers and strings.
'01'
>>> f"{i:02}"  # Works only for numbers.
'01'

对于Python 2至Python 3.5:

>>> "{:0>2}".format("1")  # Works for both numbers and strings.
'01'
>>> "{:02}".format(1)  # Works only for numbers.
'01'

For Python 3.6+ using f-strings:

>>> i = 1
>>> f"{i:0>2}"  # Works for both numbers and strings.
'01'
>>> f"{i:02}"  # Works only for numbers.
'01'

For Python 2 to Python 3.5:

>>> "{:0>2}".format("1")  # Works for both numbers and strings.
'01'
>>> "{:02}".format(1)  # Works only for numbers.
'01'

回答 4

>>> '99'.zfill(5)
'00099'
>>> '99'.rjust(5,'0')
'00099'

如果您想要相反的话:

>>> '99'.ljust(5,'0')
'99000'
>>> '99'.zfill(5)
'00099'
>>> '99'.rjust(5,'0')
'00099'

if you want the opposite:

>>> '99'.ljust(5,'0')
'99000'

回答 5

str(n).zfill(width)可以与strings,ints,floats …一起使用,并且与Python 2. x和3. x兼容:

>>> n = 3
>>> str(n).zfill(5)
'00003'
>>> n = '3'
>>> str(n).zfill(5)
'00003'
>>> n = '3.0'
>>> str(n).zfill(5)
'003.0'

str(n).zfill(width) will work with strings, ints, floats… and is Python 2.x and 3.x compatible:

>>> n = 3
>>> str(n).zfill(5)
'00003'
>>> n = '3'
>>> str(n).zfill(5)
'00003'
>>> n = '3.0'
>>> str(n).zfill(5)
'003.0'

回答 6

对于那些来这里了解的人,而不仅仅是一个快速的答案。我特别针对时间字符串执行以下操作:

hour = 4
minute = 3
"{:0>2}:{:0>2}".format(hour,minute)
# prints 04:03

"{:0>3}:{:0>5}".format(hour,minute)
# prints '004:00003'

"{:0<3}:{:0<5}".format(hour,minute)
# prints '400:30000'

"{:$<3}:{:#<5}".format(hour,minute)
# prints '4$$:3####'

“ 0”符号用“ 2”填充字符替换,默认为空白

“>”符号会分配字符串左侧的所有2个“ 0”字符

“:”符号format_spec

For the ones who came here to understand and not just a quick answer. I do these especially for time strings:

hour = 4
minute = 3
"{:0>2}:{:0>2}".format(hour,minute)
# prints 04:03

"{:0>3}:{:0>5}".format(hour,minute)
# prints '004:00003'

"{:0<3}:{:0<5}".format(hour,minute)
# prints '400:30000'

"{:$<3}:{:#<5}".format(hour,minute)
# prints '4$$:3####'

“0” symbols what to replace with the “2” padding characters, the default is an empty space

“>” symbols allign all the 2 “0” character to the left of the string

“:” symbols the format_spec


回答 7

将数字字符串的左边填充零的最有效方法是什么(即,数字字符串具有特定的长度)?

str.zfill 专用于此目的:

>>> '1'.zfill(4)
'0001'

请注意,它专门用于根据请求处理数字字符串,并将a +-移至字符串的开头:

>>> '+1'.zfill(4)
'+001'
>>> '-1'.zfill(4)
'-001'

这是有关的帮助str.zfill

>>> help(str.zfill)
Help on method_descriptor:

zfill(...)
    S.zfill(width) -> str

    Pad a numeric string S with zeros on the left, to fill a field
    of the specified width. The string S is never truncated.

性能

这也是替代方法最有效的方法:

>>> min(timeit.repeat(lambda: '1'.zfill(4)))
0.18824880896136165
>>> min(timeit.repeat(lambda: '1'.rjust(4, '0')))
0.2104538488201797
>>> min(timeit.repeat(lambda: f'{1:04}'))
0.32585487607866526
>>> min(timeit.repeat(lambda: '{:04}'.format(1)))
0.34988890308886766

为了最好地将苹果与苹果进行比较%(请注意,它实际上速度较慢),否则将预先计算:

>>> min(timeit.repeat(lambda: '1'.zfill(0 or 4)))
0.19728074967861176
>>> min(timeit.repeat(lambda: '%04d' % (0 or 1)))
0.2347015216946602

实作

稍微挖掘一下,我发现该zfill方法的实现Objects/stringlib/transmogrify.h

static PyObject *
stringlib_zfill(PyObject *self, PyObject *args)
{
    Py_ssize_t fill;
    PyObject *s;
    char *p;
    Py_ssize_t width;

    if (!PyArg_ParseTuple(args, "n:zfill", &width))
        return NULL;

    if (STRINGLIB_LEN(self) >= width) {
        return return_self(self);
    }

    fill = width - STRINGLIB_LEN(self);

    s = pad(self, fill, 0, '0');

    if (s == NULL)
        return NULL;

    p = STRINGLIB_STR(s);
    if (p[fill] == '+' || p[fill] == '-') {
        /* move sign to beginning of string */
        p[0] = p[fill];
        p[fill] = '0';
    }

    return s;
}

让我们来看一下这个C代码。

它首先在位置上解析参数,这意味着它不允许关键字参数:

>>> '1'.zfill(width=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: zfill() takes no keyword arguments

然后,它检查长度是否相同或更长,在这种情况下,它将返回字符串。

>>> '1'.zfill(0)
'1'

zfill电话pad(此pad功能也被称为ljustrjustcenter也)。这基本上将内容复制到一个新的字符串中并填充填充。

static inline PyObject *
pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
{
    PyObject *u;

    if (left < 0)
        left = 0;
    if (right < 0)
        right = 0;

    if (left == 0 && right == 0) {
        return return_self(self);
    }

    u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);
    if (u) {
        if (left)
            memset(STRINGLIB_STR(u), fill, left);
        memcpy(STRINGLIB_STR(u) + left,
               STRINGLIB_STR(self),
               STRINGLIB_LEN(self));
        if (right)
            memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
                   fill, right);
    }

    return u;
}

调用之后padzfill将任何原始的字符串移到字符串的开头+-开头。

请注意,原始字符串实际上不需要是数字:

>>> '+foo'.zfill(10)
'+000000foo'
>>> '-foo'.zfill(10)
'-000000foo'

What is the most pythonic way to pad a numeric string with zeroes to the left, i.e., so the numeric string has a specific length?

str.zfill is specifically intended to do this:

>>> '1'.zfill(4)
'0001'

Note that it is specifically intended to handle numeric strings as requested, and moves a + or - to the beginning of the string:

>>> '+1'.zfill(4)
'+001'
>>> '-1'.zfill(4)
'-001'

Here’s the help on str.zfill:

>>> help(str.zfill)
Help on method_descriptor:

zfill(...)
    S.zfill(width) -> str

    Pad a numeric string S with zeros on the left, to fill a field
    of the specified width. The string S is never truncated.

Performance

This is also the most performant of alternative methods:

>>> min(timeit.repeat(lambda: '1'.zfill(4)))
0.18824880896136165
>>> min(timeit.repeat(lambda: '1'.rjust(4, '0')))
0.2104538488201797
>>> min(timeit.repeat(lambda: f'{1:04}'))
0.32585487607866526
>>> min(timeit.repeat(lambda: '{:04}'.format(1)))
0.34988890308886766

To best compare apples to apples for the % method (note it is actually slower), which will otherwise pre-calculate:

>>> min(timeit.repeat(lambda: '1'.zfill(0 or 4)))
0.19728074967861176
>>> min(timeit.repeat(lambda: '%04d' % (0 or 1)))
0.2347015216946602

Implementation

With a little digging, I found the implementation of the zfill method in Objects/stringlib/transmogrify.h:

static PyObject *
stringlib_zfill(PyObject *self, PyObject *args)
{
    Py_ssize_t fill;
    PyObject *s;
    char *p;
    Py_ssize_t width;

    if (!PyArg_ParseTuple(args, "n:zfill", &width))
        return NULL;

    if (STRINGLIB_LEN(self) >= width) {
        return return_self(self);
    }

    fill = width - STRINGLIB_LEN(self);

    s = pad(self, fill, 0, '0');

    if (s == NULL)
        return NULL;

    p = STRINGLIB_STR(s);
    if (p[fill] == '+' || p[fill] == '-') {
        /* move sign to beginning of string */
        p[0] = p[fill];
        p[fill] = '0';
    }

    return s;
}

Let’s walk through this C code.

It first parses the argument positionally, meaning it doesn’t allow keyword arguments:

>>> '1'.zfill(width=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: zfill() takes no keyword arguments

It then checks if it’s the same length or longer, in which case it returns the string.

>>> '1'.zfill(0)
'1'

zfill calls pad (this pad function is also called by ljust, rjust, and center as well). This basically copies the contents into a new string and fills in the padding.

static inline PyObject *
pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
{
    PyObject *u;

    if (left < 0)
        left = 0;
    if (right < 0)
        right = 0;

    if (left == 0 && right == 0) {
        return return_self(self);
    }

    u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);
    if (u) {
        if (left)
            memset(STRINGLIB_STR(u), fill, left);
        memcpy(STRINGLIB_STR(u) + left,
               STRINGLIB_STR(self),
               STRINGLIB_LEN(self));
        if (right)
            memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
                   fill, right);
    }

    return u;
}

After calling pad, zfill moves any originally preceding + or - to the beginning of the string.

Note that for the original string to actually be numeric is not required:

>>> '+foo'.zfill(10)
'+000000foo'
>>> '-foo'.zfill(10)
'-000000foo'

回答 8

width = 10
x = 5
print "%0*d" % (width, x)
> 0000000005

有关所有激动人心的细节,请参见打印文档!

适用于Python 3.x的更新(7.5年后)

最后一行现在应该是:

print("%0*d" % (width, x))

print()现在是一个函数,而不是一个语句。请注意,我仍然更喜欢Old School printf()风格,因为IMNSHO读起来更好,并且因为,嗯,自1980年1月以来我一直在使用该符号。

width = 10
x = 5
print "%0*d" % (width, x)
> 0000000005

See the print documentation for all the exciting details!

Update for Python 3.x (7.5 years later)

That last line should now be:

print("%0*d" % (width, x))

I.e. print() is now a function, not a statement. Note that I still prefer the Old School printf() style because, IMNSHO, it reads better, and because, um, I’ve been using that notation since January, 1980. Something … old dogs .. something something … new tricks.


回答 9

使用Python时>= 3.6,最干净的方法是使用带字符串格式的f 字符串

>>> s = f"{1:08}"  # inline with int
>>> s
'00000001'
>>> s = f"{'1':0>8}"  # inline with str
>>> s
'00000001'
>>> n = 1
>>> s = f"{n:08}"  # int variable
>>> s
'00000001'
>>> c = "1"
>>> s = f"{c:0>8}"  # str variable
>>> s
'00000001'

我更喜欢使用格式化int,因为只有这样才能正确处理符号:

>>> f"{-1:08}"
'-0000001'

>>> f"{1:+08}"
'+0000001'

>>> f"{'-1':0>8}"
'000000-1'

When using Python >= 3.6, the cleanest way is to use f-strings with string formatting:

>>> s = f"{1:08}"  # inline with int
>>> s
'00000001'
>>> s = f"{'1':0>8}"  # inline with str
>>> s
'00000001'
>>> n = 1
>>> s = f"{n:08}"  # int variable
>>> s
'00000001'
>>> c = "1"
>>> s = f"{c:0>8}"  # str variable
>>> s
'00000001'

I would prefer formatting with an int, since only then the sign is handled correctly:

>>> f"{-1:08}"
'-0000001'

>>> f"{1:+08}"
'+0000001'

>>> f"{'-1':0>8}"
'000000-1'

回答 10

对于保存为整数的邮政编码:

>>> a = 6340
>>> b = 90210
>>> print '%05d' % a
06340
>>> print '%05d' % b
90210

For zip codes saved as integers:

>>> a = 6340
>>> b = 90210
>>> print '%05d' % a
06340
>>> print '%05d' % b
90210

回答 11

快速时序比较:

setup = '''
from random import randint
def test_1():
    num = randint(0,1000000)
    return str(num).zfill(7)
def test_2():
    num = randint(0,1000000)
    return format(num, '07')
def test_3():
    num = randint(0,1000000)
    return '{0:07d}'.format(num)
def test_4():
    num = randint(0,1000000)
    return format(num, '07d')
def test_5():
    num = randint(0,1000000)
    return '{:07d}'.format(num)
def test_6():
    num = randint(0,1000000)
    return '{x:07d}'.format(x=num)
def test_7():
    num = randint(0,1000000)
    return str(num).rjust(7, '0')
'''
import timeit
print timeit.Timer("test_1()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_2()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_3()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_4()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_5()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_6()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_7()", setup=setup).repeat(3, 900000)


> [2.281613943830961, 2.2719342631547077, 2.261691106209631]
> [2.311480238815406, 2.318420542148333, 2.3552384305184493]
> [2.3824197456864304, 2.3457239951596485, 2.3353268829498646]
> [2.312442972404032, 2.318053102249902, 2.3054072168069872]
> [2.3482314132374853, 2.3403386400002475, 2.330108825844775]
> [2.424549090688892, 2.4346475296851438, 2.429691196530058]
> [2.3259756401716487, 2.333549212826732, 2.32049893822186]

我对不同的重复进行了不同的测试。差异并不大,但是在所有测试中,zfill解决方案都是最快的。

Quick timing comparison:

setup = '''
from random import randint
def test_1():
    num = randint(0,1000000)
    return str(num).zfill(7)
def test_2():
    num = randint(0,1000000)
    return format(num, '07')
def test_3():
    num = randint(0,1000000)
    return '{0:07d}'.format(num)
def test_4():
    num = randint(0,1000000)
    return format(num, '07d')
def test_5():
    num = randint(0,1000000)
    return '{:07d}'.format(num)
def test_6():
    num = randint(0,1000000)
    return '{x:07d}'.format(x=num)
def test_7():
    num = randint(0,1000000)
    return str(num).rjust(7, '0')
'''
import timeit
print timeit.Timer("test_1()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_2()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_3()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_4()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_5()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_6()", setup=setup).repeat(3, 900000)
print timeit.Timer("test_7()", setup=setup).repeat(3, 900000)


> [2.281613943830961, 2.2719342631547077, 2.261691106209631]
> [2.311480238815406, 2.318420542148333, 2.3552384305184493]
> [2.3824197456864304, 2.3457239951596485, 2.3353268829498646]
> [2.312442972404032, 2.318053102249902, 2.3054072168069872]
> [2.3482314132374853, 2.3403386400002475, 2.330108825844775]
> [2.424549090688892, 2.4346475296851438, 2.429691196530058]
> [2.3259756401716487, 2.333549212826732, 2.32049893822186]

I’ve made different tests of different repetitions. The differences are not huge, but in all tests, the zfill solution was fastest.


回答 12

另一种方法是将列表理解与长度条件检查结合使用。下面是一个演示:

# input list of strings that we want to prepend zeros
In [71]: list_of_str = ["101010", "10101010", "11110", "0000"]

# prepend zeros to make each string to length 8, if length of string is less than 8
In [83]: ["0"*(8-len(s)) + s if len(s) < desired_len else s for s in list_of_str]
Out[83]: ['00101010', '10101010', '00011110', '00000000']

Another approach would be to use a list comprehension with a condition checking for lengths. Below is a demonstration:

# input list of strings that we want to prepend zeros
In [71]: list_of_str = ["101010", "10101010", "11110", "0000"]

# prepend zeros to make each string to length 8, if length of string is less than 8
In [83]: ["0"*(8-len(s)) + s if len(s) < desired_len else s for s in list_of_str]
Out[83]: ['00101010', '10101010', '00011110', '00000000']

回答 13

还可以:

 h = 2
 m = 7
 s = 3
 print("%02d:%02d:%02d" % (h, m, s))

因此输出为:“ 02:07:03”

Its ok too:

 h = 2
 m = 7
 s = 3
 print("%02d:%02d:%02d" % (h, m, s))

so output will be: “02:07:03”


回答 14

您还可以重复“ 0”,将其添加到str(n)最右端的宽度切片。快速而肮脏的表情。

def pad_left(n, width, pad="0"):
    return ((pad * width) + str(n))[-width:]

You could also repeat “0”, prepend it to str(n) and get the rightmost width slice. Quick and dirty little expression.

def pad_left(n, width, pad="0"):
    return ((pad * width) + str(n))[-width:]

为什么Python无法解析此JSON数据?

问题:为什么Python无法解析此JSON数据?

我在文件中有此JSON:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

我编写了以下脚本来打印所有JSON数据:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

但是,该程序会引发异常:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

如何解析JSON并提取其值?

I have this JSON in a file:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

I wrote this script to print all of the JSON data:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

This program raises an exception, though:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

How can I parse the JSON and extract its values?


回答 0

您的数据不是有效的JSON格式。您有[]什么时候应该拥有{}

  • []用于JSON数组,list在Python 中称为
  • {}用于JSON对象(dict在Python 中称为JSON对象)

JSON文件的外观如下:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

然后,您可以使用您的代码:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

使用数据,您现在还可以找到类似的值:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

试试看,看看是否有意义。

Your data is not valid JSON format. You have [] when you should have {}:

  • [] are for JSON arrays, which are called list in Python
  • {} are for JSON objects, which are called dict in Python

Here’s how your JSON file should look:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

Then you can use your code:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

With data, you can now also find values like so:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

Try those out and see if it starts to make sense.


回答 1

data.json应该看起来像这样:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

您的代码应为:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

请注意,这仅在Python 2.6及更高版本中有效,因为它取决于with-statement。在Python 2.5中使用from __future__ import with_statement,在Python <= 2.4中,请参见Justin Peel的答案,该答案基于该答案。

您现在还可以像这样访问单个值:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'

Your data.json should look like this:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

Your code should be:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

Note that this only works in Python 2.6 and up, as it depends upon the with-statement. In Python 2.5 use from __future__ import with_statement, in Python <= 2.4, see Justin Peel’s answer, which this answer is based upon.

You can now also access single values like this:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'

回答 2

贾斯汀·皮尔(Justin Peel)的回答确实很有帮助,但是,如果您使用的是Python 3,则应按以下方式读取JSON:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

注意:使用json.loads代替json.load。在Python 3中,json.loads采用字符串参数。json.load采用类似文件的对象参数。data_file.read()返回一个字符串对象。

老实说,在大多数情况下,将所有json数据加载到内存中都不是问题。

Justin Peel’s answer is really helpful, but if you are using Python 3 reading JSON should be done like this:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

Note: use json.loads instead of json.load. In Python 3, json.loads takes a string parameter. json.load takes a file-like object parameter. data_file.read() returns a string object.

To be honest, I don’t think it’s a problem to load all json data into memory most cases.


回答 3

data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))

回答 4

“超JSON”或简称“ ujson”可以处理[]您的JSON文件输入中的内容。如果您正在将程序中的JSON输入文件作为JSON元素列表读取;例如,[{[{}]}, {}, [], etc...]ujson可以处理字典列表的任何任意顺序,即列表字典。

您可以在Python包索引中找到ujson,并且该API与Python的内置json库几乎相同。

如果您要加载较大的JSON文件,则ujson也会更快。与提供的相同链接中的其他Python JSON库相比,您可以看到性能详细信息。

“Ultra JSON” or simply “ujson” can handle having [] in your JSON file input. If you’re reading a JSON input file into your program as a list of JSON elements; such as, [{[{}]}, {}, [], etc...] ujson can handle any arbitrary order of lists of dictionaries, dictionaries of lists.

You can find ujson in the Python package index and the API is almost identical to Python’s built-in json library.

ujson is also much faster if you’re loading larger JSON files. You can see the performance details in comparison to other Python JSON libraries in the same link provided.


回答 5

如果您使用的是Python3,则可以尝试将(connection.json文件)JSON 更改为:

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

然后使用以下代码:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1

If you’re using Python3, you can try changing your (connection.json file) JSON to:

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

Then using the following code:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1

回答 6

在这里,您可以使用修改后的data.json文件:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

您可以使用以下几行在控制台上调用或打印数据:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

预期输出print(data_item['parameters'][0]['id'])

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

预期输出print(data_item['parameters'][0]['id'])

valore

Here you go with modified data.json file:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

You can call or print data on console by using below lines:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

Expected output for print(data_item['parameters'][0]['id']):

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

Expected output for print(data_item['parameters'][0]['id']):

valore

回答 7

该解析有两种类型。

  1. 从系统路径解析文件中的数据
  2. 从远程URL解析JSON。

从文件中,您可以使用以下内容

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

该小节解释了使用两种情况的完整解析和获取值。使用Python解析JSON

There are two types in this parsing.

  1. Parsing data from a file from a system path
  2. Parsing JSON from remote URL.

From a file, you can use the following

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

This arcticle explains the full parsing and getting values using two scenarios.Parsing JSON using Python


回答 8

作为python3用户

loadloads方法之间的区别非常重要,尤其是当您从文件中读取json数据时。

如文档中所述:

json.load:

使用此转换表将fp(支持.read()的文本文件或包含JSON文档的二进制文件)反序列化为Python对象。

json.loads:

json.loads:使用此转换表将s(包含JSON文档的str,字节或字节数组实例)反序列化为Python对象。

json.load方法可以读取二进制文件,因此可以直接读取打开的json文档。

with open('./recipes.json') as data:
  all_recipes = json.load(data)

结果,您的json数据以根据此转换表指定的格式可用:

https://docs.python.org/3.7/library/json.html#json-to-py-table

As a python3 user,

The difference between load and loads methods is important especially when you read json data from file.

As stated in the docs:

json.load:

Deserialize fp (a .read()-supporting text file or binary file containing a JSON document) to a Python object using this conversion table.

json.loads:

json.loads: Deserialize s (a str, bytes or bytearray instance containing a JSON document) to a Python object using this conversion table.

json.load method can directly read opened json document since it is able to read binary file.

with open('./recipes.json') as data:
  all_recipes = json.load(data)

As a result, your json data available as in a format specified according to this conversion table:

https://docs.python.org/3.7/library/json.html#json-to-py-table


获取实例的类名?

问题:获取实例的类名?

如果我从中创建函数的基类是派生该实例类的基类,那么如何找到在Python中创建对象实例的类的名称?

我想也许检查模块可能在这里帮助了我,但似乎没有给我我想要的东西。除了解析__class__成员之外,我不确定如何获取此信息。

How do I find out a name of class that created an instance of an object in Python if the function I am doing this from is the base class of which the class of the instance has been derived?

Was thinking maybe the inspect module might have helped me out here, but it doesn’t seem to give me what I want. And short of parsing the __class__ member, I’m not sure how to get at this information.


回答 0

您是否尝试过该类的__name__属性?即type(x).__name__会给你Class的名字,我想这就是你想要的。

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

如果您仍在使用Python 2,请注意上述方法仅适用于新型类(在Python 3+中,所有类均为“新型”类)。您的代码可能使用一些旧式类。这两种方法均适用:

x.__class__.__name__

Have you tried the __name__ attribute of the class? ie type(x).__name__ will give you the name of the class, which I think is what you want.

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

If you’re still using Python 2, note that the above method works with new-style classes only (in Python 3+ all classes are “new-style” classes). Your code might use some old-style classes. The following works for both:

x.__class__.__name__

回答 1

您是否要将类的名称作为字符串?

instance.__class__.__name__

Do you want the name of the class as a string?

instance.__class__.__name__

回答 2

type()?

>>> class A(object):
...    def whoami(self):
...       print type(self).__name__
...
>>>
>>> class B(A):
...    pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

type() ?

>>> class A(object):
...    def whoami(self):
...       print type(self).__name__
...
>>>
>>> class B(A):
...    pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

回答 3

class A:
  pass

a = A()
str(a.__class__)

上述样本代码(当在交互式解释输入)会产生'__main__.A',而不是'A'其中如果产生__name__属性被调用。通过将结果简单地传递A.__class__str构造函数,即可为您处理解析。但是,如果您想要更明确的内容,也可以使用以下代码。

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

如果您在单独的模块中定义了具有相同名称的类,则此行为可能更可取。

上面提供的示例代码已在Python 2.7.5中进行了测试。

class A:
  pass

a = A()
str(a.__class__)

The sample code above (when input in the interactive interpreter) will produce '__main__.A' as opposed to 'A' which is produced if the __name__ attribute is invoked. By simply passing the result of A.__class__ to the str constructor the parsing is handled for you. However, you could also use the following code if you want something more explicit.

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

This behavior can be preferable if you have classes with the same name defined in separate modules.

The sample code provided above was tested in Python 2.7.5.


回答 4

type(instance).__name__ != instance.__class__.__name  #if class A is defined like
class A():
   ...

type(instance) == instance.__class__                  #if class A is defined like
class A(object):
  ...

例:

>>> class aclass(object):
...   pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>


>>> class bclass():
...   pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>
type(instance).__name__ != instance.__class__.__name  #if class A is defined like
class A():
   ...

type(instance) == instance.__class__                  #if class A is defined like
class A(object):
  ...

Example:

>>> class aclass(object):
...   pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>


>>> class bclass():
...   pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>

回答 5

好问题。

这是一个基于GHZ的简单示例,可能会帮助某人:

>>> class person(object):
        def init(self,name):
            self.name=name
        def info(self)
            print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person

Good question.

Here’s a simple example based on GHZ’s which might help someone:

>>> class person(object):
        def init(self,name):
            self.name=name
        def info(self)
            print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person

回答 6

或者,您可以使用classmethod装饰器:

class A:
    @classmethod
    def get_classname(cls):
        return cls.__name__

    def use_classname(self):
        return self.get_classname()

用法

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'

Alternatively you can use the classmethod decorator:

class A:
    @classmethod
    def get_classname(cls):
        return cls.__name__

    def use_classname(self):
        return self.get_classname()

Usage:

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'

回答 7

除了获取特殊__name__属性外,您可能会发现自己需要给定类/函数的合格名称。这是通过获取类型来完成的__qualname__

在大多数情况下,它们是完全相同的,但是,当处理嵌套类/方法时,它们在输出中会有所不同。例如:

class Spam:
    def meth(self):
        pass
    class Bar:
        pass

>>> s = Spam()
>>> type(s).__name__ 
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__       # type not needed here
'Bar'
>>> type(s).Bar.__qualname__   # type not needed here 
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'

由于自省是您所要追求的,因此始终可能需要考虑这一点。

Apart from grabbing the special __name__ attribute, you might find yourself in need of the qualified name for a given class/function. This is done by grabbing the types __qualname__.

In most cases, these will be exactly the same, but, when dealing with nested classes/methods these differ in the output you get. For example:

class Spam:
    def meth(self):
        pass
    class Bar:
        pass

>>> s = Spam()
>>> type(s).__name__ 
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__       # type not needed here
'Bar'
>>> type(s).Bar.__qualname__   # type not needed here 
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'

Since introspection is what you’re after, this is always you might want to consider.


回答 8

要获取实例类名:

type(instance).__name__

要么

instance.__class__.__name__

两者都一样

To get instance classname:

type(instance).__name__

or

instance.__class__.__name__

both are the same


Python的隐藏功能

问题:Python的隐藏功能

Python编程语言鲜为人知但有用的功能是什么?

  • 尝试将答案限于Python核心。
  • 每个答案一个功能。
  • 给出该功能的示例和简短描述,而不仅仅是指向文档的链接。
  • 使用标题作为第一行标记功能。

答案的快速链接:

What are the lesser-known but useful features of the Python programming language?

  • Try to limit answers to Python core.
  • One feature per answer.
  • Give an example and short description of the feature, not just a link to documentation.
  • Label the feature using a title as the first line.

Quick links to answers:


回答 0

链接比较运算符:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

如果您以为它在做1 < x,它显示为True,然后比较True < 10,它也是True,那么不,那实际上不是什么事情(请参阅最后一个示例。)它实际上是翻译成1 < x and x < 10,和x < 10 and 10 < x * 10 and x*10 < 100,但键入和每个输入较少该术语仅评估一次。

Chaining comparison operators:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

In case you’re thinking it’s doing 1 < x, which comes out as True, and then comparing True < 10, which is also True, then no, that’s really not what happens (see the last example.) It’s really translating into 1 < x and x < 10, and x < 10 and 10 < x * 10 and x*10 < 100, but with less typing and each term is only evaluated once.


回答 1

获取python regex解析树以调试您的regex。

正则表达式是python的一个很棒的功能,但是调试它们可能会很麻烦,而且很容易使正则表达式出错。

幸运的是,python可以通过将未记录的实验性隐藏标记re.DEBUG(实际上是128)传递给,从而输出正则表达式分析树re.compile

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

一旦了解了语法,就可以发现错误。在那里,我们可以看到,我忘了躲避[][/font]

当然,您可以将其与所需的任何标志(例如带注释的正则表达式)结合使用:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)

Get the python regex parse tree to debug your regex.

Regular expressions are a great feature of python, but debugging them can be a pain, and it’s all too easy to get a regex wrong.

Fortunately, python can print the regex parse tree, by passing the undocumented, experimental, hidden flag re.DEBUG (actually, 128) to re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Once you understand the syntax, you can spot your errors. There we can see that I forgot to escape the [] in [/font].

Of course you can combine it with whatever flags you want, like commented regexes:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)

回答 2

枚举

用enumerate包装一个可迭代对象,它将产生该项目及其索引。

例如:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

参考文献:

enumerate

Wrap an iterable with enumerate and it will yield the item along with its index.

For example:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

References:


回答 3

创建生成器对象

如果你写

x=(n for n in foo if bar(n))

您可以找出生成器并将其分配给x。现在,这意味着您可以

for n in x:

这样做的好处是您不需要中间存储,如果需要的话

x = [n for n in foo if bar(n)]

在某些情况下,这可能会导致速度显着提高。

您可以在生成器的末尾附加许多if语句,基本上是复制嵌套的for循环:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)

Creating generators objects

If you write

x=(n for n in foo if bar(n))

you can get out the generator and assign it to x. Now it means you can do

for n in x:

The advantage of this is that you don’t need intermediate storage, which you would need if you did

x = [n for n in foo if bar(n)]

In some cases this can lead to significant speed up.

You can append many if statements to the end of the generator, basically replicating nested for loops:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)

回答 4

iter()可以接受可调用参数

例如:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

iter(callable, until_value)函数反复调用callable并产生其结果,直到until_value返回为止。

iter() can take a callable argument

For instance:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

The iter(callable, until_value) function repeatedly calls callable and yields its result until until_value is returned.


回答 5

注意可变的默认参数

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

相反,您应该使用表示“未给定”的前哨值,并默认将其替换为您想要的可变变量:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

Be careful with mutable default arguments

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Instead, you should use a sentinel value denoting “not given” and replace with the mutable you’d like as default:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

回答 6

将值发送到生成器函数中。例如,具有以下功能:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

您可以:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7

Sending values into generator functions. For example having this function:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

You can:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7

回答 7

如果您不喜欢使用空格来表示作用域,则可以通过发出以下命令来使用C样式的{}:

from __future__ import braces

If you don’t like using whitespace to denote scopes, you can use the C-style {} by issuing:

from __future__ import braces

回答 8

切片运算符中的step参数。例如:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

特殊情况x[::-1]是“ x反转”的有用成语。

>>> a[::-1]
[5,4,3,2,1]

The step argument in slice operators. For example:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

The special case x[::-1] is a useful idiom for ‘x reversed’.

>>> a[::-1]
[5,4,3,2,1]

回答 9

装饰工

装饰器允许将一个函数或方法包装在另一个函数中,该函数或方法可以添加功能,修改参数或结果等。您可以在函数定义上方一行以“ at”符号(@)开头编写装饰器。

示例显示了一个print_args装饰器,该装饰器在调用之前打印装饰后的函数的参数:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo

Decorators

Decorators allow to wrap a function or method in another function that can add functionality, modify arguments or results, etc. You write decorators one line above the function definition, beginning with an “at” sign (@).

Example shows a print_args decorator that prints the decorated function’s arguments before calling it:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo

回答 10

for … else语法(请参阅http://docs.python.org/ref/for.html

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

除非调用break,否则“ else”块通常会在for循环的末尾执行。

上面的代码可以模拟如下:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")

The for…else syntax (see http://docs.python.org/ref/for.html )

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

The “else” block will be normally executed at the end of the for loop, unless the break is called.

The above code could be emulated as follows:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")

回答 11

从2.5开始,字典有一个特殊的方法__missing__用于缺失项的调用:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

collections调用defaultdict中还有一个dict子类,它的功能几乎相同,但是为不存在的项目调用不带参数的函数:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

我建议在将此类字典传递给不希望此类子类的函数之前,将其转换为常规字典。许多代码使用d[a_key]并捕获KeyErrors来检查是否存在某个项目,从而将新项目添加到dict中。

From 2.5 onwards dicts have a special method __missing__ that is invoked for missing items:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

There is also a dict subclass in collections called defaultdict that does pretty much the same but calls a function without arguments for not existing items:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

I recommend converting such dicts to regular dicts before passing them to functions that don’t expect such subclasses. A lot of code uses d[a_key] and catches KeyErrors to check if an item exists which would add a new item to the dict.


回答 12

就地价值交换

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

分配的右侧是创建新元组的表达式。作业的左侧立即将(未引用的)元组解压缩到名称ab

分配后,新的元组将不被引用并标记为垃圾回收,并且值绑定到a并且b已经交换。

Python教程中有关数据结构的部分所述

注意,多重分配实际上只是元组打包和序列拆包的组合。

In-place value swapping

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

The right-hand side of the assignment is an expression that creates a new tuple. The left-hand side of the assignment immediately unpacks that (unreferenced) tuple to the names a and b.

After the assignment, the new tuple is unreferenced and marked for garbage collection, and the values bound to a and b have been swapped.

As noted in the Python tutorial section on data structures,

Note that multiple assignment is really just a combination of tuple packing and sequence unpacking.


回答 13

可读的正则表达式

在Python中,您可以将正则表达式分成多行,命名匹配项并插入注释。

详细语法示例(从Dive into Python):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

命名匹配示例(来自正则表达式HOWTO

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

您还可以冗长地编写一个正则表达式,而不必使用re.VERBOSE多亏了字符串文字连接。

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

Readable regular expressions

In Python you can split a regular expression over multiple lines, name your matches and insert comments.

Example verbose syntax (from Dive into Python):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

Example naming matches (from Regular Expression HOWTO)

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

You can also verbosely write a regex without using re.VERBOSE thanks to string literal concatenation.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

回答 14

函数参数解压缩

您可以使用*和将列表或字典作为函数参数解压缩**

例如:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

由于列表,元组和字典广泛用作容器,因此非常有用的快捷方式。

Function argument unpacking

You can unpack a list or a dictionary as function arguments using * and **.

For example:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Very useful shortcut since lists, tuples and dicts are widely used as containers.


回答 15

当您在代码文件的顶部使用正确的编码声明时,ROT13是源代码的有效编码:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")

ROT13 is a valid encoding for source code, when you use the right coding declaration at the top of the code file:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")

回答 16

以完全动态的方式创建新类型

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

完全一样

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

可能不是最有用的东西,但很高兴知道。

编辑:新类型的固定名称,应NewType与with class语句完全相同。

编辑:调整标题以更准确地描述功能。

Creating new types in a fully dynamic manner

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

which is exactly the same as

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

Probably not the most useful thing, but nice to know.

Edit: Fixed name of new type, should be NewType to be the exact same thing as with class statement.

Edit: Adjusted the title to more accurately describe the feature.


回答 17

上下文管理器和“ with”语句

PEP 343中引入的上下文管理器是一个对象,它充当一组语句的运行时上下文。

由于该功能使用了新的关键字,因此逐步引入了该功能:通过__future__指令在Python 2.5中可用。Python 2.6及更高版本(包括Python 3)默认情况下可用。

我经常使用“ with”语句,因为我认为这是一个非常有用的结构,下面是一个快速演示:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

在幕后发生的事情是,“ with”语句调用了文件对象上的special __enter____exit__method。__exit__如果with语句主体引发了任何异常,则异常详细信息也将传递到该异常,从而允许在那里进行异常处理。

在这种特殊情况下,这为您执行的操作是,它保证在执行超出with套件范围时关闭文件,无论是正常发生还是引发异常。从根本上讲,它是一种抽象通用异常处理代码的方法。

其他常见用例包括使用线程锁定和数据库事务。

Context managers and the “with” Statement

Introduced in PEP 343, a context manager is an object that acts as a run-time context for a suite of statements.

Since the feature makes use of new keywords, it is introduced gradually: it is available in Python 2.5 via the __future__ directive. Python 2.6 and above (including Python 3) has it available by default.

I have used the “with” statement a lot because I think it’s a very useful construct, here is a quick demo:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

What’s happening here behind the scenes, is that the “with” statement calls the special __enter__ and __exit__ methods on the file object. Exception details are also passed to __exit__ if any exception was raised from the with statement body, allowing for exception handling to happen there.

What this does for you in this particular case is that it guarantees that the file is closed when execution falls out of scope of the with suite, regardless if that occurs normally or whether an exception was thrown. It is basically a way of abstracting away common exception-handling code.

Other common use cases for this include locking with threads and database transactions.


回答 18

字典具有get()方法

字典有一个“ get()”方法。如果执行d [‘key’]而键不存在,则会出现异常。如果执行d.get(’key’),则如果’key’不存在,则返回None。您可以添加第二个参数来取回该项目,而不是无,例如:d.get(’key’,0)。

这非常适合诸如加号之类的事情:

sum[value] = sum.get(value, 0) + 1

Dictionaries have a get() method

Dictionaries have a ‘get()’ method. If you do d[‘key’] and key isn’t there, you get an exception. If you do d.get(‘key’), you get back None if ‘key’ isn’t there. You can add a second argument to get that item back instead of None, eg: d.get(‘key’, 0).

It’s great for things like adding up numbers:

sum[value] = sum.get(value, 0) + 1


回答 19

描述符

它们是一大堆Python核心功能背后的魔力。

当您使用点分访问来查找成员(例如xy)时,Python首先在实例字典中查找该成员。如果找不到,它将在类字典中查找。如果它在类字典中找到它,并且该对象实现了描述符协议,而不是仅仅返回它,Python就会执行它。一个描述符是实现任何类__get____set____delete__方法。

这是使用描述符实现自己的(只读)属性版本的方法:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

您将像内置的property()一样使用它:

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

描述符在Python中用于实现属性,绑定方法,静态方法,类方法和插槽等。理解它们可以很容易地弄清为什么以前看起来像Python的“怪癖”的很多东西都是它们的样子。

Raymond Hettinger 的教程很棒,比我做得更好。

Descriptors

They’re the magic behind a whole bunch of core Python features.

When you use dotted access to look up a member (eg, x.y), Python first looks for the member in the instance dictionary. If it’s not found, it looks for it in the class dictionary. If it finds it in the class dictionary, and the object implements the descriptor protocol, instead of just returning it, Python executes it. A descriptor is any class that implements the __get__, __set__, or __delete__ methods.

Here’s how you’d implement your own (read-only) version of property using descriptors:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

and you’d use it just like the built-in property():

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

Descriptors are used in Python to implement properties, bound methods, static methods, class methods and slots, amongst other things. Understanding them makes it easy to see why a lot of things that previously looked like Python ‘quirks’ are the way they are.

Raymond Hettinger has an excellent tutorial that does a much better job of describing them than I do.


回答 20

条件分配

x = 3 if (y == 1) else 2

它确实听起来像:“如果y为1,则将3分配给x,否则将2分配给x”。请注意,不需要括号,但是出于可读性考虑,我喜欢它们。如果您有更复杂的东西,也可以将其链接起来:

x = 3 if (y == 1) else 2 if (y == -1) else 1

尽管在某个时候,它有点太过分了。

请注意,您可以在任何表达式中使用if … else。例如:

(func1 if y == 1 else func2)(arg1, arg2) 

如果y为1,则调用func1,否则调用func2。在这两种情况下,将使用参数arg1和arg2调用相应的函数。

类似地,以下内容也有效:

x = (class1 if y == 1 else class2)(arg1, arg2)

其中class1和class2是两个类。

Conditional Assignment

x = 3 if (y == 1) else 2

It does exactly what it sounds like: “assign 3 to x if y is 1, otherwise assign 2 to x”. Note that the parens are not necessary, but I like them for readability. You can also chain it if you have something more complicated:

x = 3 if (y == 1) else 2 if (y == -1) else 1

Though at a certain point, it goes a little too far.

Note that you can use if … else in any expression. For example:

(func1 if y == 1 else func2)(arg1, arg2) 

Here func1 will be called if y is 1 and func2, otherwise. In both cases the corresponding function will be called with arguments arg1 and arg2.

Analogously, the following is also valid:

x = (class1 if y == 1 else class2)(arg1, arg2)

where class1 and class2 are two classes.


回答 21

Doctest:同时进行文档编制和单元测试。

从Python文档中提取的示例:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()

Doctest: documentation and unit-testing at the same time.

Example extracted from the Python documentation:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()

回答 22

命名格式

%-formatting需要一个字典(也适用于%i /%s等。验证)。

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

并且由于locals()也是一个字典,因此您可以简单地将其作为字典传递,并从本地变量中获取%替换。我认为这是不满意的,但可以简化。

新样式格式

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))

Named formatting

% -formatting takes a dictionary (also applies %i/%s etc. validation).

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

And since locals() is also a dictionary, you can simply pass that as a dict and have % -substitions from your local variables. I think this is frowned upon, but simplifies things..

New Style Formatting

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))

回答 23

为了添加更多的python模块(尤其是第三方模块),大多数人似乎使用PYTHONPATH环境变量,或者在其站点包目录中添加符号链接或目录。另一种方法是使用* .pth文件。这是python官方文档的解释:

“ [修改python搜索路径的最方便的方法是将路径配置文件添加到Python路径上已经存在的目录中,通常是… / site-packages /目录。路径配置文件的扩展名为.pth。 ,并且每行必须包含一个附加到sys.path的路径。(由于新路径附加到sys.path,因此添加目录中的模块不会覆盖标准模块。这意味着您不能使用此机制用于安装标准模块的固定版本。)”

To add more python modules (espcially 3rd party ones), most people seem to use PYTHONPATH environment variables or they add symlinks or directories in their site-packages directories. Another way, is to use *.pth files. Here’s the official python doc’s explanation:

“The most convenient way [to modify python’s search path] is to add a path configuration file to a directory that’s already on Python’s path, usually to the …/site-packages/ directory. Path configuration files have an extension of .pth, and each line must contain a single path that will be appended to sys.path. (Because the new paths are appended to sys.path, modules in the added directories will not override standard modules. This means you can’t use this mechanism for installing fixed versions of standard modules.)”


回答 24

exceptionselse子句:

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try … except语句保护的代码未引发的异常。

参见http://docs.python.org/tut/node10.html

Exception else clause:

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.

See http://docs.python.org/tut/node10.html


回答 25

重新引发异常

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

错误处理程序中不带任何参数的’raise’语句告诉Python重新引发具有完整原始追溯的异常,允许您说“哦,对不起,对不起,我不是要抓住那个,对不起,对不起。 ”

如果您希望打印,存储或摆弄原始回溯,可以通过sys.exc_info()来获取,并像Python一样通过“回溯”模块完成打印。

Re-raising exceptions:

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

The ‘raise’ statement with no arguments inside an error handler tells Python to re-raise the exception with the original traceback intact, allowing you to say “oh, sorry, sorry, I didn’t mean to catch that, sorry, sorry.”

If you wish to print, store or fiddle with the original traceback, you can get it with sys.exc_info(), and printing it like Python would is done with the ‘traceback’ module.


回答 26

主要信息:)

import this
# btw look at this module's source :)

解密

提姆·彼得斯(Tim Peters)撰写的《 Python之禅》

美丽胜于丑陋。
显式胜于隐式。
简单胜于复杂。
复杂胜于复杂。
扁平比嵌套更好。
稀疏胜于密集。
可读性很重要。
特殊情况还不足以打破规则。
尽管实用性胜过纯度。
错误绝不能默默传递。
除非明确地保持沉默。
面对模棱两可的想法,拒绝猜测的诱惑。应该有一种-最好只有一种-显而易见的方法。
尽管除非您是荷兰人,否则一开始这种方式可能并不明显。
现在总比没有好。
虽然从来没有比这更好正确的现在。
如果实现难以解释,那是个坏主意。
如果实现易于解释,则可能是个好主意。
命名空间是一个很棒的主意-让我们做更多这些吧!

Main messages :)

import this
# btw look at this module's source :)

De-cyphered:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess. There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!


回答 27

交互式口译员选项卡完成

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

您还必须设置PYTHONSTARTUP环境变量。

Interactive Interpreter Tab Completion

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

You will also have to set a PYTHONSTARTUP environment variable.


回答 28

嵌套列表推导和生成器表达式:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

这些可以替换大量的嵌套循环代码。

Nested list comprehensions and generator expressions:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

These can replace huge chunks of nested-loop code.


回答 29

set内置运算符重载:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

标准库参考中的更多详细信息:设置类型

Operator overloading for the set builtin:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

More detail from the standard library reference: Set Types


如何检查字符串是否为空?

问题:如何检查字符串是否为空?

Python是否有类似空字符串变量的内容,您可以在其中执行以下操作:

if myString == string.empty:

无论如何,检查空字符串值的最优雅方法是什么?我""每次都很难检查空字符串,因此很难进行编码。

Does Python have something like an empty string variable where you can do:

if myString == string.empty:

Regardless, what’s the most elegant way to check for empty string values? I find hard coding "" every time for checking an empty string not as good.


回答 0

空字符串是“ falsy”,这意味着它们在布尔上下文中被认为是错误的,因此您可以执行以下操作:

if not myString:

如果您知道变量是字符串,则这是首选方法。如果您的变量也可以是其他类型,则应使用myString == ""。有关在布尔上下文中为假的其他值,请参见“ 真值测试 ”文档。

Empty strings are “falsy” which means they are considered false in a Boolean context, so you can just do this:

if not myString:

This is the preferred way if you know that your variable is a string. If your variable could also be some other type then you should use myString == "". See the documentation on Truth Value Testing for other values that are false in Boolean contexts.


回答 1

PEP 8“编程建议”部分中

对于序列(字符串,列表,元组),请使用以下事实:空序列为假。

因此,您应该使用:

if not some_string:

要么:

if some_string:

只是为了澄清,序列评估FalseTrue在布尔上下文如果它们是空的或不是。他们不等于FalseTrue

From PEP 8, in the “Programming Recommendations” section:

For sequences, (strings, lists, tuples), use the fact that empty sequences are false.

So you should use:

if not some_string:

or:

if some_string:

Just to clarify, sequences are evaluated to False or True in a Boolean context if they are empty or not. They are not equal to False or True.


回答 2

最优雅的方法可能是简单地检查其真实性或虚假性,例如:

if not my_string:

但是,您可能要删除空格,因为:

 >>> bool("")
 False
 >>> bool("   ")
 True
 >>> bool("   ".strip())
 False

但是,您可能应该对此更加明确,除非您确定该字符串已经通过某种验证并且可以通过这种方式进行测试。

The most elegant way would probably be to simply check if its true or falsy, e.g.:

if not my_string:

However, you may want to strip white space because:

 >>> bool("")
 False
 >>> bool("   ")
 True
 >>> bool("   ".strip())
 False

You should probably be a bit more explicit in this however, unless you know for sure that this string has passed some kind of validation and is a string that can be tested this way.


回答 3

我会在剥离之前测试无。另外,我会使用一个空字符串为False(或Falsy)的事实。这种方法类似于Apache的StringUtils.isBlank番石榴的Strings.isNullOrEmpty

这就是我用来测试字符串是否为None或Empty或Blank的内容:

def isBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return False
    #myString is None OR myString is empty or blank
    return True

并且,与测试字符串是否不是None或NOR空或NOR空白完全相反:

def isNotBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return True
    #myString is None OR myString is empty or blank
    return False

上面代码的更简洁形式:

def isBlank (myString):
    return not (myString and myString.strip())

def isNotBlank (myString):
    return bool(myString and myString.strip())

I would test noneness before stripping. Also, I would use the fact that empty strings are False (or Falsy). This approach is similar to Apache’s StringUtils.isBlank or Guava’s Strings.isNullOrEmpty

This is what I would use to test if a string is either None OR Empty OR Blank:

def isBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return False
    #myString is None OR myString is empty or blank
    return True

And, the exact opposite to test if a string is not None NOR Empty NOR Blank:

def isNotBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return True
    #myString is None OR myString is empty or blank
    return False

More concise forms of the above code:

def isBlank (myString):
    return not (myString and myString.strip())

def isNotBlank (myString):
    return bool(myString and myString.strip())

回答 4

我曾经写过类似Bartek的答案和javascript启发的东西:

def is_not_blank(s):
    return bool(s and s.strip())

测试:

print is_not_blank("")    # False
print is_not_blank("   ") # False
print is_not_blank("ok")  # True
print is_not_blank(None)  # False

I once wrote something similar to Bartek’s answer and javascript inspired:

def is_not_blank(s):
    return bool(s and s.strip())

Test:

print is_not_blank("")    # False
print is_not_blank("   ") # False
print is_not_blank("ok")  # True
print is_not_blank(None)  # False

回答 5

唯一真正可靠的方法是:

if "".__eq__(myString):

所有其他解决方案都可能存在问题,并且可能导致检查失败。

len(myString)==0如果myString是继承自str并覆盖的类的对象,则会失败__len__()方法方法方法。

同样myString == ""myString.__eq__("")如果myString覆盖__eq__()__ne__()

由于某种原因,"" == myString如果myString覆盖也将被愚弄__eq__()

myString is """" is myString等价。如果它们myString实际上不是字符串而是字符串的子类,则它们都将失败(都将返回False)。另外,由于它们是身份检查,所以它们起作用的唯一原因是因为Python使用了String Pooling(也称为String Internment),该字符串池在被插入的情况下使用相同的字符串实例(请参见此处:为什么使用’=来比较字符串=’或’是否’有时会产生不同的结果?)。和""从一开始就在CPython中进行实习

身份检查的最大问题是,据我所知,String Internment不规范要插入哪些字符串。从理论上讲""没有必要进行实习,而依赖于实现。

真正不能被愚弄的唯一方法是开头提到的方法:"".__eq__(myString)。由于此__eq__()方法明确调用了空字符串的方法,因此不能通过覆盖myString中的任何方法来欺骗它,并且可以与的子类牢固地结合使用str

如果对象覆盖了它的__bool__()方法,那么依靠字符串的虚假性也可能无法工作。

这不仅是理论上的工作,而且实际上可能与实际用法有关,因为我之前看到过框架和库的子类化str,并且使用myString is ""那里可能会返回错误的输出。

而且,is通常使用字符串比较字符串是一个很糟糕的陷阱,因为它有时会正确运行,而在其他时候则无法正常工作,因为字符串池遵循非常奇怪的规则。

也就是说,在大多数情况下,所有提到的解决方案都可以正常工作。这是大多数学术工作。

The only really solid way of doing this is the following:

if "".__eq__(myString):

All other solutions have possible problems and edge cases where the check can fail.

len(myString)==0 can fail if myString is an object of a class that inherits from str and overrides the __len__() method.

Similarly myString == "" and myString.__eq__("") can fail if myString overrides __eq__() and __ne__().

For some reason "" == myString also gets fooled if myString overrides __eq__().

myString is "" and "" is myString are equivalent. They will both fail if myString is not actually a string but a subclass of string (both will return False). Also, since they are identity checks, the only reason why they work is because Python uses String Pooling (also called String Internment) which uses the same instance of a string if it is interned (see here: Why does comparing strings using either ‘==’ or ‘is’ sometimes produce a different result?). And "" is interned from the start in CPython

The big problem with the identity check is that String Internment is (as far as I could find) that it is not standardised which strings are interned. That means, theoretically "" is not necessary interned and that is implementation dependant.

The only way of doing this that really cannot be fooled is the one mentioned in the beginning: "".__eq__(myString). Since this explicitly calls the __eq__() method of the empty string it cannot be fooled by overriding any methods in myString and solidly works with subclasses of str.

Also relying on the falsyness of a string might not work if the object overrides it’s __bool__() method.

This is not only theoretical work but might actually be relevant in real usage since I have seen frameworks and libraries subclassing str before and using myString is "" might return a wrong output there.

Also, comparing strings using is in general is a pretty evil trap since it will work correctly sometimes, but not at other times, since string pooling follows pretty strange rules.

That said, in most cases all of the mentioned solutions will work correctly. This is post is mostly academic work.


回答 6

测试空字符串或空字符串(较短的方法):

if myString.strip():
    print("it's not an empty or blank string")
else:
    print("it's an empty or blank string")

Test empty or blank string (shorter way):

if myString.strip():
    print("it's not an empty or blank string")
else:
    print("it's an empty or blank string")

回答 7

如果要区分空字符串和空字符串,建议使用if len(string),否则,建议仅使用if string其他人所说的方法。关于充满空格的字符串的警告仍然适用,因此请不要忘记strip

If you want to differentiate between empty and null strings, I would suggest using if len(string), otherwise, I’d suggest using simply if string as others have said. The caveat about strings full of whitespace still applies though, so don’t forget to strip.


回答 8

if stringname:false字符串为空时给出a 。我想这不可能比这更简单。

if stringname: gives a false when the string is empty. I guess it can’t be simpler than this.


回答 9

a = ''
b = '   '
a.isspace() -> False
b.isspace() -> True
a = ''
b = '   '
a.isspace() -> False
b.isspace() -> True

回答 10

每次检查空字符串时,我都发现用硬编码“”不好。

干净的代码方法

这样做:foo == ""是非常不好的做法。""是一个神奇的价值。您永远都不应检查魔术值(通常称为魔术数)

您应该做的是与描述性变量名称进行比较。

描述性变量名称

可能会认为“ empty_string”是一种描述性变量名。不是

在去做之前,请empty_string = ""以为您有一个很好的变量名可以比较。这不是“描述性变量名称”的含义。

一个好的描述性变量名称基于其上下文。你要想想空字符串什么

  • 它从何而来。
  • 为什么在那儿。
  • 为什么您需要检查它。

简单表单字段示例

您正在构建一个表单,用户可以在其中输入值。您要检查用户是否写了什么。

一个好的变量名可能是 not_filled_in

这使得代码非常可读

if formfields.name == not_filled_in:
    raise ValueError("We need your name")

全面的CSV解析示例

您正在解析CSV文件,并希望将空字符串解析为 None

(由于CSV完全基于文本,因此无法表示 None使用预定义的关键字)

一个好的变量名可能是 CSV_NONE

如果您有一个新的CSV文件,该文件None用另一个字符串表示,则使代码易于更改和调整。""

if csvfield == CSV_NONE:
    csvfield = None

毫无疑问,这段代码是否正确。很明显,它做了应该做的事情。

比较一下

if csvfield == EMPTY_STRING:
    csvfield = None

这里的第一个问题是,为什么空字符串应该得到特殊对待?

这将告诉以后的编码人员,应该始终将空字符串视为None

这是因为它将业务逻辑(应为CSV值None)与代码实现(我们实际比较的是什么)混合在一起

两者之间需要分开关注

I find hardcoding(sic) “” every time for checking an empty string not as good.

Clean code approach

Doing this: foo == "" is very bad practice. "" is a magical value. You should never check against magical values (more commonly known as magical numbers)

What you should do is compare to a descriptive variable name.

Descriptive variable names

One may think that “empty_string” is a descriptive variable name. It isn’t.

Before you go and do empty_string = "" and think you have a great variable name to compare to. This is not what “descriptive variable name” means.

A good descriptive variable name is based on its context. You have to think about what the empty string is.

  • Where does it come from.
  • Why is it there.
  • Why do you need to check for it.

Simple form field example

You are building a form where a user can enter values. You want to check if the user wrote something or not.

A good variable name may be not_filled_in

This makes the code very readable

if formfields.name == not_filled_in:
    raise ValueError("We need your name")

Thorough CSV parsing example

You are parsing CSV files and want the empty string to be parsed as None

(Since CSV is entirely text based, it cannot represent None without using predefined keywords)

A good variable name may be CSV_NONE

This makes the code easy to change and adapt if you have a new CSV file that represents None with another string than ""

if csvfield == CSV_NONE:
    csvfield = None

There are no questions about if this piece of code is correct. It is pretty clear that it does what it should do.

Compare this to

if csvfield == EMPTY_STRING:
    csvfield = None

The first question here is, Why does the empty string deserve special treatment?

This would tell future coders that an empty string should always be considered as None.

This is because it mixes business logic (What CSV value should be None) with code implementation (What are we actually comparing to)

There needs to be a separation of concern between the two.


回答 11

这个怎么样?也许它不是“最优雅的”,但是看起来很完整和清晰:

if (s is None) or (str(s).strip()==""): // STRING s IS "EMPTY"...

How about this? Perhaps it’s not “the most elegant”, but it seems pretty complete and clear:

if (s is None) or (str(s).strip()==""): // STRING s IS "EMPTY"...

回答 12

响应@ 1290。抱歉,无法格式化注释中的块。该None值在Python中不是空字符串,也不是(空格)。安德鲁·克拉克(Andrew Clark)的答案是正确的:if not myString。@rouble的答案是特定于应用程序的,不能回答OP的问题。如果您对“空白”字符串采用特殊定义,则会遇到麻烦。特别是,标准行为是str(None)产生'None'一个非空字符串。

但是,如果必须将Noneand(空格)视为“空白”字符串,这是一种更好的方法:

class weirdstr(str):
    def __new__(cls, content):
        return str.__new__(cls, content if content is not None else '')
    def __nonzero__(self):
        return bool(self.strip())

例子:

>>> normal = weirdstr('word')
>>> print normal, bool(normal)
word True

>>> spaces = weirdstr('   ')
>>> print spaces, bool(spaces)
    False

>>> blank = weirdstr('')
>>> print blank, bool(blank)
 False

>>> none = weirdstr(None)
>>> print none, bool(none)
 False

>>> if not spaces:
...     print 'This is a so-called blank string'
... 
This is a so-called blank string

满足@rouble要求,同时不破坏bool字符串的预期行为。

Responding to @1290. Sorry, no way to format blocks in comments. The None value is not an empty string in Python, and neither is (spaces). The answer from Andrew Clark is the correct one: if not myString. The answer from @rouble is application-specific and does not answer the OP’s question. You will get in trouble if you adopt a peculiar definition of what is a “blank” string. In particular, the standard behavior is that str(None) produces 'None', a non-blank string.

However if you must treat None and (spaces) as “blank” strings, here is a better way:

class weirdstr(str):
    def __new__(cls, content):
        return str.__new__(cls, content if content is not None else '')
    def __nonzero__(self):
        return bool(self.strip())

Examples:

>>> normal = weirdstr('word')
>>> print normal, bool(normal)
word True

>>> spaces = weirdstr('   ')
>>> print spaces, bool(spaces)
    False

>>> blank = weirdstr('')
>>> print blank, bool(blank)
 False

>>> none = weirdstr(None)
>>> print none, bool(none)
 False

>>> if not spaces:
...     print 'This is a so-called blank string'
... 
This is a so-called blank string

Meets the @rouble requirements while not breaking the expected bool behavior of strings.


回答 13

我觉得这很优雅,因为它可以确保它是一个字符串并检查其长度:

def empty(mystring):
    assert isinstance(mystring, str)
    if len(mystring) == 0:
        return True
    else:
        return False

I find this elegant as it makes sure it is a string and checks its length:

def empty(mystring):
    assert isinstance(mystring, str)
    if len(mystring) == 0:
        return True
    else:
        return False

回答 14

另一个简单的方法可能是定义一个简单的函数:

def isStringEmpty(inputString):
    if len(inputString) == 0:
        return True
    else:
        return False

Another easy way could be to define a simple function:

def isStringEmpty(inputString):
    if len(inputString) == 0:
        return True
    else:
        return False

回答 15

not str(myString)

对于空字符串,此表达式为True。非空字符串,None和非字符串对象都将产生False,但需要注意的是,对象可能会覆盖__str__以通过返回虚假值来阻止此逻辑。

not str(myString)

This expression is True for strings that are empty. Non-empty strings, None and non-string objects will all produce False, with the caveat that objects may override __str__ to thwart this logic by returning a falsy value.


回答 16

您可能会看一下在Python中分配空值或字符串

这是关于比较空字符串。因此not,您可以测试您的字符串是否等于带有""空字符串的空字符串,而不是使用来测试是否为空。

You may have a look at this Assigning empty value or string in Python

This is about comparing strings that are empty. So instead of testing for emptiness with not, you may test is your string is equal to empty string with "" the empty string…


回答 17

对于那些期望像Apache StringUtils.isBlank或Guava Strings.isNullOrEmpty这样的行为的用户:

if mystring and mystring.strip():
    print "not blank string"
else:
    print "blank string"

for those who expect a behaviour like the apache StringUtils.isBlank or Guava Strings.isNullOrEmpty :

if mystring and mystring.strip():
    print "not blank string"
else:
    print "blank string"

回答 18

当您逐行读取文件并想要确定哪一行为空时,请确保您将使用.strip(),因为“空”行中有换行符:

lines = open("my_file.log", "r").readlines()

for line in lines:
    if not line.strip():
        continue

    # your code for non-empty lines

When you are reading file by lines and want to determine, which line is empty, make sure you will use .strip(), because there is new line character in “empty” line:

lines = open("my_file.log", "r").readlines()

for line in lines:
    if not line.strip():
        continue

    # your code for non-empty lines

回答 19

str = ""
if not str:
   print "Empty String"
if(len(str)==0):
   print "Empty String"
str = ""
if not str:
   print "Empty String"
if(len(str)==0):
   print "Empty String"

回答 20

如果你只是用

not var1 

不可能将一个布尔变量False与一个空字符串区别开''

var1 = ''
not var1
> True

var1 = False
not var1
> True

但是,如果您在脚本中添加简单条件,则会有所不同:

var1  = False
not var1 and var1 != ''
> True

var1 = ''
not var1 and var1 != ''
> False

If you just use

not var1 

it is not possible to difference a variable which is boolean False from an empty string '':

var1 = ''
not var1
> True

var1 = False
not var1
> True

However, if you add a simple condition to your script, the difference is made:

var1  = False
not var1 and var1 != ''
> True

var1 = ''
not var1 and var1 != ''
> False

回答 21

如果这对某人有用,这是我构建的一种快速功能,可以用列表列表中的N / A替换空白字符串(python 2)。

y = [["1","2",""],["1","4",""]]

def replace_blank_strings_in_lists_of_lists(list_of_lists):
    new_list = []
    for one_list in list_of_lists:
        new_one_list = []
        for element in one_list:
            if element:
                new_one_list.append(element)
            else:
                new_one_list.append("N/A")
        new_list.append(new_one_list)
    return new_list


x= replace_blank_strings_in_lists_of_lists(y)
print x

这对于将列表列表发布到不接受某些字段空白的mysql数据库(在模式中标记为NN的字段,在我的情况下,这是由于复合主键引起的)非常有用。

In case this is useful to someone, here is a quick function i built out to replace blank strings with N/A’s in lists of lists (python 2).

y = [["1","2",""],["1","4",""]]

def replace_blank_strings_in_lists_of_lists(list_of_lists):
    new_list = []
    for one_list in list_of_lists:
        new_one_list = []
        for element in one_list:
            if element:
                new_one_list.append(element)
            else:
                new_one_list.append("N/A")
        new_list.append(new_one_list)
    return new_list


x= replace_blank_strings_in_lists_of_lists(y)
print x

This is useful for posting lists of lists to a mysql database that does not accept blanks for certain fields (fields marked as NN in schema. in my case, this was due to a composite primary key).


回答 22

我对”,’,’\ n’等字符串进行了一些实验。当且仅当变量foo是具有至少一个非空白字符的字符串时,我希望isNotWhitespace为True。我正在使用Python 3.6。我最终得到的是:

isWhitespace = str is type(foo) and not foo.strip()
isNotWhitespace = str is type(foo) and not not foo.strip()

如果需要,可以将其包装在方法定义中。

I did some experimentation with strings like ”, ‘ ‘, ‘\n’, etc. I want isNotWhitespace to be True if and only if the variable foo is a string with at least one non-whitespace character. I’m using Python 3.6. Here’s what I ended up with:

isWhitespace = str is type(foo) and not foo.strip()
isNotWhitespace = str is type(foo) and not not foo.strip()

Wrap this in a method definition if desired.


回答 23

如prmatta上面所述,但有误。

def isNoneOrEmptyOrBlankString (myString):
    if myString:
        if not myString.strip():
            return True
        else:
            return False
    return False

As prmatta posted above, but with mistake.

def isNoneOrEmptyOrBlankString (myString):
    if myString:
        if not myString.strip():
            return True
        else:
            return False
    return False