标签归档:python-2.x

如何检查变量是否为具有python 2和3兼容性的字符串

问题:如何检查变量是否为具有python 2和3兼容性的字符串

我知道我可以isinstance(x, str)在python-3.x中使用:但我还需要检查python-2.x中是否还有字符串。会isinstance(x, str)按预期在python-2.x的?还是我需要检查版本并使用isinstance(x, basestr)

具体来说,在python-2.x中:

>>>isinstance(u"test", str)
False

和python-3.x没有 u"foo"

I’m aware that I can use: isinstance(x, str) in python-3.x but I need to check if something is a string in python-2.x as well. Will isinstance(x, str) work as expected in python-2.x? Or will I need to check the version and use isinstance(x, basestr)?

Specifically, in python-2.x:

>>>isinstance(u"test", str)
False

and python-3.x does not have u"foo"


回答 0

如果要编写兼容2.x和3.x的代码,则可能要使用六个

from six import string_types
isinstance(s, string_types)

If you’re writing 2.x-and-3.x-compatible code, you’ll probably want to use six:

from six import string_types
isinstance(s, string_types)

回答 1

我发现不依赖六个软件包的最简洁的方法是:

try:
  basestring
except NameError:
  basestring = str

然后,假设您以最通用的方式检查了Python 2中的字符串,

isinstance(s, basestring)

现在也将适用于Python 3+。

The most terse approach I’ve found without relying on packages like six, is:

try:
  basestring
except NameError:
  basestring = str

then, assuming you’ve been checking for strings in Python 2 in the most generic manner,

isinstance(s, basestring)

will now also work for Python 3+.


回答 2

那在所有情况下都可行吗?

isinstance(x, ("".__class__, u"".__class__))

What about this, works in all cases?

isinstance(x, ("".__class__, u"".__class__))

回答 3

这是@Lev Levitsky的答案,重写了一下。

try:
    isinstance("", basestring)
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

try/ except测试只进行一次,然后定义总是工作,并尽可能快的功能。

编辑:实际上,我们甚至不需要调用isinstance();我们只需要评估一下basestring,看看是否得到NameError

try:
    basestring  # attempt to evaluate basestring
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

我认为,调用会更容易isinstance()

This is @Lev Levitsky’s answer, re-written a bit.

try:
    isinstance("", basestring)
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

The try/except test is done once, and then defines a function that always works and is as fast as possible.

EDIT: Actually, we don’t even need to call isinstance(); we just need to evaluate basestring and see if we get a NameError:

try:
    basestring  # attempt to evaluate basestring
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

I think it is easier to follow with the call to isinstance(), though.


回答 4

future添加了(兼容 Python 2)兼容名称,因此您可以继续编写Python 3。您可以简单地执行以下操作:

from builtins import str
isinstance(x, str) 

要安装它,只需执行pip install future

作为一个警告,它仅支持python>=2.6>=3.3但它是更现代的比six,这是唯一的建议,如果使用python 2.5

The future library adds (to Python 2) compatible names, so you can continue writing Python 3. You can simple do the following:

from builtins import str
isinstance(x, str) 

To install it, just execute pip install future.

As a caveat, it only support python>=2.6,>=3.3, but it is more modern than six, which is only recommended if using python 2.5


回答 5

也许使用类似的解决方法

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

Maybe use a workaround like

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

回答 6

您可以通过调用来获取对象的类object.__class__,以便检查object是否为默认字符串类型:

    isinstance(object,"".__class__)

而且您可以将以下内容放在代码的顶部,以便用引号括起来的字符串在python 2中的unicode中:

    from __future__ import unicode_literals

You can get the class of an object by calling object.__class__, so in order to check if object is the default string type:

    isinstance(object,"".__class__)

And You can place the following in the top of Your code so that strings enclosed by quotes are in unicode in python 2:

    from __future__ import unicode_literals

回答 7

您可以在代码的开头尝试此操作:

from __future__ import print_function
import sys
if sys.version[0] == "2":
    py3 = False
else:
    py3 = True
if py3: 
    basstring = str
else:
    basstring = basestring

然后在代码中:

anystring = "test"
# anystring = 1
if isinstance(anystring, basstring):
    print("This is a string")
else:
    print("No string")

You can try this at the beginning of your code:

from __future__ import print_function
import sys
if sys.version[0] == "2":
    py3 = False
else:
    py3 = True
if py3: 
    basstring = str
else:
    basstring = basestring

and later in the code:

anystring = "test"
# anystring = 1
if isinstance(anystring, basstring):
    print("This is a string")
else:
    print("No string")

回答 8

小心!在Python 2,str并且bytes基本上是相同的。如果您试图区分两者,则可能会导致错误。

>>> size = 5    
>>> byte_arr = bytes(size)
>>> isinstance(byte_arr, bytes)
True
>>> isinstance(byte_arr, str)
True

Be careful! In python 2, str and bytes are essentially the same. This can cause a bug if you are trying to distinguish between the two.

>>> size = 5    
>>> byte_arr = bytes(size)
>>> isinstance(byte_arr, bytes)
True
>>> isinstance(byte_arr, str)
True

回答 9

类型(字符串)== str

如果它是一个字符串,则返回true;否则,则返回false

type(string) == str

returns true if its a string, and false if not


对python 2.7的支持终止了吗?

问题:对python 2.7的支持终止了吗?

当不再支持python 2.7而不再支持python 2.7时,是否存在已知的日期/时间框架?

Is there a known date/timeframe when python 2.7 will not be supported any more in favor of python 3?


回答 0

自2014年4月13日起,来自http://hg.python.org/peps/rev/76d43e52d978(PEP 373,Python 2.7发布时间表):

Python 2.7的终止生命日期(停产日期,终止日期)已移至未来五年,即2020年。此决定旨在阐明Python 2.7的状态,并减轻那些尚无法迁移到Python 3的用户的后顾之忧。另请参阅PEP 466

As of 13 Apr 2014, from http://hg.python.org/peps/rev/76d43e52d978 (PEP 373, Python 2.7 Release Schedule):

The End Of Life date (EOL, sunset date) for Python 2.7 has been moved five years into the future, to 2020. This decision was made to clarify the status of Python 2.7 and relieve worries for those users who cannot yet migrate to Python 3. See also PEP 466.


回答 1

2010年5月,神的话语为Python 2.7 PATCHLEVEL版本将可能至少6年内作出

因此,也许是2016年,也许是以后。

编辑:推回2020年。请参阅PEP 373的修订版,并在其他答案中链接。

In May 2010, Word of God was that patchlevel releases for Python 2.7 will probably be made for at least 6 years.

So, maybe 2016, probably later.

Edit: Pushed back to 2020. See the revision to PEP 373, linked to in other answers.


回答 2

最近,该日期已更新为2020年1月1日。

参见https://pythonclock.org/

Recently, that date has been updated to January 1, 2020.

see https://pythonclock.org/


回答 3

您应该仔细阅读以下内容(参考:https : //news.ycombinator.com/item ? id =7582300):

这里没有来自python-dev列表的人有很多评论,他们并不真正理解这种差异的实际含义。核心开发人员无需维持2015年后的2.7,并且大多数人不会参与其中。那部分没有改变。发生的事情是Red Hat准备削减RHEL 7发行版,AFAIK取决于您为他们支付13年支持的费用。因此,他们将需要弄清楚如何至少在2027年之前自己获得2.7的支持。RH完全有权利分叉Python,并为自己和客户保留维护补丁(Python不是copyleft)。但,他们是好人,因此,如果仍有Python项目愿意接受这些更改,也许他们愿意至少暂时进行更改。再次,这是我基于ML讨论的推测,而不是RH实​​际上说过的。可以比喻Rails LTS,它是patio11参与[0]的Rails 2.x的商业分支。不可避免地会有人介入以支持2.7,所以让我们看看如何避免出现这样的情况,即保持2.7唯一运行的唯一方法是订阅RHEL。同时,有一些大公司在Windows上广泛使用2.7(例如Enthought,Anaconda),并且认为可以找到某个人偶尔制作Windows安装程序,前提是假定Python.org仍将托管下载。因此,实际上发生的事情不是很令人兴奋。核心提交者所做的工作与将项目按原计划进行一样没有什么不同。发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等 发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等 发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等

you should read this carefully (ref : https://news.ycombinator.com/item?id=7582300 ):

There are a lot of comments here from people who aren’t on the python-dev list and don’t really understand what this diff actually means. The core developers are not required to maintain 2.7 post-2015, and most of them won’t be involved in it. That part hasn’t changed. What is happening is that Red Hat is preparing to cut a RHEL 7 release, which AFAIK depending on how much you pay them they support for 13 years. So they will need to figure out how to support 2.7 themselves at least through 2027. Here is where I am reading between the lines. RH are well within their right to fork Python and keep their maintenance patches to themselves and their customers (Python’s not copyleft). But, they are nice guys and so maybe they are willing to upstream their changes at least for awhile if there is still a Python project willing to accept them. Again, this is my speculation based on the ML discussion, not what RH has actually said they will do. An analogy can be made to Rails LTS, a commercial fork of Rails 2.x that patio11 was involved in [0]. Inevitably somebody is going to step in to support 2.7, and so let’s see what we can do to avoid a situation where the only way to keep running 2.7 is to subscribe to RHEL. Meanwhile, there are some large companies that use 2.7 extensively on Windows (e.g. Enthought, Anaconda) and the thinking goes that somebody can probably be found to produce a Windows installer once in awhile, assuming that Python.org will still host a download. So really what is happening here is not very exciting. The core committers aren’t doing anything different than leaving the project as originally planned. What is happening is that they will leave the lights on in the source control repository and on the FTP server, so as to capture the free labor from people at large companies who have an interest in continuing to support 2.7. The alternative is that RH and other vendors create proprietary and expensive forks of Python 2.7. That may end up happening anyway, but it will take longer for your employer to notice you should stop contributing your patches back if binaries still appear on python.org and you don’t have to ask IT to set up SCM and a bug tracker, etc.


回答 4

本文说:“当2.7发布时,2.x系列将进入五年的仅漏洞修复模式。”

因此,据我所知,Python 2.7是最后一个添加2.x功能的版本,尽管发现的错误将被修复(一段时间),但新功能仅适用于3.x版本。

This article says: “When 2.7 is released, the 2.x line will move into five years of a bug fix-only mode.”

So, as far as I see, Python 2.7 was the last 2.x feature-adding release, and though found bugs are going to be fixed (for some time), new features only go to 3.x releases.


回答 5

到2020年EOS 倒计时还不错。

There is also a pretty ominous countdown clock to the EOS at 2020.


回答 6

PEP 373(Python 2.7发布时间表)是您要求的那种信息的正式来源。

当前显示“计划的未来发布日期:”

  • 2014年5月2.7.7
  • 2.7.8 2014年11月
  • 2015年5月2.7.9
  • 在此日期之后,根据需要发布

另外,它说:“ Python 2.7的生命终止日期(停产日期,日落日期)已经移到了五年后的2020年。”

根据http://hg.python.org/peps/rev/76d43e52d978在2014年4月编辑

PEP 373 (Python 2.7 Release Schedule) is the official source for the kind of information you asked for.

It currently says “Planned future release dates:”

  • 2.7.7 May 2014
  • 2.7.8 November 2014
  • 2.7.9 May 2015
  • beyond this date, releases as needed

Also, it says “The End Of Life date (EOL, sunset date) for Python 2.7 has been moved five years into the future, to 2020.”

Edited in April 2014, according to http://hg.python.org/peps/rev/76d43e52d978


回答 7

《 Python开发人员指南》列出了从2.6版到当前版本的“ Python分支的状态 ”,包括其当前支持状态以及生命周期终止日期。

当前受支持(错误+安全修复):

  • Python 3.8(当前的master / develop分支)
  • Python 3.7
  • Python 3.6
  • Python 2.7(直到2020-01-01)

仅安全修复程序:

  • Python 3.5
  • Python 3.4

The Python Developer’s Guide lists the “Status of Python branches” from version 2.6 up to the current version, including their current support status with End-of-life dates.

Currently supported (bug + security fixes):

  • Python 3.8 (current master/development branch)
  • Python 3.7
  • Python 3.6
  • Python 2.7 (until 2020-01-01)

Security fixes only:

  • Python 3.5
  • Python 3.4

回答 8

Python 2.7将会永远存在。有太多使用它的旧代码,没有人愿意重写。已经有一个名为Tauthon的分支,但是如果这个毫无意义的截止日期成为现实,我们可能还会看到其他人。

Python 2.7 wil be around forever. There is too much old code that uses it that no one wants to rewrite. There is already a fork called Tauthon, but we may see others if this pointless deadline gets real.


Python部门

问题:Python部门

我试图将一组从-100到0的数字归一化到10-100的范围,并且遇到了问题,只是注意到即使根本没有任何变量,这也无法评估我期望的方式:

>>> (20-10) / (100-10)
0

浮动划分也不起作用:

>>> float((20-10) / (100-10))
0.0

如果除法的任一侧都转换为浮点数,它将起作用:

>>> (20-10) / float((100-10))
0.1111111111111111

第一个示例中的每一边都被评估为一个int,这意味着最终答案将被强制转换为int。由于0.111小于.5,因此将其舍入为0。在我看来,这不是透明的,但我想是这样的。

有什么解释?

I was trying to normalize a set of numbers from -100 to 0 to a range of 10-100 and was having problems only to notice that even with no variables at all, this does not evaluate the way I would expect it to:

>>> (20-10) / (100-10)
0

Float division doesn’t work either:

>>> float((20-10) / (100-10))
0.0

If either side of the division is cast to a float it will work:

>>> (20-10) / float((100-10))
0.1111111111111111

Each side in the first example is evaluating as an int which means the final answer will be cast to an int. Since 0.111 is less than .5, it rounds to 0. It is not transparent in my opinion, but I guess that’s the way it is.

What is the explanation?


回答 0

您使用的是Python 2.x,其中整数除法将被截断而不是变成浮点数。

>>> 1 / 2
0

您应该将其中一个设为float

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

from __future__ import division,强制/采用总是返回float的Python 3.x行为。

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111

You’re using Python 2.x, where integer divisions will truncate instead of becoming a floating point number.

>>> 1 / 2
0

You should make one of them a float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

or from __future__ import division, which the forces / to adopt Python 3.x’s behavior that always returns a float.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111

回答 1

将Integers放入其中,因此Python给了您一个整数

>>> 10 / 90
0

如果此后将其强制转换为浮点数,则四舍五入将已经完成,换句话说,0整数将始终变为0浮点数。

如果您在除法的任一侧使用浮点数,那么Python将为您提供您所期望的答案。

>>> 10 / 90.0
0.1111111111111111

因此,在您的情况下:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111

You’re putting Integers in so Python is giving you an integer back:

>>> 10 / 90
0

If if you cast this to a float afterwards the rounding will have already been done, in other words, 0 integer will always become 0 float.

If you use floats on either side of the division then Python will give you the answer you expect.

>>> 10 / 90.0
0.1111111111111111

So in your case:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111

回答 2

在进行除法之前,需要将其更改为浮点数。那是:

float(20 - 10) / (100 - 10)

You need to change it to a float BEFORE you do the division. That is:

float(20 - 10) / (100 - 10)

回答 3

在Python 2.7中,/如果输入为整数,则运算符为整数除法:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

在Python 3.3中,/即使输入是整数,运算符也是浮点除法。

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

对于Python 3中的整数除法,我们将使用//运算符。

//运算符在Python 2.7和Python 3.3中都是整数除法运算符。

在Python 2.7和Python 3.3中:

>>>20//15
1

现在,看比较

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

对于上述程序,输出在Python 2.7中为False,在Python 3.3中为True。

在Python 2.7中a = 1.75和b = 1。

在Python 3.3中,a = 1.75和b = 1.75,仅因为/是一个浮点除法。

In Python 2.7, the / operator is an integer division if inputs are integers:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

In Python 3.3, the / operator is a float division even if the inputs are integer.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

For integer division in Python 3, we will use the // operator.

The // operator is an integer division operator in both Python 2.7 and Python 3.3.

In Python 2.7 and Python 3.3:

>>>20//15
1

Now, see the comparison

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

For the above program, the output will be False in Python 2.7 and True in Python 3.3.

In Python 2.7 a = 1.75 and b = 1.

In Python 3.3 a = 1.75 and b = 1.75, just because / is a float division.


回答 4

它与您使用的python版本有关。基本上,它采用C行为:如果将两个整数相除,结果将四舍五入为一个整数。还请记住,Python从左到右执行操作,这在您键入时发挥作用。

示例:由于这是我进行算术运算时总是会浮现的一个问题(我应该转换为浮点数和哪个数字),因此提供了一个来自该方面的示例:

>>> a = 1/2/3/4/5/4/3
>>> a
0

当我们将整数相除时,毫不奇怪的是,它会降低四舍五入。

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

如果我们强制转换要浮点数的最后一个整数,我们仍然会得到零,因为到我们的数字除以浮点数时,由于整数除法,该数字已经变为0。

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

与上述相同,但将float类型转换向左侧稍微移近。

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

最后,当我们将第一个整数转换为浮点数时,结果是所需的整数,因为从第一个除法(即最左边的整数)开始,我们使用浮点数。

额外1:如果您尝试回答该问题以改善算术评估,则应检查此内容

附加2:请注意以下情况:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0

It has to do with the version of python that you use. Basically it adopts the C behavior: if you divide two integers, the results will be rounded down to an integer. Also keep in mind that Python does the operations from left to right, which plays a role when you typecast.

Example: Since this is a question that always pops in my head when I am doing arithmetic operations (should I convert to float and which number), an example from that aspect is presented:

>>> a = 1/2/3/4/5/4/3
>>> a
0

When we divide integers, not surprisingly it gets lower rounded.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

If we typecast the last integer to float, we will still get zero, since by the time our number gets divided by the float has already become 0 because of the integer division.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

Same scenario as above but shifting the float typecast a little closer to the left side.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

Finally, when we typecast the first integer to float, the result is the desired one, since beginning from the first division, i.e. the leftmost one, we use floats.

Extra 1: If you are trying to answer that to improve arithmetic evaluation, you should check this

Extra 2: Please be careful of the following scenario:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0

回答 5

通过放置“。”来指定浮点数 该数字之后也会导致其默认浮动。

>>> 1 / 2
0

>>> 1. / 2.
0.5

Specifying a float by placing a ‘.’ after the number will also cause it to default to float.

>>> 1 / 2
0

>>> 1. / 2.
0.5

回答 6

使其中至少一个浮点,然后将是浮点除法,而不是整数:

>>> (20.0-10) / (100-10)
0.1111111111111111

将结果强制转换为浮点型为时已晚。

Make at least one of them float, then it will be float division, not integer:

>>> (20.0-10) / (100-10)
0.1111111111111111

Casting the result to float is too late.


回答 7

在python中cv2未更新除法计算。因此,您必须将其包括from __future__ import division 在程序的第一行中。

In python cv2 not updated the division calculation. so, you must include from __future__ import division in first line of the program.


回答 8

无论哪种方式,它都是整数除法。10/90 =0。在第二种情况下,您只是将0强制转换为浮点数。

尝试将“ /”的操作数之一强制转换为浮点数:

float(20-10) / (100-10)

Either way, it’s integer division. 10/90 = 0. In the second case, you’re merely casting 0 to a float.

Try casting one of the operands of “/” to be a float:

float(20-10) / (100-10)

回答 9

在第二个示例中,除法已经发生,您正在转换为浮动。试试这个:

float(20-10) / float(100-10)

You’re casting to float after the division has already happened in your second example. Try this:

float(20-10) / float(100-10)

回答 10

令我惊讶的是,没有人提到原始海报可能喜欢有理数。如果您对此感兴趣,基于Python的程序Sage会为您服务。(尽管3.x正在开发中,但目前仍基于Python2.x。)

sage: (20-10) / (100-10)
1/9

这不是每个人的解决方案,因为它会做一些准备工作,所以这些数字不是intSage Integer类元素。尽管如此,值得一提的是Python生态系统的一部分。

I’m somewhat surprised that no one has mentioned that the original poster might have liked rational numbers to result. Should you be interested in this, the Python-based program Sage has your back. (Currently still based on Python 2.x, though 3.x is under way.)

sage: (20-10) / (100-10)
1/9

This isn’t a solution for everyone, because it does do some preparsing so these numbers aren’t ints, but Sage Integer class elements. Still, worth mentioning as a part of the Python ecosystem.


回答 11

我个人更喜欢1. *在开始时插入一个。所以表达式变成了这样的东西:

1. * (20-10) / (100-10)

因为我总是对某些公式进行除法,例如:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

因此不可能简单地添加一个.0like 20.0。就我而言,用a换行float()可能会失去一点可读性。

Personally I preferred to insert a 1. * at the very beginning. So the expression become something like this:

1. * (20-10) / (100-10)

As I always do a division for some formula like:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

so it is impossible to simply add a .0 like 20.0. And in my case, wrapping with a float() may lose a little bit readability.


不带换行符的打印(print’a’,)打印空格,如何删除?

问题:不带换行符的打印(print’a’,)打印空格,如何删除?

我有此代码:

>>> for i in xrange(20):
...     print 'a',
... 
a a a a a a a a a a a a a a a a a a a a

我想输出'a',而' '不像这样:

aaaaaaaaaaaaaaaaaaaa

可能吗?

I have this code:

>>> for i in xrange(20):
...     print 'a',
... 
a a a a a a a a a a a a a a a a a a a a

I want to output 'a', without ' ' like this:

aaaaaaaaaaaaaaaaaaaa

Is it possible?


回答 0

有多种方法可以实现您的结果。如果你只是想为你的情况的解决方案,使用字符串倍增@Ant提到。仅当您的每个print语句都打印相同的字符串时,这才起作用。请注意,它适用于任何长度字符串的乘法(例如,'foo' * 20有效)。

>>> print 'a' * 20
aaaaaaaaaaaaaaaaaaaa

如果通常要这样做,请构建一个字符串,然后将其打印一次。这将为该字符串消耗一些内存,但是仅对进行一次调用print。请注意,+=现在使用的字符串串联使用的大小与您串联的字符串大小成线性关系,因此此操作很快。

>>> for i in xrange(20):
...     s += 'a'
... 
>>> print s
aaaaaaaaaaaaaaaaaaaa

或者,您可以使用sys.stdout更直接地进行操作。write(),这print是一个包装器。这将只写入您提供的原始字符串,而不进行任何格式化。请注意,即使在20 a秒结束时也不会打印换行符。

>>> import sys
>>> for i in xrange(20):
...     sys.stdout.write('a')
... 
aaaaaaaaaaaaaaaaaaaa>>> 

Python 3将print语句更改为print()函数,该函数允许您设置end参数。通过从中导入,可以在> = 2.6中使用它__future__。不过,我会避免在任何严重的2.x代码中使用此方法,因为对于从未使用过3.x的用户来说,这会有些混乱。但是,它应该使您体会3.x带来的一些好处。

>>> from __future__ import print_function
>>> for i in xrange(20):
...     print('a', end='')
... 
aaaaaaaaaaaaaaaaaaaa>>> 

There are a number of ways of achieving your result. If you’re just wanting a solution for your case, use string multiplication as @Ant mentions. This is only going to work if each of your print statements prints the same string. Note that it works for multiplication of any length string (e.g. 'foo' * 20 works).

>>> print 'a' * 20
aaaaaaaaaaaaaaaaaaaa

If you want to do this in general, build up a string and then print it once. This will consume a bit of memory for the string, but only make a single call to print. Note that string concatenation using += is now linear in the size of the string you’re concatenating so this will be fast.

>>> for i in xrange(20):
...     s += 'a'
... 
>>> print s
aaaaaaaaaaaaaaaaaaaa

Or you can do it more directly using sys.stdout.write(), which print is a wrapper around. This will write only the raw string you give it, without any formatting. Note that no newline is printed even at the end of the 20 as.

>>> import sys
>>> for i in xrange(20):
...     sys.stdout.write('a')
... 
aaaaaaaaaaaaaaaaaaaa>>> 

Python 3 changes the print statement into a print() function, which allows you to set an end parameter. You can use it in >=2.6 by importing from __future__. I’d avoid this in any serious 2.x code though, as it will be a little confusing for those who have never used 3.x. However, it should give you a taste of some of the goodness 3.x brings.

>>> from __future__ import print_function
>>> for i in xrange(20):
...     print('a', end='')
... 
aaaaaaaaaaaaaaaaaaaa>>> 

回答 1

PEP 3105:Python 2.6新增功能文档中的作为函数打印

>>> from __future__ import print_function
>>> print('a', end='')

显然,这仅适用于python 3.0或更高版本(或2.6+以from __future__ import print_function开头)。该print语句已删除,并print()在Python 3.0中默认成为函数。

From PEP 3105: print As a Function in the What’s New in Python 2.6 document:

>>> from __future__ import print_function
>>> print('a', end='')

Obviously that only works with python 3.0 or higher (or 2.6+ with a from __future__ import print_function at the beginning). The print statement was removed and became the print() function by default in Python 3.0.


回答 2

您可以通过在print语句之间将空字符串打印到stdout来抑制空格。

>>> import sys
>>> for i in range(20):
...   print 'a',
...   sys.stdout.write('')
... 
aaaaaaaaaaaaaaaaaaaa

但是,更干净的解决方案是首先构建您要打印的整个字符串,然后使用单个print语句将其输出。

You can suppress the space by printing an empty string to stdout between the print statements.

>>> import sys
>>> for i in range(20):
...   print 'a',
...   sys.stdout.write('')
... 
aaaaaaaaaaaaaaaaaaaa

However, a cleaner solution is to first build the entire string you’d like to print and then output it with a single print statement.


回答 3

您可以打印一个退格字符('\b'):

for i in xrange(20):
    print '\ba',

结果:

aaaaaaaaaaaaaaaaaaaa

You could print a backspace character ('\b'):

for i in xrange(20):
    print '\ba',

result:

aaaaaaaaaaaaaaaaaaaa

回答 4

Python 3.x:

for i in range(20):
    print('a', end='')

Python 2.6或2.7:

from __future__ import print_function
for i in xrange(20):
    print('a', end='')

Python 3.x:

for i in range(20):
    print('a', end='')

Python 2.6 or 2.7:

from __future__ import print_function
for i in xrange(20):
    print('a', end='')

回答 5

如果希望他们一次显示一个,则可以执行以下操作:

import time
import sys
for i in range(20):
    sys.stdout.write('a')
    sys.stdout.flush()
    time.sleep(0.5)

sys.stdout.flush() 必须在每次运行循环时强制写入字符。

If you want them to show up one at a time, you can do this:

import time
import sys
for i in range(20):
    sys.stdout.write('a')
    sys.stdout.flush()
    time.sleep(0.5)

sys.stdout.flush() is necessary to force the character to be written each time the loop is run.


回答 6

恰如其分:

打印为O(1),但先构建一个字符串,然后打印为O(n),其中n是字符串中字符的总数。因此,是的,尽管构建字符串是“更干净的”,但这并不是最有效的方法。

我的操作方式如下:

from sys import stdout
printf = stdout.write

现在,您有了一个“打印功能”,可以打印出您给它的任何字符串,而无需每次都返回换行符。

printf("Hello,")
printf("World!")

输出将是:世界,您好!

但是,如果要打印整数,浮点数或其他非字符串值,则必须使用str()函数将它们转换为字符串。

printf(str(2) + " " + str(4))

输出将是:2 4

Just as a side note:

Printing is O(1) but building a string and then printing is O(n), where n is the total number of characters in the string. So yes, while building the string is “cleaner”, it’s not the most efficient method of doing so.

The way I would do it is as follows:

from sys import stdout
printf = stdout.write

Now you have a “print function” that prints out any string you give it without returning the new line character each time.

printf("Hello,")
printf("World!")

The output will be: Hello, World!

However, if you want to print integers, floats, or other non-string values, you’ll have to convert them to a string with the str() function.

printf(str(2) + " " + str(4))

The output will be: 2 4


回答 7

无论是什么蚂蚁 ,或积累成一个字符串,然后打印一次:

s = '';
for i in xrange(20):
    s += 'a'
print s

Either what Ant says, or accumulate into a string, then print once:

s = '';
for i in xrange(20):
    s += 'a'
print s

回答 8

没有什么?你的意思是

>>> print 'a' * 20
aaaaaaaaaaaaaaaaaaaa

without what? do you mean

>>> print 'a' * 20
aaaaaaaaaaaaaaaaaaaa

?


回答 9

这真的很简单

对于python 3+版本,您只需要编写以下代码

for i in range(20):
      print('a',end='')

只需将循环转换为以下代码,您就不必担心其他事情

this is really simple

for python 3+ versions you only have to write the following codes

for i in range(20):
      print('a',end='')

just convert the loop to the following codes, you don’t have to worry about other things


回答 10

哇!!!

这是相当长一段时间

现在,在python 3.x中,这将非常容易

码:

for i in range(20):
      print('a',end='') # here end variable will clarify what you want in 
                        # end of the code

输出:

aaaaaaaaaaaaaaaaaaaa 

有关print()函数的更多信息

print(value1,value2,value3,sep='-',end='\n',file=sys.stdout,flush=False)

在这里

value1,value2,value3

您可以使用逗号打印多个值

sep = '-'

3个值将以’-‘字符分隔

您可以使用任何字符来代替甚至像sep =’@’或sep =’good’这样的字符串

end='\n'

默认情况下,打印功能将’\ n’字符放在输出末尾

但是您可以通过更改最终变量值来使用任何字符或字符串

例如end =’$’或end =’。或end =’Hello’

file=sys.stdout

这是默认值,系统标准输出

使用此参数,您可以创建输出文件流,例如

print("I am a Programmer", file=open("output.txt", "w"))

通过此代码,您将创建一个名为output.txt的文件,其中将存储您作为程序员的输出

flush = False

这是使用flush = True的默认值,您可以强制刷新流

WOW!!!

It’s pretty long time ago

Now, In python 3.x it will be pretty easy

code:

for i in range(20):
      print('a',end='') # here end variable will clarify what you want in 
                        # end of the code

output:

aaaaaaaaaaaaaaaaaaaa 

More about print() function

print(value1,value2,value3,sep='-',end='\n',file=sys.stdout,flush=False)

Here:

value1,value2,value3

you can print multiple values using commas

sep = '-'

3 values will be separated by ‘-‘ character

you can use any character instead of that even string like sep=’@’ or sep=’good’

end='\n'

by default print function put ‘\n’ charater at the end of output

but you can use any character or string by changing end variale value

like end=’$’ or end=’.’ or end=’Hello’

file=sys.stdout

this is a default value, system standard output

using this argument you can create a output file stream like

print("I am a Programmer", file=open("output.txt", "w"))

by this code you will create a file named output.txt where your output I am a Programmer will be stored

flush = False

It’s a default value using flush=True you can forcibly flush the stream


回答 11

就如此容易

def printSleeping():
     sleep = "I'm sleeping"
     v = ""
     for i in sleep:
         v += i
         system('cls')
         print v
         time.sleep(0.02)

as simple as that

def printSleeping():
     sleep = "I'm sleeping"
     v = ""
     for i in sleep:
         v += i
         system('cls')
         print v
         time.sleep(0.02)

Python-write()与writelines()和串联字符串

问题:Python-write()与writelines()和串联字符串

所以我正在学习Python。我正在上课,遇到一个问题,我不得不将很多压缩target.write()成一个write(),同时"\n"在每个用户输入变量(的对象write())之间都有一个。

我想出了:

nl = "\n"
lines = line1, nl, line2, nl, line3, nl
textdoc.writelines(lines)

如果我尝试这样做:

textdoc.write(lines)

我得到一个错误。但是如果我输入:

textdoc.write(line1 + "\n" + line2 + ....)

然后工作正常。为什么我不能在其中使用字符串作为换行符,write()但可以在其中使用呢writelines()

Python 2.7当我搜索google时,发现的大部分资源都超出了我的想象力,我仍然是一个外行。

So I’m learning Python. I am going through the lessons and ran into a problem where I had to condense a great many target.write() into a single write(), while having a "\n" between each user input variable(the object of write()).

I came up with:

nl = "\n"
lines = line1, nl, line2, nl, line3, nl
textdoc.writelines(lines)

If I try to do:

textdoc.write(lines)

I get an error. But if I type:

textdoc.write(line1 + "\n" + line2 + ....)

Then it works fine. Why am I unable to use a string for a newline in write() but I can use it in writelines()?

Python 2.7 When I searched google most resources I found were way over my head, I’m still a lay-people.


回答 0

  • writelines 期待字符串的迭代
  • write 需要一个字符串。

line1 + "\n" + line2将这些字符串合并到一个字符串中,然后再传递给write

请注意,如果您有很多行,则可能要使用"\n".join(list_of_lines)

  • writelines expects an iterable of strings
  • write expects a single string.

line1 + "\n" + line2 merges those strings together into a single string before passing it to write.

Note that if you have many lines, you may want to use "\n".join(list_of_lines).


回答 1

为什么我不能在write()中将字符串用于换行符,但可以在writelines()中使用它?

想法如下:如果要编写单个字符串,可以使用write()。如果您有一系列字符串,则可以使用编写所有字符串writelines()

write(arg)需要一个字符串作为参数并将其写入文件。如果您提供字符串列表,它将引发异常(顺便说一下,向我们显示错误!)。

writelines(arg)期望将iterable作为参数(在最一般的意义上,可迭代对象可以是元组,列表,字符串或迭代器)。迭代器中包含的每个项目均应为字符串。您提供的是一个字符串元组,因此一切正常。

字符串的性质对两个函数都无关紧要,即,无论您提供什么字符串,它们都只会写入文件。有趣的是,writelines()它本身并不添加换行符,因此方法名称实际上可能会造成很大的混乱。实际上,它的行为类似于一个称为的虚构方法write_all_of_these_strings(sequence)

接下来是Python中的一种惯用方式,将字符串列表写入文件,同时将每个字符串保留在自己的行中:

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.write('\n'.join(lines))

这将为您关闭文件。该构造'\n'.join(lines)将列表中的字符串连接(连接),lines并使用字符“ \ n”作为粘合。比使用+运算符更有效。

从相同的lines序列开始,以相同的输出结束,但使用writelines()

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.writelines("%s\n" % l for l in lines)

这利用了生成器表达式并动态创建了以换行符结尾的字符串。writelines()遍历此字符串序列并写入每个项目。

编辑:您应该注意的另一点:

write()并且readlines()writelines()引入之前就存在。writelines()后来作为的对应版本引入readlines(),以便人们可以轻松地编写通过readlines()以下方式读取的文件内容:

outfile.writelines(infile.readlines())

确实,这就是为什么使用writelines如此混乱的名称的主要原因。而且,今天,我们真的不再想要使用此方法。readlines()writelines()开始写入数据之前,将整个文件读取到计算机的内存中。首先,这可能会浪费时间。为什么不阅读其他部分就开始写部分数据呢?但是,最重要的是,这种方法可能会占用大量内存。在极端情况下,如果输入文件大于计算机的内存,则此方法甚至不起作用。解决此问题的方法是仅使用迭代器。一个工作示例:

with open('inputfile') as infile:
    with open('outputfile') as outfile:
        for line in infile:
            outfile.write(line)

这将逐行读取输入文件。读取一行后,该行即被写入输出文件。从概念上讲,内存中始终只有一行(相比之下,在采用读取行/写入行方法的情况下,整个文件内容都在内存中)。

Why am I unable to use a string for a newline in write() but I can use it in writelines()?

The idea is the following: if you want to write a single string you can do this with write(). If you have a sequence of strings you can write them all using writelines().

write(arg) expects a string as argument and writes it to the file. If you provide a list of strings, it will raise an exception (by the way, show errors to us!).

writelines(arg) expects an iterable as argument (an iterable object can be a tuple, a list, a string, or an iterator in the most general sense). Each item contained in the iterator is expected to be a string. A tuple of strings is what you provided, so things worked.

The nature of the string(s) does not matter to both of the functions, i.e. they just write to the file whatever you provide them. The interesting part is that writelines() does not add newline characters on its own, so the method name can actually be quite confusing. It actually behaves like an imaginary method called write_all_of_these_strings(sequence).

What follows is an idiomatic way in Python to write a list of strings to a file while keeping each string in its own line:

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.write('\n'.join(lines))

This takes care of closing the file for you. The construct '\n'.join(lines) concatenates (connects) the strings in the list lines and uses the character ‘\n’ as glue. It is more efficient than using the + operator.

Starting from the same lines sequence, ending up with the same output, but using writelines():

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.writelines("%s\n" % l for l in lines)

This makes use of a generator expression and dynamically creates newline-terminated strings. writelines() iterates over this sequence of strings and writes every item.

Edit: Another point you should be aware of:

write() and readlines() existed before writelines() was introduced. writelines() was introduced later as a counterpart of readlines(), so that one could easily write the file content that was just read via readlines():

outfile.writelines(infile.readlines())

Really, this is the main reason why writelines has such a confusing name. Also, today, we do not really want to use this method anymore. readlines() reads the entire file to the memory of your machine before writelines() starts to write the data. First of all, this may waste time. Why not start writing parts of data while reading other parts? But, most importantly, this approach can be very memory consuming. In an extreme scenario, where the input file is larger than the memory of your machine, this approach won’t even work. The solution to this problem is to use iterators only. A working example:

with open('inputfile') as infile:
    with open('outputfile') as outfile:
        for line in infile:
            outfile.write(line)

This reads the input file line by line. As soon as one line is read, this line is written to the output file. Schematically spoken, there always is only one single line in memory (compared to the entire file content being in memory in case of the readlines/writelines approach).


回答 2

如果您只想保存和加载列表,请尝试Pickle

泡菜保存:

with open("yourFile","wb")as file:
 pickle.dump(YourList,file)

和加载:

with open("yourFile","rb")as file:
 YourList=pickle.load(file)

if you just want to save and load a list try Pickle

Pickle saving:

with open("yourFile","wb")as file:
 pickle.dump(YourList,file)

and loading:

with open("yourFile","rb")as file:
 YourList=pickle.load(file)

回答 3

实际上,我认为问题在于您的变量“行”不好。您将行定义为元组,但是我相信write()需要一个字符串。您所要做的就是将逗号变成加号(+)。

nl = "\n"
lines = line1+nl+line2+nl+line3+nl
textdoc.writelines(lines)

应该管用。

Actually, I think the problem is that your variable “lines” is bad. You defined lines as a tuple, but I believe that write() requires a string. All you have to change is your commas into pluses (+).

nl = "\n"
lines = line1+nl+line2+nl+line3+nl
textdoc.writelines(lines)

should work.


回答 4

习德(Zed Shaw)的书中的练习16?您可以使用转义符,如下所示:

paragraph1 = "%s \n %s \n %s \n" % (line1, line2, line3)
target.write(paragraph1)
target.close()

Exercise 16 from Zed Shaw’s book? You can use escape characters as follows:

paragraph1 = "%s \n %s \n %s \n" % (line1, line2, line3)
target.write(paragraph1)
target.close()

Python-‘ASCII’编解码器无法解码字节

问题:Python-‘ASCII’编解码器无法解码字节

我真的很困惑 我尝试编码,但错误提示can't decode...

>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

我知道如何避免在字符串上加上“ u”前缀的错误。我只是想知道为什么在调用编码时错误是“无法解码”的。Python到底是做什么的?

I’m really confused. I tried to encode but the error said can't decode....

>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

I know how to avoid the error with “u” prefix on the string. I’m just wondering why the error is “can’t decode” when encode was called. What is Python doing under the hood?


回答 0

"你好".encode('utf-8')

encode将unicode对象转换为string对象。但是这里您已经在string对象上调用了它(因为您没有u)。因此python必须先将转换stringunicode对象。所以它相当于

"你好".decode().encode('utf-8')

但是解码失败,因为字符串无效的ascii。这就是为什么您会抱怨无法解码的原因。

"你好".encode('utf-8')

encode converts a unicode object to a string object. But here you have invoked it on a string object (because you don’t have the u). So python has to convert the string to a unicode object first. So it does the equivalent of

"你好".decode().encode('utf-8')

But the decode fails because the string isn’t valid ascii. That’s why you get a complaint about not being able to decode.


回答 1

始终从unicode 编码为字节。
在这个方向上,您可以选择encoding

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

另一种方法是从字节解码为unicode。
在这个方向上,您必须知道什么是编码

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

这一点压力不够大。如果您想避免播放unicode的“打hack鼠”游戏,那么了解数据级别的情况很重要。这里说明了另一种方式:

  • 一个unicode对象已经被解码了,您再也不想调用decode它了。
  • 一个字节串对象已经被编码,您永远不想调用encode它。

现在,在看到.encode字节字符串时,Python 2首先尝试将其隐式转换为文本(unicode对象)。同样,在看到.decodeunicode字符串时,Python 2隐式尝试将其转换为字节(str对象)。

这些隐式转换是您调用时可以得到的原因。这是因为编码通常接受type的参数;接收参数时,在使用另一种编码对它进行重新编码之前,会对类型进行隐式解码。此转换选择默认的“ ascii”解码器,给您编码器内部的解码错误。UnicodeDecodeErrorencodeunicodestrunicode

事实上,在Python 3的方法str.decodebytes.encode甚至不存在。为了避免这种常见的混淆,将它们移除是一个有争议的尝试。

…或任何编码sys.getdefaultencoding()提及的内容;通常这是“ ascii”

Always encode from unicode to bytes.
In this direction, you get to choose the encoding.

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

The other way is to decode from bytes to unicode.
In this direction, you have to know what the encoding is.

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

This point can’t be stressed enough. If you want to avoid playing unicode “whack-a-mole”, it’s important to understand what’s happening at the data level. Here it is explained another way:

  • A unicode object is decoded already, you never want to call decode on it.
  • A bytestring object is encoded already, you never want to call encode on it.

Now, on seeing .encode on a byte string, Python 2 first tries to implicitly convert it to text (a unicode object). Similarly, on seeing .decode on a unicode string, Python 2 implicitly tries to convert it to bytes (a str object).

These implicit conversions are why you can get UnicodeDecodeError when you’ve called encode. It’s because encoding usually accepts a parameter of type unicode; when receiving a str parameter, there’s an implicit decoding into an object of type unicode before re-encoding it with another encoding. This conversion chooses a default ‘ascii’ decoder, giving you the decoding error inside an encoder.

In fact, in Python 3 the methods str.decode and bytes.encode don’t even exist. Their removal was a [controversial] attempt to avoid this common confusion.

…or whatever coding sys.getdefaultencoding() mentions; usually this is ‘ascii’


回答 2

你可以试试这个

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

要么

您也可以尝试关注

在.py文件顶部添加以下行。

# -*- coding: utf-8 -*- 

You can try this

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

Or

You can also try following

Add following line at top of your .py file.

# -*- coding: utf-8 -*- 

回答 3

如果您使用的是Python <3,则需要在解释器前面加上一个前缀,u以告知您的字符串文字是Unicode

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'

进一步阅读Unicode HOWTO

If you’re using Python < 3, you’ll need to tell the interpreter that your string literal is Unicode by prefixing it with a u:

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'

Further reading: Unicode HOWTO.


回答 4

您用于u"你好".encode('utf8')编码unicode字符串。但是,如果要表示"你好",则应该对其进行解码。就像:

"你好".decode("utf8")

您将得到想要的东西。也许您应该了解有关编码和解码的更多信息。

You use u"你好".encode('utf8') to encode an unicode string. But if you want to represent "你好", you should decode it. Just like:

"你好".decode("utf8")

You will get what you want. Maybe you should learn more about encode & decode.


回答 5

如果您要处理Unicode,有时可以用代替encode('utf-8'),也可以忽略特殊字符,例如

"你好".encode('ascii','ignore')

或如something.decode('unicode_escape').encode('ascii','ignore')这里所建议

在此示例中不是特别有用,但是在无法转换某些特殊字符的其他情况下可以更好地工作。

或者,您可以考虑使用替换特定字符replace()

In case you’re dealing with Unicode, sometimes instead of encode('utf-8'), you can also try to ignore the special characters, e.g.

"你好".encode('ascii','ignore')

or as something.decode('unicode_escape').encode('ascii','ignore') as suggested here.

Not particularly useful in this example, but can work better in other scenarios when it’s not possible to convert some special characters.

Alternatively you can consider replacing particular character using replace().


回答 6

如果要从Linux或类似系统(BSD,不确定Mac)上的外壳启动python解释器,则还应检查外壳的默认编码。

locale charmap从shell 调用(不是python解释器),您应该看到

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

如果不是这种情况,您会看到其他情况,例如

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

Python将(至少在某些情况下,例如在我的情况下)继承外壳程序的编码,并且将无法打印(某些?全部?)unicode字符。Python的默认编码,你看,并通过控制sys.getdefaultencoding()sys.setdefaultencoding()在这种情况下被忽略。

如果发现此问题,可以通过以下方法解决

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(或选择要使用的键盘映射而不是en_EN。)您也可以编辑/etc/locale.conf(或控制系统中区域设置的文件)。

If you are starting the python interpreter from a shell on Linux or similar systems (BSD, not sure about Mac), you should also check the default encoding for the shell.

Call locale charmap from the shell (not the python interpreter) and you should see

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

If this is not the case, and you see something else, e.g.

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

Python will (at least in some cases such as in mine) inherit the shell’s encoding and will not be able to print (some? all?) unicode characters. Python’s own default encoding that you see and control via sys.getdefaultencoding() and sys.setdefaultencoding() is in this case ignored.

If you find that you have this problem, you can fix that by

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(Or alternatively choose whichever keymap you want instead of en_EN.) You can also edit /etc/locale.conf (or whichever file governs the locale definition in your system) to correct this.


Python中的raw_input函数

问题:Python中的raw_input函数

功能是什么raw_input?是用户界面吗?我们什么时候使用它?

What is the raw_input function? Is it a user interface? When do we use it?


回答 0

它提出了一个提示给用户(可选argraw_input([arg])),从用户获得输入,并通过在一个字符串的用户返回数据的输入。请参阅有关的文档raw_input()

例:

name = raw_input("What is your name? ")
print "Hello, %s." % name

这与input() 后者的不同之处在于后者试图解释用户给出的输入。通常最好避免input()并坚持使用raw_input()自定义的解析/转换代码。

注意:这适用于Python 2.x

It presents a prompt to the user (the optional arg of raw_input([arg])), gets input from the user and returns the data input by the user in a string. See the docs for raw_input().

Example:

name = raw_input("What is your name? ")
print "Hello, %s." % name

This differs from input() in that the latter tries to interpret the input given by the user; it is usually best to avoid input() and to stick with raw_input() and custom parsing/conversion code.

Note: This is for Python 2.x


回答 1

raw_input()input()在Python 3中被重命名为。

来自http://docs.python.org/dev/py3k/whatsnew/3.0.html

raw_input() was renamed to input() in Python 3.

From http://docs.python.org/dev/py3k/whatsnew/3.0.html


回答 2

“输入”功能将您输入的输入转换为Python代码。“ raw_input”不会转换输入,而是按照给定的方式接受输入。建议对所有内容使用raw_input。用法:

>>a = raw_input()
>>5
>>a
>>'5'

The “input” function converts the input you enter as if it were python code. “raw_input” doesn’t convert the input and takes the input as it is given. Its advisable to use raw_input for everything. Usage:

>>a = raw_input()
>>5
>>a
>>'5'

回答 3

raw_input是一种输入形式,采用字符串形式的参数,而input函数则根据您的输入来采用值。假设a = input(5)返回a作为值为5的整数,而a = raw_input(5)返回a作为字符串“ 5”

raw_input is a form of input that takes the argument in the form of a string whereas the input function takes the value depending upon your input. Say, a=input(5) returns a as an integer with value 5 whereas a=raw_input(5) returns a as a string of “5”


回答 4

如果需要使代码更简单,则另一个示例方法是使用print混合提示。

格式:-

x = raw_input()-这将以字符串形式返回用户输入

x = int(raw_input())-从raw_input()以字符串形式获取输入数字,然后使用int()将其转换为整数。

print '\nWhat\'s your name ?', 
name = raw_input('--> ')
print '\nHow old are you, %s?' % name,
age = int(raw_input())
print '\nHow tall are you (in cms), %s?' % name,
height = int(raw_input())
print '\nHow much do you weigh (in kgs), %s?' % name,
weight = int(raw_input())

print '\nSo, %s is %d years old, %d cms tall and weighs %d kgs.\n' %(
name, age, height, weight)

Another example method, to mix the prompt using print, if you need to make your code simpler.

Format:-

x = raw_input () — This will return the user input as a string

x= int(raw_input()) — Gets the input number as a string from raw_input() and then converts it to an integer using int().

print '\nWhat\'s your name ?', 
name = raw_input('--> ')
print '\nHow old are you, %s?' % name,
age = int(raw_input())
print '\nHow tall are you (in cms), %s?' % name,
height = int(raw_input())
print '\nHow much do you weigh (in kgs), %s?' % name,
weight = int(raw_input())

print '\nSo, %s is %d years old, %d cms tall and weighs %d kgs.\n' %(
name, age, height, weight)

回答 5

如果我让raw_input这样,就不要Josh或其他任何东西。我想这是一个变量,但我不理解她的角色:-(

raw_input函数提示您输入,并以字符串形式返回。这肯定对我有用。您不需要闲置。只需打开“ DOS提示符”并运行程序。

这就是我的样子:

C:\temp>type test.py
print "Halt!"
s = raw_input("Who Goes there? ")
print "You may pass,", s

C:\temp>python test.py
Halt!
Who Goes there? Magnus
You may pass, Magnus

[Enter在程序打印“谁去那里?”之后,我键入我的名字并按]。

If I let raw_input like that, no Josh or anything else. It’s a variable,I think,but I don’t understand her roll :-(

The raw_input function prompts you for input and returns that as a string. This certainly worked for me. You don’t need idle. Just open a “DOS prompt” and run the program.

This is what it looked like for me:

C:\temp>type test.py
print "Halt!"
s = raw_input("Who Goes there? ")
print "You may pass,", s

C:\temp>python test.py
Halt!
Who Goes there? Magnus
You may pass, Magnus

I types my name and pressed [Enter] after the program had printed “Who Goes there?”


Python 2.x中的nonlocal关键字

问题:Python 2.x中的nonlocal关键字

我正在尝试在python 2.6中实现闭包,我需要访问一个非局部变量,但似乎此关键字在python 2.x中不可用。在这些版本的python中,如何在闭包中访问非局部变量?

I’m trying to implement a closure in Python 2.6 and I need to access a nonlocal variable but it seems like this keyword is not available in python 2.x. How should one access nonlocal variables in closures in these versions of python?


回答 0

内部函数可以读取 2.x中的非局部变量,而无需重新绑定它们。这很烦人,但是您可以解决它。只需创建一个字典,然后将数据作为元素存储在其中即可。禁止内部函数对非局部变量引用的对象进行突变

要使用Wikipedia中的示例:

def outer():
    d = {'y' : 0}
    def inner():
        d['y'] += 1
        return d['y']
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

Inner functions can read nonlocal variables in 2.x, just not rebind them. This is annoying, but you can work around it. Just create a dictionary, and store your data as elements therein. Inner functions are not prohibited from mutating the objects that nonlocal variables refer to.

To use the example from Wikipedia:

def outer():
    d = {'y' : 0}
    def inner():
        d['y'] += 1
        return d['y']
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

回答 1

以下解决方案的灵感来自Elias Zamaria答案,但与该答案相反,它确实可以正确处理外部函数的多次调用。“变量” inner.y位于的当前调用中outer。因为它是一个变量,所以它不是变量,而是对象属性(对象inner本身就是函数本身)。这非常丑陋(请注意,只能在inner定义函数后才能创建属性),但似乎有效。

def outer():
    def inner():
        inner.y += 1
        return inner.y
    inner.y = 0
    return inner

f = outer()
g = outer()
print(f(), f(), g(), f(), g()) #prints (1, 2, 1, 3, 2)

The following solution is inspired by the answer by Elias Zamaria, but contrary to that answer does handle multiple calls of the outer function correctly. The “variable” inner.y is local to the current call of outer. Only it isn’t a variable, since that is forbidden, but an object attribute (the object being the function inner itself). This is very ugly (note that the attribute can only be created after the inner function is defined) but seems effective.

def outer():
    def inner():
        inner.y += 1
        return inner.y
    inner.y = 0
    return inner

f = outer()
g = outer()
print(f(), f(), g(), f(), g()) #prints (1, 2, 1, 3, 2)

回答 2

与字典相比,非本地类的混乱程度更低。修改@ChrisB的示例

def outer():
    class context:
        y = 0
    def inner():
        context.y += 1
        return context.y
    return inner

然后

f = outer()
assert f() == 1
assert f() == 2
assert f() == 3
assert f() == 4

每个external()调用都会创建一个称为上下文的新的独特类(不仅仅是一个新实例)。因此,它避免了@Nathaniel提防共享上下文。

g = outer()
assert g() == 1
assert g() == 2

assert f() == 5

Rather than a dictionary, there’s less clutter to a nonlocal class. Modifying @ChrisB’s example:

def outer():
    class context:
        y = 0
    def inner():
        context.y += 1
        return context.y
    return inner

Then

f = outer()
assert f() == 1
assert f() == 2
assert f() == 3
assert f() == 4

Each outer() call creates a new and distinct class called context (not merely a new instance). So it avoids @Nathaniel’s beware about shared context.

g = outer()
assert g() == 1
assert g() == 2

assert f() == 5

回答 3

我认为这里的关键是“访问”的含义。读取闭包范围之外的变量应该没有问题,例如,

x = 3
def outer():
    def inner():
        print x
    inner()
outer()

应该可以按预期工作(打印3)。但是,覆盖x的值不起作用,例如,

x = 3
def outer():
    def inner():
        x = 5
    inner()
outer()
print x

仍会打印3。根据我对PEP-3104的理解,这就是nonlocal关键字的含义。如PEP中所述,您可以使用一个类来完成同一件事(有点凌乱):

class Namespace(object): pass
ns = Namespace()
ns.x = 3
def outer():
    def inner():
        ns.x = 5
    inner()
outer()
print ns.x

I think the key here is what you mean by “access”. There should be no issue with reading a variable outside of the closure scope, e.g.,

x = 3
def outer():
    def inner():
        print x
    inner()
outer()

should work as expected (printing 3). However, overriding the value of x does not work, e.g.,

x = 3
def outer():
    def inner():
        x = 5
    inner()
outer()
print x

will still print 3. From my understanding of PEP-3104 this is what the nonlocal keyword is meant to cover. As mentioned in the PEP, you can use a class to accomplish the same thing (kind of messy):

class Namespace(object): pass
ns = Namespace()
ns.x = 3
def outer():
    def inner():
        ns.x = 5
    inner()
outer()
print ns.x

回答 4

如果由于任何原因,此处的任何答案都不理想,则可以使用另一种方法在Python 2中实现非局部变量:

def outer():
    outer.y = 0
    def inner():
        outer.y += 1
        return outer.y
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

在变量的赋值语句中使用函数名称是多余的,但对我来说,比将变量放入字典中看起来更简单和简洁。就像克里斯·B(Chris B.)的回答一样,一个电话会记住另一个电话的价值。

There is another way to implement nonlocal variables in Python 2, in case any of the answers here are undesirable for whatever reason:

def outer():
    outer.y = 0
    def inner():
        outer.y += 1
        return outer.y
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

It is redundant to use the name of the function in the assignment statement of the variable, but it looks simpler and cleaner to me than putting the variable in a dictionary. The value is remembered from one call to another, just like in Chris B.’s answer.


回答 5

以下是Alois Mahdal在评论另一个答案时提出的建议:

class Nonlocal(object):
    """ Helper to implement nonlocal names in Python 2.x """
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


def outer():
    nl = Nonlocal(y=0)
    def inner():
        nl.y += 1
        return nl.y
    return inner

f = outer()
print(f(), f(), f()) # -> (1 2 3)

更新资料

在最近回顾了这一点之后,我对它的装饰风格感到震惊-当我想到将其实现为装饰器将使它更加通用和有用时(尽管这样做无疑会在某种程度上降低其可读性)。

# Implemented as a decorator.

class Nonlocal(object):
    """ Decorator class to help implement nonlocal names in Python 2.x """
    def __init__(self, **kwargs):
        self._vars = kwargs

    def __call__(self, func):
        for k, v in self._vars.items():
            setattr(func, k, v)
        return func


@Nonlocal(y=0)
def outer():
    def inner():
        outer.y += 1
        return outer.y
    return inner


f = outer()
print(f(), f(), f()) # -> (1 2 3)

请注意,这两个版本均可在Python 2和3中使用。

Here’s something inspired by a suggestion Alois Mahdal made in a comment regarding another answer:

class Nonlocal(object):
    """ Helper to implement nonlocal names in Python 2.x """
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


def outer():
    nl = Nonlocal(y=0)
    def inner():
        nl.y += 1
        return nl.y
    return inner

f = outer()
print(f(), f(), f()) # -> (1 2 3)

Update

After looking back at this recently, I was struck by how decorator-like it was—when it dawned on me that implementing it as one would make it more generic & useful (although doing so arguably degrades its readability to some degree).

# Implemented as a decorator.

class Nonlocal(object):
    """ Decorator class to help implement nonlocal names in Python 2.x """
    def __init__(self, **kwargs):
        self._vars = kwargs

    def __call__(self, func):
        for k, v in self._vars.items():
            setattr(func, k, v)
        return func


@Nonlocal(y=0)
def outer():
    def inner():
        outer.y += 1
        return outer.y
    return inner


f = outer()
print(f(), f(), f()) # -> (1 2 3)

Note that both versions work in both Python 2 and 3.


回答 6

python的作用域规则中有一个缺陷-赋值使变量在其立即包含的函数作用域内是局部的。对于全局变量,您可以使用global关键字解决。

解决方案是引入一个在两个作用域之间共享的对象,该对象包含可变变量,但本身通过未分配的变量引用。

def outer(v):
    def inner(container = [v]):
        container[0] += 1
        return container[0]
    return inner

另一种选择是一些示波器黑客:

def outer(v):
    def inner(varname = 'v', scope = locals()):
        scope[varname] += 1
        return scope[varname]
    return inner

您可能可以找出一些技巧来将参数的名称获取到outer,然后将其作为varname传递,但是在不依赖名称的情况下,outer您需要使用Y组合器。

There is a wart in python’s scoping rules – assignment makes a variable local to its immediately enclosing function scope. For a global variable, you would solve this with the global keyword.

The solution is to introduce an object which is shared between the two scopes, which contains mutable variables, but is itself referenced through a variable which is not assigned.

def outer(v):
    def inner(container = [v]):
        container[0] += 1
        return container[0]
    return inner

An alternative is some scopes hackery:

def outer(v):
    def inner(varname = 'v', scope = locals()):
        scope[varname] += 1
        return scope[varname]
    return inner

You might be able to figure out some trickery to get the name of the parameter to outer, and then pass it as varname, but without relying on the name outer you would like need to use a Y combinator.


回答 7

另一种方法(尽管太冗长了):

import ctypes

def outer():
    y = 0
    def inner():
        ctypes.pythonapi.PyCell_Set(id(inner.func_closure[0]), id(y + 1))
        return y
    return inner

x = outer()
x()
>> 1
x()
>> 2
y = outer()
y()
>> 1
x()
>> 3

Another way to do it (although it’s too verbose):

import ctypes

def outer():
    y = 0
    def inner():
        ctypes.pythonapi.PyCell_Set(id(inner.func_closure[0]), id(y + 1))
        return y
    return inner

x = outer()
x()
>> 1
x()
>> 2
y = outer()
y()
>> 1
x()
>> 3

回答 8

将Martineau的优雅解决方案扩展到一个实用且不太优雅的用例中,我得到:

class nonlocals(object):
""" Helper to implement nonlocal names in Python 2.x.
Usage example:
def outer():
     nl = nonlocals( n=0, m=1 )
     def inner():
         nl.n += 1
     inner() # will increment nl.n

or...
    sums = nonlocals( { k:v for k,v in locals().iteritems() if k.startswith('tot_') } )
"""
def __init__(self, **kwargs):
    self.__dict__.update(kwargs)

def __init__(self, a_dict):
    self.__dict__.update(a_dict)

Extending Martineau elegant solution above to a practical and somewhat less elegant use case I get:

class nonlocals(object):
""" Helper to implement nonlocal names in Python 2.x.
Usage example:
def outer():
     nl = nonlocals( n=0, m=1 )
     def inner():
         nl.n += 1
     inner() # will increment nl.n

or...
    sums = nonlocals( { k:v for k,v in locals().iteritems() if k.startswith('tot_') } )
"""
def __init__(self, **kwargs):
    self.__dict__.update(kwargs)

def __init__(self, a_dict):
    self.__dict__.update(a_dict)

回答 9

使用全局变量

def outer():
    global y # import1
    y = 0
    def inner():
        global y # import2 - requires import1
        y += 1
        return y
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

我个人不喜欢全局变量。但是,我的建议基于https://stackoverflow.com/a/19877437/1083704回答

def report():
        class Rank: 
            def __init__(self):
                report.ranks += 1
        rank = Rank()
report.ranks = 0
report()

在用户需要声明全局变量的地方ranks,每次需要调用report。我的改进消除了从用户初始化函数变量的需要。

Use a global variable

def outer():
    global y # import1
    y = 0
    def inner():
        global y # import2 - requires import1
        y += 1
        return y
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

Personally, I do not like the global variables. But, my proposal is based on https://stackoverflow.com/a/19877437/1083704 answer

def report():
        class Rank: 
            def __init__(self):
                report.ranks += 1
        rank = Rank()
report.ranks = 0
report()

where user needs to declare a global variable ranks, every time you need to call the report. My improvement eliminates the need to initialize the function variables from the user.


Python super()引发TypeError

问题:Python super()引发TypeError

在Python 2.5中,以下代码引发TypeError

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

如果我更换class Xclass X(object),它会奏效。这有什么解释?

In Python 2.5, the following code raises a TypeError:

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

If I replace the class X with class X(object), it will work. What’s the explanation for this?


回答 0

原因是super()只能在新型类上运行,这在2.x系列中意味着从object

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b

The reason is that super() only operates on new-style classes, which in the 2.x series means extending from object:

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b

回答 1

另外,除非必须,否则不要使用super()。您可能会怀疑,使用新型类不是通用的“正确的事情”。

有时候,您可能期望多重继承,并且可能会想要多重继承,但是在您知道MRO的繁琐细节之前,最好不要去管它,并坚持:

 X.a(self)

In addition, don’t use super() unless you have to. It’s not the general-purpose “right thing” to do with new-style classes that you might suspect.

There are times when you’re expecting multiple inheritance and you might possibly want it, but until you know the hairy details of the MRO, best leave it alone and stick to:

 X.a(self)

回答 2

如果以上答案均未明确提及。您的父类需要继承自“对象”,这实际上会将其转变为新的样式类。

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass

In case none of the above answers mentioned it clearly. Your parent class needs to inherit from “object”, which would essentially turn it into a new style class.

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass

回答 3

我尝试了各种Xa()方法;但是,它们似乎需要X的实例才能执行a(),所以我做了X()。a(self),这似乎比以前的回答更完整,至少对于我遇到的应用程序而言。由于不必要的构造和破坏,这似乎不是解决问题的好方法,但它可以正常工作。

我的特定应用程序是Python的cmd.Cmd模块,由于某种原因,它显然不是NewStyle对象。

最后结果:

X().a(self)

I tried the various X.a() methods; however, they seem to require an instance of X in order to perform a(), so I did X().a(self), which seems more complete than the previous answers, at least for the applications I’ve encountered. It doesn’t seem to be a good way of handling the problem as there is unnecessary construction and destruction, but it works fine.

My specific application was Python’s cmd.Cmd module, which is evidently not a NewStyle object for some reason.

Final Result:

X().a(self)

Python中“ in”的关联性?

问题:Python中“ in”的关联性?

我正在制作一个Python解析器,这确实让我感到困惑:

>>>  1 in  []  in 'a'
False

>>> (1 in  []) in 'a'
TypeError: 'in <string>' requires string as left operand, not bool

>>>  1 in ([] in 'a')
TypeError: 'in <string>' requires string as left operand, not list

关于关联性等方面,“ in”在Python中到底如何工作?

为什么这些表达式中没有两个表现相同?

I’m making a Python parser, and this is really confusing me:

>>>  1 in  []  in 'a'
False

>>> (1 in  []) in 'a'
TypeError: 'in <string>' requires string as left operand, not bool

>>>  1 in ([] in 'a')
TypeError: 'in <string>' requires string as left operand, not list

How exactly does “in” work in Python, with regards to associativity, etc.?

Why do no two of these expressions behave the same way?


回答 0

1 in [] in 'a'被评估为(1 in []) and ([] in 'a')

由于第一个条件(1 in [])是False,整个条件的评估为False; ([] in 'a')永远不会实际评估,因此不会引发任何错误。

这是语句定义:

In [121]: def func():
   .....:     return 1 in [] in 'a'
   .....: 

In [122]: dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               6 (in)
             11 JUMP_IF_FALSE            8 (to 22)  #if first comparison is wrong 
                                                    #then jump to 22, 
             14 POP_TOP             
             15 LOAD_CONST               2 ('a')
             18 COMPARE_OP               6 (in)     #this is never executed, so no Error
             21 RETURN_VALUE         
        >>   22 ROT_TWO             
             23 POP_TOP             
             24 RETURN_VALUE        

In [150]: def func1():
   .....:     return (1 in  []) in 'a'
   .....: 

In [151]: dis.dis(func1)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               3 (())
              6 COMPARE_OP               6 (in)   # perform 1 in []
              9 LOAD_CONST               2 ('a')  # now load 'a'
             12 COMPARE_OP               6 (in)   # compare result of (1 in []) with 'a'
                                                  # throws Error coz (False in 'a') is
                                                  # TypeError
             15 RETURN_VALUE   



In [153]: def func2():
   .....:     return 1 in ([] in 'a')
   .....: 

In [154]: dis.dis(func2)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 LOAD_CONST               2 ('a') 
              9 COMPARE_OP               6 (in)  # perform ([] in 'a'), which is 
                                                 # Incorrect, so it throws TypeError
             12 COMPARE_OP               6 (in)  # if no Error then 
                                                 # compare 1 with the result of ([] in 'a')
             15 RETURN_VALUE        

1 in [] in 'a' is evaluated as (1 in []) and ([] in 'a').

Since the first condition (1 in []) is False, the whole condition is evaluated as False; ([] in 'a') is never actually evaluated, so no error is raised.

Here are the statement definitions:

In [121]: def func():
   .....:     return 1 in [] in 'a'
   .....: 

In [122]: dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               6 (in)
             11 JUMP_IF_FALSE            8 (to 22)  #if first comparison is wrong 
                                                    #then jump to 22, 
             14 POP_TOP             
             15 LOAD_CONST               2 ('a')
             18 COMPARE_OP               6 (in)     #this is never executed, so no Error
             21 RETURN_VALUE         
        >>   22 ROT_TWO             
             23 POP_TOP             
             24 RETURN_VALUE        

In [150]: def func1():
   .....:     return (1 in  []) in 'a'
   .....: 

In [151]: dis.dis(func1)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               3 (())
              6 COMPARE_OP               6 (in)   # perform 1 in []
              9 LOAD_CONST               2 ('a')  # now load 'a'
             12 COMPARE_OP               6 (in)   # compare result of (1 in []) with 'a'
                                                  # throws Error coz (False in 'a') is
                                                  # TypeError
             15 RETURN_VALUE   



In [153]: def func2():
   .....:     return 1 in ([] in 'a')
   .....: 

In [154]: dis.dis(func2)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 LOAD_CONST               2 ('a') 
              9 COMPARE_OP               6 (in)  # perform ([] in 'a'), which is 
                                                 # Incorrect, so it throws TypeError
             12 COMPARE_OP               6 (in)  # if no Error then 
                                                 # compare 1 with the result of ([] in 'a')
             15 RETURN_VALUE        

回答 1

Python通过链式比较来做特殊的事情。

对以下内容的评估不同:

x > y > z   # in this case, if x > y evaluates to true, then
            # the value of y is being used to compare, again,
            # to z

(x > y) > z # the parenth form, on the other hand, will first
            # evaluate x > y. And, compare the evaluated result
            # with z, which can be "True > z" or "False > z"

但是,在这两种情况下,如果第一个比较是False,则不会查看语句的其余部分。

对于您的特殊情况

1 in [] in 'a'   # this is false because 1 is not in []

(1 in []) in a   # this gives an error because we are
                 # essentially doing this: False in 'a'

1 in ([] in 'a') # this fails because you cannot do
                 # [] in 'a'

同样为了说明上面的第一条规则,这些是评估为True的语句。

1 in [1,2] in [4,[1,2]] # But "1 in [4,[1,2]]" is False

2 < 4 > 1               # and note "2 < 1" is also not true

python运算符的优先级:http : //docs.python.org/reference/expressions.html#summary

Python does special things with chained comparisons.

The following are evaluated differently:

x > y > z   # in this case, if x > y evaluates to true, then
            # the value of y is being used to compare, again,
            # to z

(x > y) > z # the parenth form, on the other hand, will first
            # evaluate x > y. And, compare the evaluated result
            # with z, which can be "True > z" or "False > z"

In both cases though, if the first comparison is False, the rest of the statement won’t be looked at.

For your particular case,

1 in [] in 'a'   # this is false because 1 is not in []

(1 in []) in a   # this gives an error because we are
                 # essentially doing this: False in 'a'

1 in ([] in 'a') # this fails because you cannot do
                 # [] in 'a'

Also to demonstrate the first rule above, these are statements that evaluate to True.

1 in [1,2] in [4,[1,2]] # But "1 in [4,[1,2]]" is False

2 < 4 > 1               # and note "2 < 1" is also not true

Precedence of python operators: http://docs.python.org/reference/expressions.html#summary


回答 2

从文档中:

比较可以任意链接,例如,x <y <= z等于x <y和y <= z,除了y仅被评估一次(但在两种情况下,当x <y被发现时,z都不被评估。是假的)。

这意味着,x in y in z!中没有关联性!

以下是等效的:

1 in  []  in 'a'
# <=>
middle = []
#            False          not evaluated
result = (1 in middle) and (middle in 'a')


(1 in  []) in 'a'
# <=>
lhs = (1 in []) # False
result = lhs in 'a' # False in 'a' - TypeError


1 in  ([] in 'a')
# <=>
rhs = ([] in 'a') # TypeError
result = 1 in rhs

From the documentation:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

What this means is, that there no associativity in x in y in z!

The following are equivalent:

1 in  []  in 'a'
# <=>
middle = []
#            False          not evaluated
result = (1 in middle) and (middle in 'a')


(1 in  []) in 'a'
# <=>
lhs = (1 in []) # False
result = lhs in 'a' # False in 'a' - TypeError


1 in  ([] in 'a')
# <=>
rhs = ([] in 'a') # TypeError
result = 1 in rhs

回答 3

简短的回答是,由于这里已经以良好的方式多次给出了一个较长的答案,那就是布尔表达式被短路了,如果进一步的评估不能使true变为false ,则布尔表达式 已停止评估。

(请参阅http://en.wikipedia.org/wiki/Short-circuit_evaluation

答案可能有点短(没有双关语),但是如上所述,所有其他解释在这里都已经做得很好,但是我认为该词值得一提。

The short answer, since the long one is already given several times here and in excellent ways, is that the boolean expression is short-circuited, this is has stopped evaluation when a change of true in false or vice versa cannot happen by further evaluation.

(see http://en.wikipedia.org/wiki/Short-circuit_evaluation)

It might be a little short (no pun intended) as an answer, but as mentioned, all other explanation is allready done quite well here, but I thought the term deserved to be mentioned.