标签归档:operators

python *运算符的专有名称?

问题:python *运算符的专有名称?

什么是运营商的正确名称*,如function(*args)?打开包装,解压缩,还有其他东西吗?

What is the correct name for operator *, as in function(*args)? unpack, unzip, something else?


回答 0

在Ruby和Perl 6中,这被称为“ splat”,我认为那些社区的大多数人都会明白您的意思。

Python的教程使用短语“拆包参数列表”,这是长和描述。我在Python中还没有听说过其他特殊名称。

In Ruby and Perl 6 this has been called “splat”, and I think most people from those communities will figure out what you mean if you call it that.

The Python tutorial uses the phrase “unpacking argument lists”, which is long and descriptive.

It is also referred to as iterable unpacking, or in the case of **, dictionary unpacking.


回答 1

我称之为“位置扩展”,与之相反**,我称之为“关键字扩展”。

I call it “positional expansion”, as opposed to ** which I call “keyword expansion”.


回答 2

Python的教程简单地说,这是的*-运算符“。它执行任意参数列表的解压缩。

The Python Tutorial simply calls it ‘the *-operator’. It performs unpacking of arbitrary argument lists.


回答 3

我说“ star-args”,Python的人似乎知道我的意思。

**比较棘手-我认为只是“ qargs”,因为它通常用作**kw**kwargs

I say “star-args” and Python people seem to know what i mean.

** is trickier – I think just “qargs” since it is usually used as **kw or **kwargs


回答 4

你也可以拨打*一个聚集参数(在函数参数定义中使用时)或分散操作时(在函数调用中使用)。

如此处所示:考虑Python / Tuples / Variable-length参数元组

One can also call * a gather parameter (when used in function arguments definition) or a scatter operator (when used at function invocation).

As seen here: Think Python/Tuples/Variable-length argument tuples.


回答 5

我相信它最常被称为“ splat运算符”。解压缩参数是它的作用。

I believe it’s most commonly called the “splat operator.” Unpacking arguments is what it does.


回答 6

我将* args称为“ star args”或“ varargs”,并将** kwargs称为“ keyword args”。

I call *args “star args” or “varargs” and **kwargs “keyword args”.


Python中的代字号运算符

问题:Python中的代字号运算符

Python中的tilde运算符有什么用?

我能想到的一件事是在字符串或列表的两面都做一些事情,例如检查字符串是否为回文:

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2)) 

还有其他好的用法吗?

What’s the usage of the tilde operator in Python?

One thing I can think about is do something in both sides of a string or list, such as check if a string is palindromic or not:

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2)) 

Any other good usage?


回答 0

它是从C借来的一元运算符(采用单个参数),其中所有数据类型只是解释字节的不同方式。这是“取反”或“补码”操作,其中输入数据的所有位都取反。

在Python中,对于整数,该整数的二进制补码表示形式的位被颠倒(b <- b XOR 1对于每个单独的位而言),并且结果再次解释为二进制补码整数。因此对于整数,~x等于(-x) - 1

~运算符的形式化形式为operator.invert。要在您自己的类中支持此运算符,请为其提供一个__invert__(self)方法。

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

对于具有相同类实例的实例的“补码”或“逆”有意义的任何类,都可以用作反转运算符。但是,如果误用了运算符,则可能导致混乱,因此请确保在为__invert__类提供方法之前这样做确实有意义。(请注意,字节字符串[ex:'\xff']不支持此运算符,即使将字节字符串的所有位取反也很有意义。)

It is a unary operator (taking a single argument) that is borrowed from C, where all data types are just different ways of interpreting bytes. It is the “invert” or “complement” operation, in which all the bits of the input data are reversed.

In Python, for integers, the bits of the twos-complement representation of the integer are reversed (as in b <- b XOR 1 for each individual bit), and the result interpreted again as a twos-complement integer. So for integers, ~x is equivalent to (-x) - 1.

The reified form of the ~ operator is provided as operator.invert. To support this operator in your own class, give it an __invert__(self) method.

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

Any class in which it is meaningful to have a “complement” or “inverse” of an instance that is also an instance of the same class is a possible candidate for the invert operator. However, operator overloading can lead to confusion if misused, so be sure that it really makes sense to do so before supplying an __invert__ method to your class. (Note that byte-strings [ex: '\xff'] do not support this operator, even though it is meaningful to invert all the bits of a byte-string.)


回答 1

~是python中按位补码运算符,它本质上计算-x - 1

所以一张桌子看起来像

i  ~i  
0  -1
1  -2
2  -3
3  -4 
4  -5 
5  -6

因此,对于i = 0它会比较s[0]s[len(s) - 1],对i = 1s[1]s[len(s) - 2]

至于您的其他问题,这对于一系列按位破解可能很有

~ is the bitwise complement operator in python which essentially calculates -x - 1

So a table would look like

i  ~i  
0  -1
1  -2
2  -3
3  -4 
4  -5 
5  -6

So for i = 0 it would compare s[0] with s[len(s) - 1], for i = 1, s[1] with s[len(s) - 2].

As for your other question, this can be useful for a range of bitwise hacks.


回答 2

除了是按位补码运算符外,~还可以帮助还原布尔值,尽管bool此处不是常规类型,而是应使用numpy.bool_


对此进行了解释,

import numpy as np
assert ~np.True_ == np.False_

有时,反转逻辑值可能很有用,例如,下面的~运算符用于清除数据集并返回不带NaN的列。

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]

Besides being a bitwise complement operator, ~ can also help revert a boolean value, though it is not the conventional bool type here, rather you should use numpy.bool_.


This is explained in,

import numpy as np
assert ~np.True_ == np.False_

Reversing logical value can be useful sometimes, e.g., below ~ operator is used to cleanse your dataset and return you a column without NaN.

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]

回答 3

应该注意的是,在数组索引的情况下,array[~i]等于reversed_array[i]。可以将其视为从数组末尾开始的索引:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i

One should note that in the case of array indexing, array[~i] amounts to reversed_array[i]. It can be seen as indexing starting from the end of the array:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i

回答 4

我在实践中唯一使用过此功能的时间是使用numpy/pandas。例如,使用.isin() dataframe方法

他们在文档中显示了这个基本示例

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

但是,如果您不希望所有行都不在 [0,2]中怎么办?

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False

The only time I’ve ever used this in practice is with numpy/pandas. For example, with the .isin() dataframe method.

In the docs they show this basic example

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

But what if instead you wanted all the rows not in [0, 2]?

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False

回答 5

我正在解决这个leetcode问题,遇到了一个叫Zitao Wang的用户,这个漂亮的解决方案

问题是这样的:对于给定数组中的每个元素,在不使用除法和O(n)时间的情况下找到所有剩余数字的乘积

标准解决方案是:

Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
        and then multiplying them for the final answer 

他的解决方案只利用了一个for循环。他使用实时计算左乘积和右乘积~

def productExceptSelf(self, nums):
    res = [1]*len(nums)
    lprod = 1
    rprod = 1
    for i in range(len(nums)):
        res[i] *= lprod
        lprod *= nums[i]
        res[~i] *= rprod
        rprod *= nums[~i]
    return res

I was solving this leetcode problem and I came across this beautiful solution by a user named Zitao Wang.

The problem goes like this for each element in the given array find the product of all the remaining numbers without making use of divison and in O(n) time

The standard solution is:

Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
        and then multiplying them for the final answer 

His solution uses only one for loop by making use of. He computes the left product and right product on the fly using ~

def productExceptSelf(self, nums):
    res = [1]*len(nums)
    lprod = 1
    rprod = 1
    for i in range(len(nums)):
        res[i] *= lprod
        lprod *= nums[i]
        res[~i] *= rprod
        rprod *= nums[~i]
    return res

回答 6

这是次要用法,是波浪线…

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio)) 
    return data.loc[~in_test_set], data.loc[in_test_set]

上面的代码来自“动手学习机器”

您使用代字号(〜符号)替代-符号索引标记

就像您使用减号一样-用于整数索引

例如)

array = [1,2,3,4,5,6]
print(array[-1])

与…相同

print(array[~1])

This is minor usage is tilde…

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio)) 
    return data.loc[~in_test_set], data.loc[in_test_set]

the code above is from “Hands On Machine Learning”

you use tilde (~ sign) as alternative to – sign index marker

just like you use minus – is for integer index

ex)

array = [1,2,3,4,5,6]
print(array[-1])

is the samething as

print(array[~1])


重写Python的“ in”运算符?

问题:重写Python的“ in”运算符?

如果要在Python中创建自己的类,则应定义什么函数,以便允许使用“ in”运算符,例如

class MyClass(object):
    ...

m = MyClass()

if 54 in m:
    ...

If I am creating my own class in Python, what function should I define so as to allow the use of the ‘in’ operator, e.g.

class MyClass(object):
    ...

m = MyClass()

if 54 in m:
    ...

回答 0


回答 1

一个更完整的答案是:

class MyClass(object):

    def __init__(self):
        self.numbers = [1,2,3,4,54]

    def __contains__(self, key):
        return key in self.numbers

在这里,当问54是否在m中时,您将得到True:

>>> m = MyClass()
>>> 54 in m
True  

请参阅有关重载的文档__contains__

A more complete answer is:

class MyClass(object):

    def __init__(self):
        self.numbers = [1,2,3,4,54]

    def __contains__(self, key):
        return key in self.numbers

Here you would get True when asking if 54 was in m:

>>> m = MyClass()
>>> 54 in m
True  

See documentation on overloading __contains__.


回答 2

您可能还想看一下我用来创建特定于域的语言的中缀运算符覆盖框架:

http://code.activestate.com/recipes/384122/

You might also want to take a look at an infix operator override framework I was able to use to create a domain-specific language:

http://code.activestate.com/recipes/384122/


什么是“ 1 ..__ truediv__”?Python是否具有..(“点点”)表示法语法?

问题:什么是“ 1 ..__ truediv__”?Python是否具有..(“点点”)表示法语法?

最近,我遇到了一种语法,这种语法在我学习python时从未见过,在大多数教程中,这种..表示法看起来像这样:

f = 1..__truediv__ # or 1..__div__ for python 2

print(f(8)) # prints 0.125 

我发现它和(当然,它更长)完全一样:

f = lambda x: (1).__truediv__(x)
print(f(8)) # prints 0.125 or 1//8

但是我的问题是:

  • 它怎么做呢?
  • 这两个点实际上意味着什么?
  • 如何在更复杂的语句中使用它(如果可能)?

将来可能会为我节省很多代码行… :)

I recently came across a syntax I never seen before when I learned python nor in most tutorials, the .. notation, it looks something like this:

f = 1..__truediv__ # or 1..__div__ for python 2

print(f(8)) # prints 0.125 

I figured it was exactly the same as (except it’s longer, of course):

f = lambda x: (1).__truediv__(x)
print(f(8)) # prints 0.125 or 1//8

But my questions are:

  • How can it do that?
  • What does it actually mean with the two dots?
  • How can you use it in a more complex statement (if possible)?

This will probably save me many lines of code in the future…:)


回答 0

您所拥有的是一个float不带尾随零的文字,然后您可以访问的__truediv__方法。它本身不是运算符;第一个点是float值的一部分,第二个点是用于访问对象属性和方法的点运算符。

您可以通过执行以下操作达到相同的目的。

>>> f = 1.
>>> f
1.0
>>> f.__floordiv__
<method-wrapper '__floordiv__' of float object at 0x7f9fb4dc1a20>

另一个例子

>>> 1..__add__(2.)
3.0

在这里,我们将1.0加到2.0,显然得出3.0。

What you have is a float literal without the trailing zero, which you then access the __truediv__ method of. It’s not an operator in itself; the first dot is part of the float value, and the second is the dot operator to access the objects properties and methods.

You can reach the same point by doing the following.

>>> f = 1.
>>> f
1.0
>>> f.__floordiv__
<method-wrapper '__floordiv__' of float object at 0x7f9fb4dc1a20>

Another example

>>> 1..__add__(2.)
3.0

Here we add 1.0 to 2.0, which obviously yields 3.0.


回答 1

该问题已经得到足够的答案(即@Paul Rooney的答案),但也可以验证这些答案的正确性。

让我回顾一下现有的答案:这..不是一个语法元素!

您可以检查源代码如何“标记化”。这些标记表示代码的解释方式:

>>> from tokenize import tokenize
>>> from io import BytesIO

>>> s = "1..__truediv__"
>>> list(tokenize(BytesIO(s.encode('utf-8')).readline))
[...
 TokenInfo(type=2 (NUMBER), string='1.', start=(1, 0), end=(1, 2), line='1..__truediv__'),
 TokenInfo(type=53 (OP), string='.', start=(1, 2), end=(1, 3), line='1..__truediv__'),
 TokenInfo(type=1 (NAME), string='__truediv__', start=(1, 3), end=(1, 14), line='1..__truediv__'),
 ...]

因此,字符串1.被解释为数字,第二个.是OP(运算符,在这种情况下为“ get attribute”运算符),而则__truediv__是方法名称。因此,这只是访问__truediv__float 的方法1.0

查看生成的字节码的另一种方法是对其进行汇编。这实际上显示了执行某些代码时执行的指令: dis

>>> import dis

>>> def f():
...     return 1..__truediv__

>>> dis.dis(f)
  4           0 LOAD_CONST               1 (1.0)
              3 LOAD_ATTR                0 (__truediv__)
              6 RETURN_VALUE

基本上说的一样。它加载__truediv__常量的属性1.0


关于你的问题

以及如何在更复杂的语句中使用它(如果可能)?

即使您可能永远也不要这样写代码,只是因为不清楚代码在做什么。因此,请不要在更复杂的语句中使用它。我什至会走得更远,以至于您不应该在如此“简单”的语句中使用它,至少您应该使用括号将指令分开:

f = (1.).__truediv__

这肯定会更具可读性-但类似于:

from functools import partial
from operator import truediv
f = partial(truediv, 1.0)

会更好!

使用的方法partial还保留了python的数据模型(该1..__truediv__方法没有!),可以通过以下小片段进行演示:

>>> f1 = 1..__truediv__
>>> f2 = partial(truediv, 1.)

>>> f2(1+2j)  # reciprocal of complex number - works
(0.2-0.4j)
>>> f2('a')   # reciprocal of string should raise an exception
TypeError: unsupported operand type(s) for /: 'float' and 'str'

>>> f1(1+2j)  # reciprocal of complex number - works but gives an unexpected result
NotImplemented
>>> f1('a')   # reciprocal of string should raise an exception but it doesn't
NotImplemented

这是因为1. / (1+2j)不是由- float.__truediv__而是通过complex.__rtruediv__operator.truediv进行评估的,请确保在正常操作返回时调用了反向操作,NotImplemented__truediv__直接操作时没有这些后备。这种“预期行为”的丧失是您(通常)不应直接使用魔术方法的主要原因。

The question is already sufficiently answered (i.e. @Paul Rooneys answer) but it’s also possible to verify the correctness of these answers.

Let me recap the existing answers: The .. is not a single syntax element!

You can check how the source code is “tokenized”. These tokens represent how the code is interpreted:

>>> from tokenize import tokenize
>>> from io import BytesIO

>>> s = "1..__truediv__"
>>> list(tokenize(BytesIO(s.encode('utf-8')).readline))
[...
 TokenInfo(type=2 (NUMBER), string='1.', start=(1, 0), end=(1, 2), line='1..__truediv__'),
 TokenInfo(type=53 (OP), string='.', start=(1, 2), end=(1, 3), line='1..__truediv__'),
 TokenInfo(type=1 (NAME), string='__truediv__', start=(1, 3), end=(1, 14), line='1..__truediv__'),
 ...]

So the string 1. is interpreted as number, the second . is an OP (an operator, in this case the “get attribute” operator) and the __truediv__ is the method name. So this is just accessing the __truediv__ method of the float 1.0.

Another way of viewing the generated bytecode is to disassemble it. This actually shows the instructions that are performed when some code is executed:

>>> import dis

>>> def f():
...     return 1..__truediv__

>>> dis.dis(f)
  4           0 LOAD_CONST               1 (1.0)
              3 LOAD_ATTR                0 (__truediv__)
              6 RETURN_VALUE

Which basically says the same. It loads the attribute __truediv__ of the constant 1.0.


Regarding your question

And how can you use it in a more complex statement (if possible)?

Even though it’s possible you should never write code like that, simply because it’s unclear what the code is doing. So please don’t use it in more complex statements. I would even go so far that you shouldn’t use it in so “simple” statements, at least you should use parenthesis to separate the instructions:

f = (1.).__truediv__

this would be definetly more readable – but something along the lines of:

from functools import partial
from operator import truediv
f = partial(truediv, 1.0)

would be even better!

The approach using partial also preserves python’s data model (the 1..__truediv__ approach does not!) which can be demonstrated by this little snippet:

>>> f1 = 1..__truediv__
>>> f2 = partial(truediv, 1.)

>>> f2(1+2j)  # reciprocal of complex number - works
(0.2-0.4j)
>>> f2('a')   # reciprocal of string should raise an exception
TypeError: unsupported operand type(s) for /: 'float' and 'str'

>>> f1(1+2j)  # reciprocal of complex number - works but gives an unexpected result
NotImplemented
>>> f1('a')   # reciprocal of string should raise an exception but it doesn't
NotImplemented

This is because 1. / (1+2j) is not evaluated by float.__truediv__ but with complex.__rtruediv__operator.truediv makes sure the reverse operation is called when the normal operation returns NotImplemented but you don’t have these fallbacks when you operate on __truediv__ directly. This loss of “expected behaviour” is the main reason why you (normally) shouldn’t use magic methods directly.


回答 2

首先,两个点可能有点尴尬:

f = 1..__truediv__ # or 1..__div__ for python 2

但这与写作相同:

f = 1.0.__truediv__ # or 1.0.__div__ for python 2

因为float文字可以用三种形式编写:

normal_float = 1.0
short_float = 1.  # == 1.0
prefixed_float = .1  # == 0.1

Two dots together may be a little awkward at first:

f = 1..__truediv__ # or 1..__div__ for python 2

But it is the same as writing:

f = 1.0.__truediv__ # or 1.0.__div__ for python 2

Because float literals can be written in three forms:

normal_float = 1.0
short_float = 1.  # == 1.0
prefixed_float = .1  # == 0.1

回答 3

什么f = 1..__truediv__

f是在值为1的float上绑定的特殊方法。特别,

1.0 / x

在Python 3中,调用:

(1.0).__truediv__(x)

证据:

class Float(float):
    def __truediv__(self, other):
        print('__truediv__ called')
        return super(Float, self).__truediv__(other)

和:

>>> one = Float(1)
>>> one/2
__truediv__ called
0.5

如果这样做:

f = one.__truediv__

我们保留绑定到该绑定方法的名称

>>> f(2)
__truediv__ called
0.5
>>> f(3)
__truediv__ called
0.3333333333333333

如果我们在一个紧密的循环中执行该点分查找,则可以节省一些时间。

解析抽象语法树(AST)

我们可以看到,解析表达式的AST可以告诉我们,我们__truediv__在浮点数上获取属性1.0

>>> import ast
>>> ast.dump(ast.parse('1..__truediv__').body[0])
"Expr(value=Attribute(value=Num(n=1.0), attr='__truediv__', ctx=Load()))"

您可以从以下获得相同的结果函数:

f = float(1).__truediv__

要么

f = (1.0).__truediv__

扣除

我们也可以通过扣除到达那里。

让我们建立它。

1本身是一个int

>>> 1
1
>>> type(1)
<type 'int'>

1,之后是句点:

>>> 1.
1.0
>>> type(1.)
<type 'float'>

下一个点本身就是SyntaxError,但它会在float实例上开始点分查找:

>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>

没有人提到这一点 -这现在是浮动的“绑定方法”1.0

>>> f = 1..__truediv__
>>> f
<method-wrapper '__truediv__' of float object at 0x127F3CD8>
>>> f(2)
0.5
>>> f(3)
0.33333333333333331

我们可以更容易地完成相同的功能:

>>> def divide_one_by(x):
...     return 1.0/x
...     
>>> divide_one_by(2)
0.5
>>> divide_one_by(3)
0.33333333333333331

性能

divide_one_by函数的缺点是它需要另一个Python堆栈框架,这使其比绑定方法要慢一些:

>>> def f_1():
...     for x in range(1, 11):
...         f(x)
...         
>>> def f_2():
...     for x in range(1, 11):
...         divide_one_by(x)
...         
>>> timeit.repeat(f_1)
[2.5495760687176485, 2.5585621018805469, 2.5411816588331888]
>>> timeit.repeat(f_2)
[3.479687248616699, 3.46196088706062, 3.473726342237768]

当然,如果您仅可以使用普通文字,那就更快了:

>>> def f_3():
...     for x in range(1, 11):
...         1.0/x
...         
>>> timeit.repeat(f_3)
[2.1224895628296281, 2.1219930218637728, 2.1280188256941983]

What is f = 1..__truediv__?

f is a bound special method on a float with a value of one. Specifically,

1.0 / x

in Python 3, invokes:

(1.0).__truediv__(x)

Evidence:

class Float(float):
    def __truediv__(self, other):
        print('__truediv__ called')
        return super(Float, self).__truediv__(other)

and:

>>> one = Float(1)
>>> one/2
__truediv__ called
0.5

If we do:

f = one.__truediv__

We retain a name bound to that bound method

>>> f(2)
__truediv__ called
0.5
>>> f(3)
__truediv__ called
0.3333333333333333

If we were doing that dotted lookup in a tight loop, this could save a little time.

Parsing the Abstract Syntax Tree (AST)

We can see that parsing the AST for the expression tells us that we are getting the __truediv__ attribute on the floating point number, 1.0:

>>> import ast
>>> ast.dump(ast.parse('1..__truediv__').body[0])
"Expr(value=Attribute(value=Num(n=1.0), attr='__truediv__', ctx=Load()))"

You could get the same resulting function from:

f = float(1).__truediv__

Or

f = (1.0).__truediv__

Deduction

We can also get there by deduction.

Let’s build it up.

1 by itself is an int:

>>> 1
1
>>> type(1)
<type 'int'>

1 with a period after it is a float:

>>> 1.
1.0
>>> type(1.)
<type 'float'>

The next dot by itself would be a SyntaxError, but it begins a dotted lookup on the instance of the float:

>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>

No one else has mentioned this – This is now a “bound method” on the float, 1.0:

>>> f = 1..__truediv__
>>> f
<method-wrapper '__truediv__' of float object at 0x127F3CD8>
>>> f(2)
0.5
>>> f(3)
0.33333333333333331

We could accomplish the same function much more readably:

>>> def divide_one_by(x):
...     return 1.0/x
...     
>>> divide_one_by(2)
0.5
>>> divide_one_by(3)
0.33333333333333331

Performance

The downside of the divide_one_by function is that it requires another Python stack frame, making it somewhat slower than the bound method:

>>> def f_1():
...     for x in range(1, 11):
...         f(x)
...         
>>> def f_2():
...     for x in range(1, 11):
...         divide_one_by(x)
...         
>>> timeit.repeat(f_1)
[2.5495760687176485, 2.5585621018805469, 2.5411816588331888]
>>> timeit.repeat(f_2)
[3.479687248616699, 3.46196088706062, 3.473726342237768]

Of course, if you can just use plain literals, that’s even faster:

>>> def f_3():
...     for x in range(1, 11):
...         1.0/x
...         
>>> timeit.repeat(f_3)
[2.1224895628296281, 2.1219930218637728, 2.1280188256941983]

Python!=操作与“不是”

问题:Python!=操作与“不是”

在对此问题的评论中,我看到了一条建议使用的声明

result is not None

result != None

我想知道两者之间的区别是什么,为什么要推荐一个而不是另一个?

In a comment on this question, I saw a statement that recommended using

result is not None

vs

result != None

I was wondering what the difference is, and why one might be recommended over the other?


回答 0

==是一项平等测试。它检查右侧和左侧是否是相等的对象(根据它们__eq____cmp__方法)。

is身份测试。它检查右侧和左侧是否是同一对象。没有方法调用完成,对象不能影响is操作。

您可以将is(和is not)用于单例,例如None,您不关心可能假装为的对象,None或者想要与之进行比较时要防止对象破裂的地方None

== is an equality test. It checks whether the right hand side and the left hand side are equal objects (according to their __eq__ or __cmp__ methods.)

is is an identity test. It checks whether the right hand side and the left hand side are the very same object. No methodcalls are done, objects can’t influence the is operation.

You use is (and is not) for singletons, like None, where you don’t care about objects that might want to pretend to be None or where you want to protect against objects breaking when being compared against None.


回答 1

首先,让我再谈几个问题。如果您只是想回答问题,请向下滚动到“回答问题”。

定义

对象标识:创建对象时,可以将其分配给变量。然后,您也可以将其分配给另一个变量。还有一个。

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

在这种情况下,cancelclose,和dismiss都指的是同一个对象在内存中。您仅创建了一个Button对象,并且所有三个变量都引用了该对象。我们说cancelclosedismiss都指同一对象; 也就是说,它们只引用一个对象。

对象相等性:比较两个对象时,通常不必关心它是否指向内存中完全相同的对象。使用对象相等性,您可以定义自己的规则以比较两个对象。当您写作时if a == b:,您实际上是在说if a.__eq__(b):。这使您可以定义一个__eq__方法,a以便可以使用自己的比较逻辑。

平等比较的理由

理由:两个对象具有完全相同的数据,但不完全相同。(它们不是内存中的同一对象。) 示例:字符串

>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True

注意:我在这里使用unicode字符串,因为Python足够聪明,可以重用常规字符串,而无需在内存中创建新的字符串。

在这里,我有两个unicode字符串ab。它们具有完全相同的内容,但是在内存中它们不是相同的对象。但是,当我们比较它们时,我们希望它们比较相等。这里发生的是unicode对象已实现该__eq__方法。

class unicode(object):
    # ...

    def __eq__(self, other):
        if len(self) != len(other):
            return False

        for i, j in zip(self, other):
            if i != j:
                return False

        return True

注意:__eq__on unicode的实现肯定比这更有效。

原理:两个对象具有不同的数据,但是如果某些关键数据相同,则将它们视为同一对象。 示例:大多数类型的模型数据

>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True

在这里,我有两台戴尔显示器,ab。它们具有相同的品牌和型号。但是,它们在内存中既没有相同的数据也没有相同的对象。但是,当我们比较它们时,我们希望它们比较相等。这里发生的事情是Monitor对象实现了该__eq__方法。

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model

回答你的问题

比较时None,请始终使用is not。在Python中,没有一个是单例的-内存中只有一个实例。

通过比较身份,可以非常快速地执行此操作。Python检查您所引用的对象是否与全局None对象具有相同的内存地址-两个数字的非常非常快速的比较。

通过比较相等性,Python必须检查您的对象是否具有__eq__方法。如果不是,它将检查每个超类以寻找一种__eq__方法。如果找到一个,Python会调用它。如果该__eq__方法很慢并且在注意到另一个对象为时不立即返回,则尤其糟糕None

你没有实现__eq__吗?然后,Python可能会找到该__eq__方法object并改用该方法-无论如何,它只会检查对象的身份。

在Python中比较大多数其他内容时,您将使用!=

First, let me go over a few terms. If you just want your question answered, scroll down to “Answering your question”.

Definitions

Object identity: When you create an object, you can assign it to a variable. You can then also assign it to another variable. And another.

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

In this case, cancel, close, and dismiss all refer to the same object in memory. You only created one Button object, and all three variables refer to this one object. We say that cancel, close, and dismiss all refer to identical objects; that is, they refer to one single object.

Object equality: When you compare two objects, you usually don’t care that it refers to the exact same object in memory. With object equality, you can define your own rules for how two objects compare. When you write if a == b:, you are essentially saying if a.__eq__(b):. This lets you define a __eq__ method on a so that you can use your own comparison logic.

Rationale for equality comparisons

Rationale: Two objects have the exact same data, but are not identical. (They are not the same object in memory.) Example: Strings

>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True

Note: I use unicode strings here because Python is smart enough to reuse regular strings without creating new ones in memory.

Here, I have two unicode strings, a and b. They have the exact same content, but they are not the same object in memory. However, when we compare them, we want them to compare equal. What’s happening here is that the unicode object has implemented the __eq__ method.

class unicode(object):
    # ...

    def __eq__(self, other):
        if len(self) != len(other):
            return False

        for i, j in zip(self, other):
            if i != j:
                return False

        return True

Note: __eq__ on unicode is definitely implemented more efficiently than this.

Rationale: Two objects have different data, but are considered the same object if some key data is the same. Example: Most types of model data

>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True

Here, I have two Dell monitors, a and b. They have the same make and model. However, they neither have the same data nor are the same object in memory. However, when we compare them, we want them to compare equal. What’s happening here is that the Monitor object implemented the __eq__ method.

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model

Answering your question

When comparing to None, always use is not. None is a singleton in Python – there is only ever one instance of it in memory.

By comparing identity, this can be performed very quickly. Python checks whether the object you’re referring to has the same memory address as the global None object – a very, very fast comparison of two numbers.

By comparing equality, Python has to look up whether your object has an __eq__ method. If it does not, it examines each superclass looking for an __eq__ method. If it finds one, Python calls it. This is especially bad if the __eq__ method is slow and doesn’t immediately return when it notices that the other object is None.

Did you not implement __eq__? Then Python will probably find the __eq__ method on object and use that instead – which just checks for object identity anyway.

When comparing most other things in Python, you will be using !=.


回答 2

考虑以下:

class Bad(object):
    def __eq__(self, other):
        return True

c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)

Consider the following:

class Bad(object):
    def __eq__(self, other):
        return True

c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)

回答 3

None是单例,因此身份比较将始终有效,而对象可以通过伪造相等比较.__eq__()

None is a singleton, therefore identity comparison will always work, whereas an object can fake the equality comparison via .__eq__().


回答 4

>>>()是()
真正
>>> 1是1
真正
>>>(1,)==(1,)
真正
>>>(1,)是(1,)
假
>>> a =(1,)
>>> b = a
>>> a是b
真正

有些对象是单例,因此is与它们等效==。大多数不是。

>>> () is ()
True
>>> 1 is 1
True
>>> (1,) == (1,)
True
>>> (1,) is (1,)
False
>>> a = (1,)
>>> b = a
>>> a is b
True

Some objects are singletons, and thus is with them is equivalent to ==. Most are not.


Python中%的结果是什么?

问题:Python中%的结果是什么?

什么是%在计算?我似乎无法弄清楚它的作用。

例如,它算出计算的百分比4 % 2吗:显然等于0。如何?

What does the % in a calculation? I can’t seem to work out what it does.

Does it work out a percent of the calculation for example: 4 % 2 is apparently equal to 0. How?


回答 0

%(模)运算符从第一个参数除以第二个参数得出余数。首先将数字参数转换为通用类型。零权限参数引发ZeroDivisionError异常。参数可以是浮点数,例如3.14%0.7等于0.34(因为3.14等于4 * 0.7 + 0.34。)模运算符始终产生与第二个操作数具有相同符号的结果(或为零);结果的绝对值严格小于第二个操作数的绝对值[2]。

取自http://docs.python.org/reference/expressions.html

例1: 6%2计算结果为0,如果将6除以2(3次),则没有余数。

实施例27%2评估为1因为有一个的其余部分1时7由2(3次)划分。

综上所述,它返回除法运算的余数,或者0没有余数。因此,6%2意味着找到6的余数除以2。

The % (modulo) operator yields the remainder from the division of the first argument by the second. The numeric arguments are first converted to a common type. A zero right argument raises the ZeroDivisionError exception. The arguments may be floating point numbers, e.g., 3.14%0.7 equals 0.34 (since 3.14 equals 4*0.7 + 0.34.) The modulo operator always yields a result with the same sign as its second operand (or zero); the absolute value of the result is strictly smaller than the absolute value of the second operand [2].

Taken from http://docs.python.org/reference/expressions.html

Example 1: 6%2 evaluates to 0 because there’s no remainder if 6 is divided by 2 ( 3 times ).

Example 2: 7%2 evaluates to 1 because there’s a remainder of 1 when 7 is divided by 2 ( 3 times ).

So to summarise that, it returns the remainder of a division operation, or 0 if there is no remainder. So 6%2 means find the remainder of 6 divided by 2.


回答 1

在某种程度上,主题%还用于字符串格式化操作,例如%=将值替换为字符串:

>>> x = 'abc_%(key)s_'
>>> x %= {'key':'value'}
>>> x 
'abc_value_'

同样,偏离主题,但它似乎是一个小记录功能,它花了一段时间来跟踪,并且我认为这是有关Python的模数计算的此SO页面高度行列。

Somewhat off topic, the % is also used in string formatting operations like %= to substitute values into a string:

>>> x = 'abc_%(key)s_'
>>> x %= {'key':'value'}
>>> x 
'abc_value_'

Again, off topic, but it seems to be a little documented feature which took me awhile to track down, and I thought it was related to Pythons modulo calculation for which this SO page ranks highly.


回答 2

像这样的表达式x % y求余数x ÷ y-从技术上讲,它是“模数”而不是“提醒”,因此,如果与其他语言%(余数运算符)进行比较,结果可能会有所不同。有一些细微的差异(如果您对实际的结果感兴趣,另请参见“为什么要使用Python的整数分区”)。

优先级与运算符/(除法)和*(乘法)相同。

>>> 9 / 2
4
>>> 9 % 2
1
  • 9除以2等于4。
  • 4乘2是8
  • 9减去8为1-余数。

Python陷阱:取决于您使用的Python版本,%它也是(不建议使用的)字符串插值运算符,因此请注意您是否来自使用自动类型转换的语言(如PHP或JS),在其中使用'12' % 2 + 3合法的表达式: Python,TypeError: not all arguments converted during string formatting这可能会使您感到困惑。

[Python 3更新]

用户n00p评论:

9/2在Python中为4.5。您必须像这样进行整数除法:9 // 2如果要python告诉您除法(4)之后还剩下多少个整个对象。

确切地说,整数除法曾经是Python 2中的默认设置(请注意,这个答案比我的男孩年龄大,这个男孩已经在学校学习,当时2.x是主流):

$ python2.7
Python 2.7.10 (default, Oct  6 2017, 22:29:07)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4
>>> 9 // 2
4
>>> 9 % 2
1

在现代Python中,9 / 2结果4.5确实是:

$ python3.6
Python 3.6.1 (default, Apr 27 2017, 00:15:59)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4.5
>>> 9 // 2
4
>>> 9 % 2
1

[更新]

用户dahiya_boy在评论会话中询问:

问:能否请您解释原因-11 % 5 = 4-dahiya_boy

这很奇怪吧?如果您使用JavaScript尝试此操作:

> -11 % 5
-1

这是因为在JavaScript %中,它是“余数”运算符,而在Python中,它是“模数”(时钟数学)运算符。

您可以直接从GvR获得解释


编辑-dahiya_boy

在Java和iOS中,-11 % 5 = -1而在python和ruby中-11 % 5 = 4

Paulo Scardine解释了一半的原因,下面是其余的解释

在Java和iOS,%使剩余这意味着,如果你把11%的5 给出了Quotient = 2 and remainder = 1-11%5给出Quotient = -2 and remainder = -1

快速iOS中的示例代码。

但是当我们在python中谈论它时,它给出了时钟模数。及其使用以下公式的工作

mod(a,n) = a - {n * Floor(a/n)}

那就意味着

mod(11,5) = 11 - {5 * Floor(11/5)} => 11 - {5 * 2}

所以, mod(11,5) = 1

mod(-11,5) = -11 - 5 * Floor(11/5) => -11 - {5 * (-3)}

所以, mod(-11,5) = 4

python 3.0中的示例代码。


为什么Python的整数分区

今天(再次)被要求解释为什么Python中的整数除法返回结果的底数,而不是像C一样向零截断。

对于正数,不足为奇:

>>> 5//2
2

但是,如果其中一个操作数是负数,则结果是下限的,即从零舍入(朝负无穷大):

>>> -5//2
-3
>>> 5//-2
-3

这打扰了一些人,但是有一个很好的数学理由。整数除法运算(//)及其兄弟运算,取模运算(%)在一起并满足良好的数学关系(所有变量均为整数):

a/b = q with remainder r

这样

b*q + r = a and 0 <= r < b

(假设a和b> = 0)。

如果要使关系扩展为负a(使b为正),则有两种选择:如果将q截断为零,则r将变为负,因此不变量变为0 <= abs(r)<否则,您可以将q朝负无穷大移动,并且不变保持0 <= r <b。[更新:解决了此问题]

在数学数论中,数学家总是喜欢后一种选择(例如参见Wikipedia)。对于Python,我做出了相同的选择,因为模运算有一些有趣的应用,其中a的符号没有意义。考虑采用POSIX时间戳(自1970年初以来的秒数),并将其转换为一天中的时间。由于一天中有24 * 3600 = 86400秒,因此该计算仅为t%86400。但是,如果我们使用负数来表示1970年之前的时间,则“截断为零”规则将得出毫无意义的结果!使用下限规则,一切正常。

我想到的其他应用程序是计算机图形学中像素位置的计算。我敢肯定还有更多。

顺便说一下,对于负数b,所有事物都翻转了,并且不变式变为:

0 >= r > b.

那么C为什么不这样做呢?在设计C时,硬件可能没有这样做。而且硬件可能不会这样做,因为在最旧的硬件中,负数表示为“符号+幅度”,而不是如今使用的二进制补码表示法(至少对于整数)。我的第一台计算机是Control Data大型机,它使用整数和浮点数的补码。60的模式表示负零!

蒂姆·彼得斯(Tim Peters)知道所有Python的浮点骨架都埋在哪里,对我希望将这些规则扩展到浮点模数表示担忧。他可能是对的。当x是非常小的负数时,truncate-towards-negative-infinity规则会导致x%1.0的精度损失。但这还不足以打破整数模,并且//与之紧密耦合。

PS。请注意,我使用的是//而不是/-这是Python 3语法,并且在Python 2中也允许强调您知道自己正在调用整数除法。Python 2中的/运算符是模棱两可的,因为它对两个整数操作数返回的结果与对int和一个或两个或多个浮点数的返回不同。但这是一个完全独立的故事。参见PEP 238。

由Guido van Rossum发表于9:49 AM

An expression like x % y evaluates to the remainder of x ÷ y – well, technically it is “modulus” instead of “reminder” so results may be different if you are comparing with other languages where % is the remainder operator. There are some subtle differences (if you are interested in the practical consequences see also “Why Python’s Integer Division Floors” bellow).

Precedence is the same as operators / (division) and * (multiplication).

>>> 9 / 2
4
>>> 9 % 2
1
  • 9 divided by 2 is equal to 4.
  • 4 times 2 is 8
  • 9 minus 8 is 1 – the remainder.

Python gotcha: depending on the Python version you are using, % is also the (deprecated) string interpolation operator, so watch out if you are coming from a language with automatic type casting (like PHP or JS) where an expression like '12' % 2 + 3 is legal: in Python it will result in TypeError: not all arguments converted during string formatting which probably will be pretty confusing for you.

[update for Python 3]

User n00p comments:

9/2 is 4.5 in python. You have to do integer division like so: 9//2 if you want python to tell you how many whole objects is left after division(4).

To be precise, integer division used to be the default in Python 2 (mind you, this answer is older than my boy who is already in school and at the time 2.x were mainstream):

$ python2.7
Python 2.7.10 (default, Oct  6 2017, 22:29:07)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4
>>> 9 // 2
4
>>> 9 % 2
1

In modern Python 9 / 2 results 4.5 indeed:

$ python3.6
Python 3.6.1 (default, Apr 27 2017, 00:15:59)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4.5
>>> 9 // 2
4
>>> 9 % 2
1

[update]

User dahiya_boy asked in the comment session:

Q. Can you please explain why -11 % 5 = 4 – dahiya_boy

This is weird, right? If you try this in JavaScript:

> -11 % 5
-1

This is because in JavaScript % is the “remainder” operator while in Python it is the “modulus” (clock math) operator.

You can get the explanation directly from GvR:


Edit – dahiya_boy

In Java and iOS -11 % 5 = -1 whereas in python and ruby -11 % 5 = 4.

Well half of the reason is explained by the Paulo Scardine, and rest of the explanation is below here

In Java and iOS, % gives the remainder that means if you divide 11 % 5 gives Quotient = 2 and remainder = 1 and -11 % 5 gives Quotient = -2 and remainder = -1.

Sample code in swift iOS.

But when we talk about in python its gives clock modulus. And its work with below formula

mod(a,n) = a - {n * Floor(a/n)}

Thats means,

mod(11,5) = 11 - {5 * Floor(11/5)} => 11 - {5 * 2}

So, mod(11,5) = 1

And

mod(-11,5) = -11 - 5 * Floor(-11/5) => -11 - {5 * (-3)}

So, mod(-11,5) = 4

Sample code in python 3.0.


Why Python’s Integer Division Floors

I was asked (again) today to explain why integer division in Python returns the floor of the result instead of truncating towards zero like C.

For positive numbers, there’s no surprise:

>>> 5//2
2

But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity):

>>> -5//2
-3
>>> 5//-2
-3

This disturbs some people, but there is a good mathematical reason. The integer division operation (//) and its sibling, the modulo operation (%), go together and satisfy a nice mathematical relationship (all variables are integers):

a/b = q with remainder r

such that

b*q + r = a and 0 <= r < b

(assuming a and b are >= 0).

If you want the relationship to extend for negative a (keeping b positive), you have two choices: if you truncate q towards zero, r will become negative, so that the invariant changes to 0 <= abs(r) < otherwise, you can floor q towards negative infinity, and the invariant remains 0 <= r < b. [update: fixed this para]

In mathematical number theory, mathematicians always prefer the latter choice (see e.g. Wikipedia). For Python, I made the same choice because there are some interesting applications of the modulo operation where the sign of a is uninteresting. Consider taking a POSIX timestamp (seconds since the start of 1970) and turning it into the time of day. Since there are 24*3600 = 86400 seconds in a day, this calculation is simply t % 86400. But if we were to express times before 1970 using negative numbers, the “truncate towards zero” rule would give a meaningless result! Using the floor rule it all works out fine.

Other applications I’ve thought of are computations of pixel positions in computer graphics. I’m sure there are more.

For negative b, by the way, everything just flips, and the invariant becomes:

0 >= r > b.

So why doesn’t C do it this way? Probably the hardware didn’t do this at the time C was designed. And the hardware probably didn’t do it this way because in the oldest hardware, negative numbers were represented as “sign + magnitude” rather than the two’s complement representation used these days (at least for integers). My first computer was a Control Data mainframe and it used one’s complement for integers as well as floats. A pattern of 60 ones meant negative zero!

Tim Peters, who knows where all Python’s floating point skeletons are buried, has expressed some worry about my desire to extend these rules to floating point modulo. He’s probably right; the truncate-towards-negative-infinity rule can cause precision loss for x%1.0 when x is a very small negative number. But that’s not enough for me to break integer modulo, and // is tightly coupled to that.

PS. Note that I am using // instead of / — this is Python 3 syntax, and also allowed in Python 2 to emphasize that you know you are invoking integer division. The / operator in Python 2 is ambiguous, since it returns a different result for two integer operands than for an int and a float or two floats. But that’s a totally separate story; see PEP 238.

Posted by Guido van Rossum at 9:49 AM


回答 3

模数是一种数学运算,有时也称为“时钟算术”。我发现将其简单描述为剩余部分会产生误导和混乱,因为它掩盖了它在计算机科学中被大量使用的真正原因。它实际上是用于环绕循环的。

想想时钟:假设您以“军事”时间查看时钟,该时间范围为0:00-23.59。现在,如果您希望每天午夜发生一些事情,那么您希望当前时间mod 24为零:

如果(小时%24 == 0):

您可以想到历史中的所有小时都围绕24小时一圈地循环,并且一天中的当前小时是无限长的mod24。这是一个比余数更深刻的概念,这是一种数学方法处理周期,这在计算机科学中非常重要。它也用于环绕数组,允许您增加索引并使用模数在到达数组末尾后返回到开头。

The modulus is a mathematical operation, sometimes described as “clock arithmetic.” I find that describing it as simply a remainder is misleading and confusing because it masks the real reason it is used so much in computer science. It really is used to wrap around cycles.

Think of a clock: Suppose you look at a clock in “military” time, where the range of times goes from 0:00 – 23.59. Now if you wanted something to happen every day at midnight, you would want the current time mod 24 to be zero:

if (hour % 24 == 0):

You can think of all hours in history wrapping around a circle of 24 hours over and over and the current hour of the day is that infinitely long number mod 24. It is a much more profound concept than just a remainder, it is a mathematical way to deal with cycles and it is very important in computer science. It is also used to wrap around arrays, allowing you to increase the index and use the modulus to wrap back to the beginning after you reach the end of the array.


回答 4

Python-基本运算符
http://www.tutorialspoint.com/python/python_basic_operators.htm

模量-将左操作数除以右操作数并返回余数

a = 10和b = 20

b%a = 0

Python – Basic Operators
http://www.tutorialspoint.com/python/python_basic_operators.htm

Modulus – Divides left hand operand by right hand operand and returns remainder

a = 10 and b = 20

b % a = 0


回答 5

在大多数语言中,%用于模数。Python也不exceptions。

In most languages % is used for modulus. Python is no exception.


回答 6

%Modulo运算符也可以用于打印字符串(就像在C中一样),如Google https://developers.google.com/edu/python/strings上定义的那样。

      # % operator
  text = "%d little pigs come out or I'll %s and %s and %s" % (3, 'huff', 'puff', 'blow down')

这似乎有点题外话,但肯定会有所帮助。

% Modulo operator can be also used for printing strings (Just like in C) as defined on Google https://developers.google.com/edu/python/strings.

      # % operator
  text = "%d little pigs come out or I'll %s and %s and %s" % (3, 'huff', 'puff', 'blow down')

This seems to bit off topic but It will certainly help someone.


回答 7

x % y计算除法的余数x除以y其中的商是一个整数。其余的符号为y


在Python 3上计算得出6.75; 这是因为这样/做是真正的除法,而不是Python 2上的整数除法(默认情况下)(默认情况下)。在Python 2上1 / 4,由于结果舍入为0。

整数除法也可以在Python 3上使用//运算符完成,因此要得到7,可以执行:

3 + 2 + 1 - 5 + 4 % 2 - 1 // 4 + 6

此外,只需添加以下行,即可在Python 2上获得Python样式划分

from __future__ import division

作为每个源文件中的第一条源代码行。

x % y calculates the remainder of the division x divided by y where the quotient is an integer. The remainder has the sign of y.


On Python 3 the calculation yields 6.75; this is because the / does a true division, not integer division like (by default) on Python 2. On Python 2 1 / 4 gives 0, as the result is rounded down.

The integer division can be done on Python 3 too, with // operator, thus to get the 7 as a result, you can execute:

3 + 2 + 1 - 5 + 4 % 2 - 1 // 4 + 6

Also, you can get the Python style division on Python 2, by just adding the line

from __future__ import division

as the first source code line in each source file.


回答 8

模运算符,通常用于整数的余数除法,但在Python中可用于浮点数。

http://docs.python.org/reference/expressions.html

%(模)运算符从第一个参数除以第二个参数得出余数。首先将数字参数转换为通用类型。零权限参数引发ZeroDivisionError异常。参数可以是浮点数,例如3.14%0.7等于0.34(因为3.14等于4 * 0.7 + 0.34。)模运算符始终产生与第二个操作数具有相同符号的结果(或为零);结果的绝对值严格小于第二个操作数的绝对值[2]。

Modulus operator, it is used for remainder division on integers, typically, but in Python can be used for floating point numbers.

http://docs.python.org/reference/expressions.html

The % (modulo) operator yields the remainder from the division of the first argument by the second. The numeric arguments are first converted to a common type. A zero right argument raises the ZeroDivisionError exception. The arguments may be floating point numbers, e.g., 3.14%0.7 equals 0.34 (since 3.14 equals 4*0.7 + 0.34.) The modulo operator always yields a result with the same sign as its second operand (or zero); the absolute value of the result is strictly smaller than the absolute value of the second operand [2].


回答 9

这是一个模运算,除了它是老式的C风格的字符串格式化运算符,而不是模运算。有关详细信息,请参见此处。您将在现有代码中看到很多这样的内容。

It’s a modulo operation, except when it’s an old-fashioned C-style string formatting operator, not a modulo operation. See here for details. You’ll see a lot of this in existing code.


回答 10

此外,还有一个有用的内置函数,称为divmod

divmod(a,b)

使用两个(非复数)数字作为参数,并在使用长除法时返回一对包含其商和余数的数字。

Also, there is a useful built-in function called divmod:

divmod(a, b)

Take two (non complex) numbers as arguments and return a pair of numbers consisting of their quotient and remainder when using long division.


回答 11

意识到

(3 +2 + 1 - 5) + (4 % 2) - (1/4) + 6

如果使用Python 3.4计算,即使带括号的结果也是6.75,而不是7。


而且’/’运算符也不是那么容易理解(python2.7):试试…

- 1/4

1 - 1/4

这里有点题外话,但是在评估上面的表达式时应该考虑:)

Be aware that

(3 +2 + 1 - 5) + (4 % 2) - (1/4) + 6

even with the brackets results in 6.75 instead of 7 if calculated in Python 3.4.


And the ‘/’ operator is not that easy to understand, too (python2.7): try…

- 1/4

1 - 1/4

This is a bit off-topic here, but should be considered when evaluating the above expression :)


回答 12

对于我来说,很难在线找到使用%的特定用例,例如,为什么做分数模除法或负模除法会得出答案呢?希望这有助于澄清如下问题:

模量部门:

模除法返回数学除法运算的余数。这样做如下:

假设我们的股息为5,除数为2,则以下除法运算将等于(等于x):

dividend = 5
divisor = 2

x = 5/2 
  1. 模量计算的第一步是进行整数除法:

    x_int = 5 // 2(Python中的整数除法使用双斜杠)

    x_int = 2

  2. 接下来,x_int的输出乘以除数:

    x_mult = x_int *除数x_mult = 4

  3. 最后,从x_mult中减去股息

    红利-x_mult = 1

  4. 模运算,因此返回1:

    5%2 = 1

申请将模数应用于分数

Example: 2 % 5 

当应用于分数时,模量的计算与上面相同;但是,重要的是要注意,当除数大于被除数时,整数除法将得出零值:

dividend = 2 
divisor = 5

整数除法得出0,而; 因此,当执行上面的步骤3时,将计算分红的值(减去零):

dividend - 0 = 2  —> 2 % 5 = 2 

申请将模数应用于负数

发生地板除法,其中整数除法的值四舍五入到最低整数值:

import math 

x = -1.1
math.floor(-1.1) = -2 

y = 1.1
math.floor = 1

因此,当您进行整数除法时,您可能会得到与预期不同的结果!

将以上步骤应用于以下除数和除数可以说明模量概念:

dividend: -5 
divisor: 2 

步骤1:应用整数除法

x_int = -5 // 2  = -3

步骤2:将整数除法的结果乘以除数

x_mult = x_int * 2 = -6

步骤3:从乘法变量中减去红利,请注意双负数。

dividend - x_mult = -5 -(-6) = 1

因此:

-5 % 2 = 1

It was hard for me to readily find specific use cases for the use of % online ,e.g. why does doing fractional modulus division or negative modulus division result in the answer that it does. Hope this helps clarify questions like this:

Modulus Division In General:

Modulus division returns the remainder of a mathematical division operation. It is does it as follows:

Say we have a dividend of 5 and divisor of 2, the following division operation would be (equated to x):

dividend = 5
divisor = 2

x = 5/2 
  1. The first step in the modulus calculation is to conduct integer division:

    x_int = 5 // 2 ( integer division in python uses double slash)

    x_int = 2

  2. Next, the output of x_int is multiplied by the divisor:

    x_mult = x_int * divisor x_mult = 4

  3. Lastly, the dividend is subtracted from the x_mult

    dividend – x_mult = 1

  4. The modulus operation ,therefore, returns 1:

    5 % 2 = 1

Application to apply the modulus to a fraction

Example: 2 % 5 

The calculation of the modulus when applied to a fraction is the same as above; however, it is important to note that the integer division will result in a value of zero when the divisor is larger than the dividend:

dividend = 2 
divisor = 5

The integer division results in 0 whereas the; therefore, when step 3 above is performed, the value of the dividend is carried through (subtracted from zero):

dividend - 0 = 2  —> 2 % 5 = 2 

Application to apply the modulus to a negative

Floor division occurs in which the value of the integer division is rounded down to the lowest integer value:

import math 

x = -1.1
math.floor(-1.1) = -2 

y = 1.1
math.floor = 1

Therefore, when you do integer division you may get a different outcome than you expect!

Applying the steps above on the following dividend and divisor illustrates the modulus concept:

dividend: -5 
divisor: 2 

Step 1: Apply integer division

x_int = -5 // 2  = -3

Step 2: Multiply the result of the integer division by the divisor

x_mult = x_int * 2 = -6

Step 3: Subtract the dividend from the multiplied variable, notice the double negative.

dividend - x_mult = -5 -(-6) = 1

Therefore:

-5 % 2 = 1

回答 13

%(模)运算符从第一个参数除以第二个参数得出余数。首先将数字参数转换为通用类型。

3 + 2 + 1-5 + 4%2-1/4 + 6 = 7

这基于运算符优先级。

The % (modulo) operator yields the remainder from the division of the first argument by the second. The numeric arguments are first converted to a common type.

3 + 2 + 1 – 5 + 4 % 2 – 1 / 4 + 6 = 7

This is based on operator precedence.


回答 14

%3 % 2 = 14 % 2 = 0

/ 是(在这种情况下为整数)除,因此:

3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
1 + 4%2 - 1/4 + 6
1 + 0 - 0 + 6
7

% is modulo. 3 % 2 = 1, 4 % 2 = 0

/ is (an integer in this case) division, so:

3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
1 + 4%2 - 1/4 + 6
1 + 0 - 0 + 6
7

回答 15

这是模运算 http://en.wikipedia.org/wiki/Modulo_operation

http://docs.python.org/reference/expressions.html

因此,按照操作顺序,

(3 + 2 + 1-5)+(4%2)-(1/4)+ 6

(1)+(0)-(0)+ 6

7

1/4 = 0,因为我们在这里进行整数运算。

It’s a modulo operation http://en.wikipedia.org/wiki/Modulo_operation

http://docs.python.org/reference/expressions.html

So with order of operations, that works out to

(3+2+1-5) + (4%2) – (1/4) + 6

(1) + (0) – (0) + 6

7

The 1/4=0 because we’re doing integer math here.


回答 16

就像许多类似C的语言一样,它是余数或模运算。有关数字类型信息,请参见文档-int,float,long,complex

It is, as in many C-like languages, the remainder or modulo operation. See the documentation for numeric types — int, float, long, complex.


回答 17

模数-左操作数除以右操作数,并返回余数。

如果有帮助:

1:0> 2%6
=> 2
2:0> 8%6
=> 2
3:0> 2%6 == 8%6
=> true

… 等等。

Modulus – Divides left hand operand by right hand operand and returns remainder.

If it helps:

1:0> 2%6
=> 2
2:0> 8%6
=> 2
3:0> 2%6 == 8%6
=> true

… and so on.


回答 18

我发现掌握模数运算符(%)的最简单方法是进行长除法。它是余数,可用于确定数字是偶数还是奇数:

4%2 = 0

  2
2|4
 -4
  0


11%3 = 2

  3
3|11
 -9
  2

I have found that the easiest way to grasp the modulus operator (%) is through long division. It is the remainder and can be useful in determining a number to be even or odd:

4%2 = 0

  2
2|4
 -4
  0


11%3 = 2

  3
3|11
 -9
  2

“ is”运算符对整数的行为异常

问题:“ is”运算符对整数的行为异常

为什么以下内容在Python中表现异常?

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?
>>> 257 is 257
True           # Yet the literal numbers compare properly

我正在使用Python 2.5.2。尝试使用某些不同版本的Python,Python 2.3.3似乎在99到100之间显示了上述行为。

基于以上所述,我可以假设Python是内部实现的,因此“小”整数的存储方式与大整数的存储方式不同,并且is运算符可以分辨出这种差异。为什么要泄漏抽象?当我事先不知道它们是否为数字时,比较两个任意对象以查看它们是否相同的更好方法是什么?

Why does the following behave unexpectedly in Python?

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?
>>> 257 is 257
True           # Yet the literal numbers compare properly

I am using Python 2.5.2. Trying some different versions of Python, it appears that Python 2.3.3 shows the above behaviour between 99 and 100.

Based on the above, I can hypothesize that Python is internally implemented such that “small” integers are stored in a different way than larger integers and the is operator can tell the difference. Why the leaky abstraction? What is a better way of comparing two arbitrary objects to see whether they are the same when I don’t know in advance whether they are numbers or not?


回答 0

看看这个:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

这是我在Python 2文档“普通整数对象”中发现的内容(对于Python 3也是一样):

当前的实现为-5到256之间的所有整数保留一个整数对象数组,当您在该范围内创建int时,实际上实际上是返回对现有对象的引用。因此应该可以更改1的值。我怀疑在这种情况下Python的行为是不确定的。:-)

Take a look at this:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

Here’s what I found in the Python 2 documentation, “Plain Integer Objects” (It’s the same for Python 3):

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object. So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. :-)


回答 1

Python的“ is”运算符在使用整数时表现异常吗?

总结-让我强调一下:不要is用于比较整数。

这不是您应该有任何期望的行为。

相反,分别使用==!=比较相等和不平等。例如:

>>> a = 1000
>>> a == 1000       # Test integers like this,
True
>>> a != 5000       # or this!
True
>>> a is 1000       # Don't do this! - Don't use `is` to test integers!!
False

说明

要知道这一点,您需要了解以下内容。

首先,该怎么is办?它是一个比较运算符。从文档中

运算符isis not测试对象标识:x is y当且仅当x和y是同一对象时才为true。x is not y产生反真值。

因此,以下内容是等效的。

>>> a is b
>>> id(a) == id(b)

文档中

id 返回对象的“身份”。这是一个整数(或长整数),在该对象的生存期内,此整数保证是唯一且恒定的。具有不重叠生存期的两个对象可能具有相同的id()值。

请注意,CPython(Python的参考实现)中对象的ID是内存中的位置这一事实是实现细节。Python的其他实现(例如Jython或IronPython)可以轻松地使用的不同实现id

那么用例是is什么呢? PEP8描述

与单例之类的比较None应始终使用isis not,而不应使用相等运算符。

问题

您询问并陈述以下问题(带有代码):

为什么以下内容在Python中表现异常?

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result

不是预期的结果。为什么会这样?这仅意味着256两者a和引用的整数值是整数b的相同实例。整数在Python中是不可变的,因此它们不能更改。这对任何代码都没有影响。不应期望。这仅仅是一个实现细节。

但是也许我们应该为每次声明一个等于256的值而在内存中没有新的单独实例感到高兴。

>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?

看起来我们现在有两个单独的整数实例,它们的值257在内存中。由于整数是不可变的,因此会浪费内存。希望我们不要浪费很多。我们可能不是。但是不能保证这种行为。

>>> 257 is 257
True           # Yet the literal numbers compare properly

好吧,这看起来好像您的Python特定实现正在尝试变得聪明,除非必须这样做,否则不会在内存中创建冗余值的整数。您似乎表明您正在使用Python的引用实现,即CPython。对CPython有好处。

如果CPython可以在全球范围内做到这一点甚至更好,如果它可以便宜地做到这一点(因为查找会花费一定的成本),也许还有另一种实现方式。

但是对于对代码的影响,您不必在乎整数是否是整数的特定实例。您只需要关心该实例的值是什么,就可以使用普通的比较运算符,即==

是什么is

is检查id两个对象的相同。在CPython中,id是内存中的位置,但是在另一个实现中,它可能是其他一些唯一标识的数字。要用代码重新声明:

>>> a is b

是相同的

>>> id(a) == id(b)

那我们为什么要使用is呢?

相对于说,这是一个非常快速的检查,检查两个很长的字符串的值是否相等。但是由于它适用于对象的唯一性,因此我们的用例有限。实际上,我们主要是想用它来检查None,这是一个单例(内存中一个地方存在的唯一实例)。如果有可能将其他单例合并is,我们可以创建其他单例,我们可能会与进行检查,但这相对较少。这是一个示例(将在Python 2和3中运行),例如

SENTINEL_SINGLETON = object() # this will only be created one time.

def foo(keyword_argument=None):
    if keyword_argument is None:
        print('no argument given to foo')
    bar()
    bar(keyword_argument)
    bar('baz')

def bar(keyword_argument=SENTINEL_SINGLETON):
    # SENTINEL_SINGLETON tells us if we were not passed anything
    # as None is a legitimate potential argument we could get.
    if keyword_argument is SENTINEL_SINGLETON:
        print('no argument given to bar')
    else:
        print('argument to bar: {0}'.format(keyword_argument))

foo()

哪些打印:

no argument given to foo
no argument given to bar
argument to bar: None
argument to bar: baz

因此,我们看到,使用is和和哨兵,我们可以区分何时bar不带参数调用和何时带调用None。这些是主要的用例的is-不要没有用它来测试整数,字符串,元组,或者其他喜欢这些东西的平等。

Python’s “is” operator behaves unexpectedly with integers?

In summary – let me emphasize: Do not use is to compare integers.

This isn’t behavior you should have any expectations about.

Instead, use == and != to compare for equality and inequality, respectively. For example:

>>> a = 1000
>>> a == 1000       # Test integers like this,
True
>>> a != 5000       # or this!
True
>>> a is 1000       # Don't do this! - Don't use `is` to test integers!!
False

Explanation

To know this, you need to know the following.

First, what does is do? It is a comparison operator. From the documentation:

The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.

And so the following are equivalent.

>>> a is b
>>> id(a) == id(b)

From the documentation:

id Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

Note that the fact that the id of an object in CPython (the reference implementation of Python) is the location in memory is an implementation detail. Other implementations of Python (such as Jython or IronPython) could easily have a different implementation for id.

So what is the use-case for is? PEP8 describes:

Comparisons to singletons like None should always be done with is or is not, never the equality operators.

The Question

You ask, and state, the following question (with code):

Why does the following behave unexpectedly in Python?

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result

It is not an expected result. Why is it expected? It only means that the integers valued at 256 referenced by both a and b are the same instance of integer. Integers are immutable in Python, thus they cannot change. This should have no impact on any code. It should not be expected. It is merely an implementation detail.

But perhaps we should be glad that there is not a new separate instance in memory every time we state a value equals 256.

>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?

Looks like we now have two separate instances of integers with the value of 257 in memory. Since integers are immutable, this wastes memory. Let’s hope we’re not wasting a lot of it. We’re probably not. But this behavior is not guaranteed.

>>> 257 is 257
True           # Yet the literal numbers compare properly

Well, this looks like your particular implementation of Python is trying to be smart and not creating redundantly valued integers in memory unless it has to. You seem to indicate you are using the referent implementation of Python, which is CPython. Good for CPython.

It might be even better if CPython could do this globally, if it could do so cheaply (as there would a cost in the lookup), perhaps another implementation might.

But as for impact on code, you should not care if an integer is a particular instance of an integer. You should only care what the value of that instance is, and you would use the normal comparison operators for that, i.e. ==.

What is does

is checks that the id of two objects are the same. In CPython, the id is the location in memory, but it could be some other uniquely identifying number in another implementation. To restate this with code:

>>> a is b

is the same as

>>> id(a) == id(b)

Why would we want to use is then?

This can be a very fast check relative to say, checking if two very long strings are equal in value. But since it applies to the uniqueness of the object, we thus have limited use-cases for it. In fact, we mostly want to use it to check for None, which is a singleton (a sole instance existing in one place in memory). We might create other singletons if there is potential to conflate them, which we might check with is, but these are relatively rare. Here’s an example (will work in Python 2 and 3) e.g.

SENTINEL_SINGLETON = object() # this will only be created one time.

def foo(keyword_argument=None):
    if keyword_argument is None:
        print('no argument given to foo')
    bar()
    bar(keyword_argument)
    bar('baz')

def bar(keyword_argument=SENTINEL_SINGLETON):
    # SENTINEL_SINGLETON tells us if we were not passed anything
    # as None is a legitimate potential argument we could get.
    if keyword_argument is SENTINEL_SINGLETON:
        print('no argument given to bar')
    else:
        print('argument to bar: {0}'.format(keyword_argument))

foo()

Which prints:

no argument given to foo
no argument given to bar
argument to bar: None
argument to bar: baz

And so we see, with is and a sentinel, we are able to differentiate between when bar is called with no arguments and when it is called with None. These are the primary use-cases for is – do not use it to test for equality of integers, strings, tuples, or other things like these.


回答 2

这取决于您是否要看两个事物是否相等或相同的对象。

is检查它们是否是相同的对象,而不仅仅是相等。小整数可能指向相同的内存位置以提高空间效率

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

您应该==用来比较任意对象的相等性。您可以使用__eq____ne__属性指定行为。

It depends on whether you’re looking to see if 2 things are equal, or the same object.

is checks to see if they are the same object, not just equal. The small ints are probably pointing to the same memory location for space efficiency

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

You should use == to compare equality of arbitrary objects. You can specify the behavior with the __eq__, and __ne__ attributes.


回答 3

我来晚了,但是,您想从中获得答案吗?我将尝试以介绍性的方式对此进行说明,以便更多的人可以跟进。


关于CPython的一件好事是您实际上可以看到其来源。我将使用3.5版本的链接,但是找到相应的2.x链接是微不足道的。

在CPython中,用于创建新对象的C-API函数intPyLong_FromLong(long v)。此功能的说明是:

当前的实现为-5到256之间的所有整数保留一个整数对象数组,当您在该范围内创建int时,实际上实际上是返回对现有对象的引用。因此应该可以更改1的值。我怀疑在这种情况下Python的行为是不确定的。:-)

(我的斜体)

不了解您,但我看到了并想:让我们找到那个数组!

如果您还不熟悉实现CPython的C代码,则应 ; 一切都井井有条,可读性强。对于我们而言,我们需要在看Objects子目录中的主源代码目录树

PyLong_FromLong处理long对象,因此不难推断我们需要窥视内部longobject.c。看完内部,您可能会觉得事情很混乱。它们是,但不要担心,我们正在寻找的功能在第230行令人不寒而栗,等待我们检查出来。这是一个很小的函数,因此主体(不包括声明)可以轻松粘贴到此处:

PyObject *
PyLong_FromLong(long ival)
{
    // omitting declarations

    CHECK_SMALL_INT(ival);

    if (ival < 0) {
        /* negate: cant write this as abs_ival = -ival since that
           invokes undefined behaviour when ival is LONG_MIN */
        abs_ival = 0U-(unsigned long)ival;
        sign = -1;
    }
    else {
        abs_ival = (unsigned long)ival;
    }

    /* Fast path for single-digit ints */
    if (!(abs_ival >> PyLong_SHIFT)) {
        v = _PyLong_New(1);
        if (v) {
            Py_SIZE(v) = sign;
            v->ob_digit[0] = Py_SAFE_DOWNCAST(
                abs_ival, unsigned long, digit);
        }
        return (PyObject*)v; 
}

现在,我们不是C 主代码-haxxorz,但我们也不傻,我们可以看到这CHECK_SMALL_INT(ival);一切诱人地窥视着我们。我们可以理解,这与此有关。让我们来看看:

#define CHECK_SMALL_INT(ival) \
    do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \
        return get_small_int((sdigit)ival); \
    } while(0)

因此,get_small_int如果值ival满足条件,则它是一个调用函数的宏:

if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS)

那么什么是NSMALLNEGINTSNSMALLPOSINTS?宏!他们在这里

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif

所以我们的条件是if (-5 <= ival && ival < 257)通话get_small_int

接下来,让我们看一下get_small_int它的所有荣耀(好吧,我们只看它的身体,因为那是有趣的地方):

PyObject *v;
assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS);
v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);

好的,声明一个PyObject,断言先前的条件成立并执行赋值:

v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];

small_ints看起来很像我们一直在寻找的那个数组,它是!我们只要阅读该死的文档,我们就永远知道!

/* Small integers are preallocated in this array so that they
   can be shared.
   The integers that are preallocated are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

是的,这是我们的家伙。当您要int在该范围内创建一个新[NSMALLNEGINTS, NSMALLPOSINTS)对象时,您只需返回对已预先分配的现有对象的引用。

由于引用引用的是同一对象,因此id()直接发布或检查其上的身份is将返回完全相同的内容。

但是,什么时候分配它们?

_PyLong_Init Python 初始化期间,将很乐意进入for循环为您执行此操作:

for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {

查看源代码以阅读循环体!

希望我的解释使您现在对C的认识清楚(很明显是故意的)。


但是,257 is 257?这是怎么回事?

这实际上更容易解释,我已经尝试过这样做;这是由于Python将这个交互式语句作为一个单独的块执行:

>>> 257 is 257

在编译此语句期间,CPython将看到您有两个匹配的文字,并将使用相同的PyLongObject表示形式257。如果您自己进行编译并检查其内容,则可以看到以下内容:

>>> codeObj = compile("257 is 257", "blah!", "exec")
>>> codeObj.co_consts
(257, None)

当CPython进行操作时,现在将要加载完全相同的对象:

>>> import dis
>>> dis.dis(codeObj)
  1           0 LOAD_CONST               0 (257)   # dis
              3 LOAD_CONST               0 (257)   # dis again
              6 COMPARE_OP               8 (is)

所以is会回来的True

I’m late but, you want some source with your answer? I’ll try and word this in an introductory manner so more folks can follow along.


A good thing about CPython is that you can actually see the source for this. I’m going to use links for the 3.5 release, but finding the corresponding 2.x ones is trivial.

In CPython, the C-API function that handles creating a new int object is PyLong_FromLong(long v). The description for this function is:

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object. So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. :-)

(My italics)

Don’t know about you but I see this and think: Let’s find that array!

If you haven’t fiddled with the C code implementing CPython you should; everything is pretty organized and readable. For our case, we need to look in the Objects subdirectory of the main source code directory tree.

PyLong_FromLong deals with long objects so it shouldn’t be hard to deduce that we need to peek inside longobject.c. After looking inside you might think things are chaotic; they are, but fear not, the function we’re looking for is chilling at line 230 waiting for us to check it out. It’s a smallish function so the main body (excluding declarations) is easily pasted here:

PyObject *
PyLong_FromLong(long ival)
{
    // omitting declarations

    CHECK_SMALL_INT(ival);

    if (ival < 0) {
        /* negate: cant write this as abs_ival = -ival since that
           invokes undefined behaviour when ival is LONG_MIN */
        abs_ival = 0U-(unsigned long)ival;
        sign = -1;
    }
    else {
        abs_ival = (unsigned long)ival;
    }

    /* Fast path for single-digit ints */
    if (!(abs_ival >> PyLong_SHIFT)) {
        v = _PyLong_New(1);
        if (v) {
            Py_SIZE(v) = sign;
            v->ob_digit[0] = Py_SAFE_DOWNCAST(
                abs_ival, unsigned long, digit);
        }
        return (PyObject*)v; 
}

Now, we’re no C master-code-haxxorz but we’re also not dumb, we can see that CHECK_SMALL_INT(ival); peeking at us all seductively; we can understand it has something to do with this. Let’s check it out:

#define CHECK_SMALL_INT(ival) \
    do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \
        return get_small_int((sdigit)ival); \
    } while(0)

So it’s a macro that calls function get_small_int if the value ival satisfies the condition:

if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS)

So what are NSMALLNEGINTS and NSMALLPOSINTS? Macros! Here they are:

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif

So our condition is if (-5 <= ival && ival < 257) call get_small_int.

Next let’s look at get_small_int in all its glory (well, we’ll just look at its body because that’s where the interesting things are):

PyObject *v;
assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS);
v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);

Okay, declare a PyObject, assert that the previous condition holds and execute the assignment:

v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];

small_ints looks a lot like that array we’ve been searching for, and it is! We could’ve just read the damn documentation and we would’ve know all along!:

/* Small integers are preallocated in this array so that they
   can be shared.
   The integers that are preallocated are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

So yup, this is our guy. When you want to create a new int in the range [NSMALLNEGINTS, NSMALLPOSINTS) you’ll just get back a reference to an already existing object that has been preallocated.

Since the reference refers to the same object, issuing id() directly or checking for identity with is on it will return exactly the same thing.

But, when are they allocated??

During initialization in _PyLong_Init Python will gladly enter in a for loop do do this for you:

for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {

Check out the source to read the loop body!

I hope my explanation has made you C things clearly now (pun obviously intented).


But, 257 is 257? What’s up?

This is actually easier to explain, and I have attempted to do so already; it’s due to the fact that Python will execute this interactive statement as a single block:

>>> 257 is 257

During complilation of this statement, CPython will see that you have two matching literals and will use the same PyLongObject representing 257. You can see this if you do the compilation yourself and examine its contents:

>>> codeObj = compile("257 is 257", "blah!", "exec")
>>> codeObj.co_consts
(257, None)

When CPython does the operation, it’s now just going to load the exact same object:

>>> import dis
>>> dis.dis(codeObj)
  1           0 LOAD_CONST               0 (257)   # dis
              3 LOAD_CONST               0 (257)   # dis again
              6 COMPARE_OP               8 (is)

So is will return True.


回答 4

您可以检入源文件intobject.c,Python会缓存小整数以提高效率。每次创建对小整数的引用时,都是在引用缓存的小整数,而不是新对象。257不是一个小整数,因此它被计算为另一个对象。

最好==用于此目的。

As you can check in source file intobject.c, Python caches small integers for efficiency. Every time you create a reference to a small integer, you are referring the cached small integer, not a new object. 257 is not an small integer, so it is calculated as a different object.

It is better to use == for that purpose.


回答 5

我认为您的假设是正确的。实验id(对象的身份):

In [1]: id(255)
Out[1]: 146349024

In [2]: id(255)
Out[2]: 146349024

In [3]: id(257)
Out[3]: 146802752

In [4]: id(257)
Out[4]: 148993740

In [5]: a=255

In [6]: b=255

In [7]: c=257

In [8]: d=257

In [9]: id(a), id(b), id(c), id(d)
Out[9]: (146349024, 146349024, 146783024, 146804020)

看来数字<= 255被当作​​文字,而上面的任何东西都被不同地对待!

I think your hypotheses is correct. Experiment with id (identity of object):

In [1]: id(255)
Out[1]: 146349024

In [2]: id(255)
Out[2]: 146349024

In [3]: id(257)
Out[3]: 146802752

In [4]: id(257)
Out[4]: 148993740

In [5]: a=255

In [6]: b=255

In [7]: c=257

In [8]: d=257

In [9]: id(a), id(b), id(c), id(d)
Out[9]: (146349024, 146349024, 146783024, 146804020)

It appears that numbers <= 255 are treated as literals and anything above is treated differently!


回答 6

对于整数,字符串或日期时间之类的不可变值对象,对象标识并不是特别有用。最好考虑平等。身份本质上是值对象的实现细节-由于它们是不可变的,因此对同一个对象或多个对象具有多个引用之间没有有效的区别。

For immutable value objects, like ints, strings or datetimes, object identity is not especially useful. It’s better to think about equality. Identity is essentially an implementation detail for value objects – since they’re immutable, there’s no effective difference between having multiple refs to the same object or multiple objects.


回答 7

现有答案中都没有指出另一个问题。允许Python合并任何两个不可变的值,并且预先创建的小int值不是发生这种情况的唯一方法。永远不能保证 Python实现会做到这一点,但他们所做的不仅仅只是小整数。


一方面,还有一些其他预先创建的值,例如empty tuplestrbytes和一些短字符串(在CPython 3.6中,这是256个单字符Latin-1字符串)。例如:

>>> a = ()
>>> b = ()
>>> a is b
True

而且,即使是非预先创建的值也可以相同。考虑以下示例:

>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True

这不限于int值:

>>> g, h = 42.23e100, 42.23e100
>>> g is h
True

显然,CPython没有为预先创建float42.23e100。那么,这是怎么回事?

CPython的编译器将合并一些已知不变类型等的恒定值intfloatstrbytes,在相同的编译单元。对于一个模块,整个模块是一个编译单元,但是在交互式解释器中,每个语句都是一个单独的编译单元。由于cd是在单独的语句中定义的,因此不会合并它们的值。由于ef是在同一条语句中定义的,因此将合并它们的值。


您可以通过分解字节码来查看发生了什么。尝试定义一个执行该操作的函数,e, f = 128, 128然后对其进行调用dis.dis,您将看到只有一个常数值(128, 128)

>>> def f(): i, j = 258, 258
>>> dis.dis(f)
  1           0 LOAD_CONST               2 ((128, 128))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (i)
              6 STORE_FAST               1 (j)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480

您可能会注意到,128即使字节码实际上并未使用编译器,编译器也已将其存储为常量,这使您了解了CPython编译器所做的优化很少。这意味着(非空)元组实际上不会最终合并:

>>> k, l = (1, 2), (1, 2)
>>> k is l
False

把在一个函数,dis它,看看co_consts-there是一个12两个(1, 2)共享相同的元组12,但不相同,并且((1, 2), (1, 2))具有两个不同的元组相等的元组。


CPython还有另外一个优化:字符串实习。与编译器常量折叠不同,这不限于源代码文字:

>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True

另一方面,它仅限于内部存储类型“ ascii compact”,“ compact”或“ legacy ready”str类型和字符串,并且在许多情况下,只有“ ascii compact”会被嵌入。


无论如何,不​​同实现之间,同一实现的版本之间,甚至同一实现的同一副本上运行相同代码的时间之间,关于值必须是,可能是或不能不同的规则有所不同。 。

有趣的是值得学习一个特定Python的规则。但是在代码中不值得依赖它们。唯一安全的规则是:

  • 不要编写假定两个相等但分别创建的不可变值相同的代码(不要使用x is y,请使用x == y
  • 不要编写假定两个相等但分别创建的不可变值不同的代码(不要使用x is not y,请使用x != y

或者,换句话说,仅用于is测试已记录的单例(如None)或仅在代码中的一个位置创建的单例(如_sentinel = object()成语)。

There’s another issue that isn’t pointed out in any of the existing answers. Python is allowed to merge any two immutable values, and pre-created small int values are not the only way this can happen. A Python implementation is never guaranteed to do this, but they all do it for more than just small ints.


For one thing, there are some other pre-created values, such as the empty tuple, str, and bytes, and some short strings (in CPython 3.6, it’s the 256 single-character Latin-1 strings). For example:

>>> a = ()
>>> b = ()
>>> a is b
True

But also, even non-pre-created values can be identical. Consider these examples:

>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True

And this isn’t limited to int values:

>>> g, h = 42.23e100, 42.23e100
>>> g is h
True

Obviously, CPython doesn’t come with a pre-created float value for 42.23e100. So, what’s going on here?

The CPython compiler will merge constant values of some known-immutable types like int, float, str, bytes, in the same compilation unit. For a module, the whole module is a compilation unit, but at the interactive interpreter, each statement is a separate compilation unit. Since c and d are defined in separate statements, their values aren’t merged. Since e and f are defined in the same statement, their values are merged.


You can see what’s going on by disassembling the bytecode. Try defining a function that does e, f = 128, 128 and then calling dis.dis on it, and you’ll see that there’s a single constant value (128, 128)

>>> def f(): i, j = 258, 258
>>> dis.dis(f)
  1           0 LOAD_CONST               2 ((128, 128))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (i)
              6 STORE_FAST               1 (j)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480

You may notice that the compiler has stored 128 as a constant even though it’s not actually used by the bytecode, which gives you an idea of how little optimization CPython’s compiler does. Which means that (non-empty) tuples actually don’t end up merged:

>>> k, l = (1, 2), (1, 2)
>>> k is l
False

Put that in a function, dis it, and look at the co_consts—there’s a 1 and a 2, two (1, 2) tuples that share the same 1 and 2 but are not identical, and a ((1, 2), (1, 2)) tuple that has the two distinct equal tuples.


There’s one more optimization that CPython does: string interning. Unlike compiler constant folding, this isn’t restricted to source code literals:

>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True

On the other hand, it is limited to the str type, and to strings of internal storage kind “ascii compact”, “compact”, or “legacy ready”, and in many cases only “ascii compact” will get interned.


At any rate, the rules for what values must be, might be, or cannot be distinct vary from implementation to implementation, and between versions of the same implementation, and maybe even between runs of the same code on the same copy of the same implementation.

It can be worth learning the rules for one specific Python for the fun of it. But it’s not worth relying on them in your code. The only safe rule is:

  • Do not write code that assumes two equal but separately-created immutable values are identical (don’t use x is y, use x == y)
  • Do not write code that assumes two equal but separately-created immutable values are distinct (don’t use x is not y, use x != y)

Or, in other words, only use is to test for the documented singletons (like None) or that are only created in one place in the code (like the _sentinel = object() idiom).


回答 8

is 身份相等运算符(功能类似于id(a) == id(b));只是两个相等的数字不一定是同一对象。出于性能原因,一些小整数正好会被记住,因此它们往往是相同的(因为它们是不可变的,因此可以这样做)。

===另一方面,PHP的运算符被描述为检查相等性和类型:x == y and type(x) == type(y)根据Paulo Freitas的评论。这足以满足通用数,但不同于以荒谬方式is定义的类__eq__

class Unequal:
    def __eq__(self, other):
        return False

对于“内置”类,PHP显然允许相同的东西(我指的是在C级实现,而不是在PHP中实现)。计时器对象可能有点荒谬,它每次用作数字时,其值都不同。相当为什么要模拟Visual Basic,Now而不是显示它是带有time.time()我不知道。

Greg Hewgill(OP)发表了一条澄清的评论:“我的目标是比较对象标识,而不是价值相等。除了数字,我希望对象标识与价值相等相同。”

这将有另一个答案,因为我们必须将事物归类为数字,以选择是否与==或进行比较isCPython定义数字协议,包括PyNumber_Check,但这不能从Python本身访问。

我们可以尝试使用isinstance所有已知的数字类型,但这不可避免地是不完整的。类型模块包含一个StringTypes列表,但没有NumberTypes。从Python 2.6开始,内置数字类具有基类numbers.Number,但存在相同的问题:

import numpy, numbers
assert not issubclass(numpy.int16,numbers.Number)
assert issubclass(int,numbers.Number)

顺便说一句,NumPy将产生低数字的单独实例。

我实际上不知道这个问题的答案。我想从理论上讲可以使用ctypes进行调用PyNumber_Check,但是即使该函数也已经受到参数,并且肯定不是可移植的。我们只需要对我们目前要测试的内容有所保留。

最后,此问题源于Python最初没有类型树,其谓词如Scheme number?Haskell的 类型类 Numis检查对象身份,而不是值相等。PHP的历史也很悠久,===显然is在PHP5中的对象上起作用,而在PHP4中没有。这就是跨语言(包括一种语言的版本)之间转移的越来越大的痛苦。

is is the identity equality operator (functioning like id(a) == id(b)); it’s just that two equal numbers aren’t necessarily the same object. For performance reasons some small integers happen to be memoized so they will tend to be the same (this can be done since they are immutable).

PHP’s === operator, on the other hand, is described as checking equality and type: x == y and type(x) == type(y) as per Paulo Freitas’ comment. This will suffice for common numbers, but differ from is for classes that define __eq__ in an absurd manner:

class Unequal:
    def __eq__(self, other):
        return False

PHP apparently allows the same thing for “built-in” classes (which I take to mean implemented at C level, not in PHP). A slightly less absurd use might be a timer object, which has a different value every time it’s used as a number. Quite why you’d want to emulate Visual Basic’s Now instead of showing that it is an evaluation with time.time() I don’t know.

Greg Hewgill (OP) made one clarifying comment “My goal is to compare object identity, rather than equality of value. Except for numbers, where I want to treat object identity the same as equality of value.”

This would have yet another answer, as we have to categorize things as numbers or not, to select whether we compare with == or is. CPython defines the number protocol, including PyNumber_Check, but this is not accessible from Python itself.

We could try to use isinstance with all the number types we know of, but this would inevitably be incomplete. The types module contains a StringTypes list but no NumberTypes. Since Python 2.6, the built in number classes have a base class numbers.Number, but it has the same problem:

import numpy, numbers
assert not issubclass(numpy.int16,numbers.Number)
assert issubclass(int,numbers.Number)

By the way, NumPy will produce separate instances of low numbers.

I don’t actually know an answer to this variant of the question. I suppose one could theoretically use ctypes to call PyNumber_Check, but even that function has been debated, and it’s certainly not portable. We’ll just have to be less particular about what we test for now.

In the end, this issue stems from Python not originally having a type tree with predicates like Scheme’s number?, or Haskell’s type class Num. is checks object identity, not value equality. PHP has a colorful history as well, where === apparently behaves as is only on objects in PHP5, but not PHP4. Such are the growing pains of moving across languages (including versions of one).


回答 9

字符串也会发生这种情况:

>>> s = b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

现在一切似乎都很好。

>>> s = 'somestr'
>>> b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

这也是预期的。

>>> s1 = b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, True, 4555308080, 4555308080)

>>> s1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, False, 4555308176, 4555308272)

现在那是出乎意料的。

It also happens with strings:

>>> s = b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

Now everything seems fine.

>>> s = 'somestr'
>>> b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

That’s expected too.

>>> s1 = b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, True, 4555308080, 4555308080)

>>> s1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, False, 4555308176, 4555308272)

Now that’s unexpected.


回答 10

Python 3.8的新增功能:Python行为的变化

现在,当将身份检查(和 )与某些类型的文字(例如字符串,整数)一起使用时,编译器会生成SyntaxWarning。这些通常在CPython中偶然地起作用,但是语言规范无法保证。该警告建议用户改用相等性测试( 和)。isis not==!=

What’s New In Python 3.8: Changes in Python behavior:

The compiler now produces a SyntaxWarning when identity checks (is and is not) are used with certain types of literals (e.g. strings, ints). These can often work by accident in CPython, but are not guaranteed by the language spec. The warning advises users to use equality tests (== and !=) instead.


用于除法时,“ /”和“ //”之间有什么区别?

问题:用于除法时,“ /”和“ //”之间有什么区别?

将一个使用在另一个上是否有好处?在Python 2中,它们似乎都返回相同的结果:

>>> 6/3
2
>>> 6//3
2

Is there a benefit to using one over the other? In Python 2, they both seem to return the same results:

>>> 6/3
2
>>> 6//3
2

回答 0

在Python 3.x中,5 / 2将返回2.5并且5 // 2将返回2。前者是浮点除法,后者是地板除法,有时也称为整数除法

在Python 2.2或更高版本的2.x行中,除非执行from __future__ import division,否则整数没有区别,这会使Python 2.x采取3.x行为。

不管将来的进口是什么,5.0 // 2都会归还,2.0因为这是操作的地板分割结果。

您可以在https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator中找到详细说明

In Python 3.x, 5 / 2 will return 2.5 and 5 // 2 will return 2. The former is floating point division, and the latter is floor division, sometimes also called integer division.

In Python 2.2 or later in the 2.x line, there is no difference for integers unless you perform a from __future__ import division, which causes Python 2.x to adopt the 3.x behavior.

Regardless of the future import, 5.0 // 2 will return 2.0 since that’s the floor division result of the operation.

You can find a detailed description at https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator


回答 1

Python 2.x澄清:

为了阐明Python 2.x系列,/既不是楼层划分也不是真正的划分。当前接受的答案尚不清楚。

/是地板除法时 ARG游戏int,但真正当师之一或两者的参数的个数是float

上面讲了更多的事实,并且比接受的答案中的第二段更清楚。

Python 2.x Clarification:

To clarify for the Python 2.x line, / is neither floor division nor true division. The current accepted answer is not clear on this.

/ is floor division when both args are int, but is true division when either or both of the args are float.

The above tells more truth, and is more clear than the 2nd paragraph in the accepted answer.


回答 2

//不论您使用哪种类型,都可以实施“楼层划分”。所以 1.0/2.0会给0.5,但两者1/21//2并且1.0//2.0会给0

有关详细信息,请参见https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator

// implements “floor division”, regardless of your type. So 1.0/2.0 will give 0.5, but both 1/2, 1//2 and 1.0//2.0 will give 0.

See https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator for details


回答 3

// -浮点除法

// ->楼层划分

让我们在python 2.7和python 3.5中查看一些示例。

Python 2.7.10和Python 3.5

print (2/3)  ----> 0                   Python 2.7
print (2/3)  ----> 0.6666666666666666  Python 3.5

Python 2.7.10和Python 3.5

  print (4/2)  ----> 2         Python 2.7
  print (4/2)  ----> 2.0       Python 3.5

现在,如果您希望在python 2.7中具有与python 3.5相同的输出,则可以执行以下操作:

Python 2.7.10

from __future__ import division
print (2/3)  ----> 0.6666666666666666   #Python 2.7
print (4/2)  ----> 2.0                  #Python 2.7

在python 2.7和python 3.5中,Floor划分之间没有区别

138.93//3 ---> 46.0        #Python 2.7
138.93//3 ---> 46.0        #Python 3.5
4//3      ---> 1           #Python 2.7
4//3      ---> 1           #Python 3.5

/ –> Floating point division

// –> Floor division

Lets see some examples in both python 2.7 and in Python 3.5.

Python 2.7.10 vs. Python 3.5

print (2/3)  ----> 0                   Python 2.7
print (2/3)  ----> 0.6666666666666666  Python 3.5

Python 2.7.10 vs. Python 3.5

  print (4/2)  ----> 2         Python 2.7
  print (4/2)  ----> 2.0       Python 3.5

Now if you want to have (in python 2.7) same output as in python 3.5, you can do the following:

Python 2.7.10

from __future__ import division
print (2/3)  ----> 0.6666666666666666   #Python 2.7
print (4/2)  ----> 2.0                  #Python 2.7

Where as there is no differece between Floor division in both python 2.7 and in Python 3.5

138.93//3 ---> 46.0        #Python 2.7
138.93//3 ---> 46.0        #Python 3.5
4//3      ---> 1           #Python 2.7
4//3      ---> 1           #Python 3.5

回答 4

正如大家已经回答的那样,//是楼层划分。

之所以如此重要,是因为//在所有2.2版本的Python版本中,包括Python 3.x版本,都明确地进行了地域划分。

的行为/可能会有所不同,具体取决于:

  • 是否有效__future__导入(模块本地)
  • Python命令行选项,-Q old或者-Q new

As everyone has already answered, // is floor division.

Why this is important is that // is unambiguously floor division, in all Python versions from 2.2, including Python 3.x versions.

The behavior of / can change depending on:

  • Active __future__ import or not (module-local)
  • Python command line option, either -Q old or -Q new

回答 5

>>> print 5.0 / 2
2.5

>>> print 5.0 // 2
2.0
>>> print 5.0 / 2
2.5

>>> print 5.0 // 2
2.0

回答 6

Python 2.7和其他即将发布的python版本:

  • 部门(/

将左操作数除以右操作数

例: 4 / 2 = 2

  • 楼层部门(//

操作数的除法,结果是除掉小数点后的数字的商。但是,如果其中一个操作数是负数,则结果是下限的,即从零开始舍入(朝负无穷大):

例如:9//2 = 49.0//2.0 = 4.0-11//3 = -4-11.0//3 = -4.0

这两个/师和//地板除法运算的操作以类似的方式。

Python 2.7 and other upcoming version of python:

  • Division (/)

Divides left hand operand by right hand operand

Example: 4 / 2 = 2

  • Floor Division (//)

The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity):

Examples: 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0

Both / Division and // floor division operator are operating in similar fashion.


回答 7

双斜线//是地板分割:

>>> 7//3
2

The double slash, //, is floor division:

>>> 7//3
2

回答 8

//是底数除法,它将始终为您提供结果的整数底数。另一个是“常规”划分。

// is floor division, it will always give you the integer floor of the result. The other is ‘regular’ division.


回答 9

等式的答案四舍五入为下一个较小的整数,或者以.0作为小数点进行浮点运算。

>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0

The answer of the equation is rounded to the next smaller integer or float with .0 as decimal point.

>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0

回答 10

上面的答案是好的。我想补充一点。最多两个值都导致相同的商。在该楼层之后,除法运算符(//)正常工作,但除法运算符()无效/

 - > int(755349677599789174/2)
 - > 377674838799894592      #wrong answer
 - > 755349677599789174 //2
 - > 377674838799894587      #correct answer

The above answers are good. I want to add another point. Up to some values both of them result in the same quotient. After that floor division operator (//) works fine but not division (/) operator.

 - > int(755349677599789174/2)
 - > 377674838799894592      #wrong answer
 - > 755349677599789174 //2
 - > 377674838799894587      #correct answer

回答 11

5.0//2会导致2.0,而不是2因为运算符返回值的返回类型//遵循python强制(类型转换)规则。

Python促进将较低数据类型(整数)转换为较高数据类型(浮点数),以避免数据丢失。

5.0//2 results in 2.0, and not 2 because the return type of the return value from // operator follows python coercion (type casting) rules.

Python promotes conversion of lower datatype (integer) to higher data type (float) to avoid data loss.


回答 12

  • // 是底数划分,它将始终为您提供结果的底数。
  • 另一个/是浮点除法。

以下是之间的差///; 我已经在Python 3.7.2中运行了这些算术运算

>>> print (11 / 3)
3.6666666666666665

>>> print (11 // 3)
3

>>> print (11.3 / 3)
3.7666666666666667

>>> print (11.3 // 3)
3.0
  • // is floor division, it will always give you the floor value of the result.
  • And the other one / is the floating-point division.

Followings are the difference between / and //; I have run these arithmetic operations in Python 3.7.2

>>> print (11 / 3)
3.6666666666666665

>>> print (11 // 3)
3

>>> print (11.3 / 3)
3.7666666666666667

>>> print (11.3 // 3)
3.0

为什么Python中没有++和-运算符?

问题:为什么Python中没有++和-运算符?

为什么在Python中没有++and --运算符?

Why are there no ++ and -- operators in Python?


回答 0

不是因为它没有道理;而是因为它没有意义。最好将“ x ++”定义为“ x + = 1,求出x的先前绑定”。

如果您想知道最初的原因,则必须要么浏览旧的Python邮件列表,要么询问那里的某个人(例如Guido),但是在事实成立之后就很容易找到理由了:

与其他语言一样,不需要简单的增量和减量。您不会for(int i = 0; i < 10; ++i)经常用Python 编写东西。相反,你做类似的事情for i in range(0, 10)

由于几乎不需要它,因此没有太多理由为其提供特殊的语法。当您确实需要增加时,+=通常就可以了。

这不是是否有意义,还是可以做到的决定。这是一个好处是否值得添加到该语言的核心语法中的问题。请记住,这是四个运算符-postinc,postdec,preinc,predec,并且每个运算符都需要具有自己的类重载;他们都需要指定和测试;它将在语言中添加操作码(暗示更大,因此更慢的VM引擎);每个支持逻辑增量的类都需要实现它们(在+=和之上-=)。

+=和都是多余的-=,因此将成为净亏损。

It’s not because it doesn’t make sense; it makes perfect sense to define “x++” as “x += 1, evaluating to the previous binding of x”.

If you want to know the original reason, you’ll have to either wade through old Python mailing lists or ask somebody who was there (eg. Guido), but it’s easy enough to justify after the fact:

Simple increment and decrement aren’t needed as much as in other languages. You don’t write things like for(int i = 0; i < 10; ++i) in Python very often; instead you do things like for i in range(0, 10).

Since it’s not needed nearly as often, there’s much less reason to give it its own special syntax; when you do need to increment, += is usually just fine.

It’s not a decision of whether it makes sense, or whether it can be done–it does, and it can. It’s a question of whether the benefit is worth adding to the core syntax of the language. Remember, this is four operators–postinc, postdec, preinc, predec, and each of these would need to have its own class overloads; they all need to be specified, and tested; it would add opcodes to the language (implying a larger, and therefore slower, VM engine); every class that supports a logical increment would need to implement them (on top of += and -=).

This is all redundant with += and -=, so it would become a net loss.


回答 1

我写的这个原始答案是关于计算机民俗的一个神话:被丹尼斯·里奇(Dennis Ritchie)认为是“历史上不可能的”,正如ACM通讯编辑在2012年7月致函doi:10.1145 / 2209249.2209251


C增/减运算符是在C编译器不是很聪明的时候发明的,作者希望能够指定使用机器语言运算符的直接意图,从而节省了编译器的几个周期,可能会做一个

load memory
load 1
add
store memory

代替

inc memory 

PDP-11甚至支持分别对应于*++p和的“自动递增”和“延迟自动递增”指令*p++。如果非常好奇,请参阅手册第5.3节。

由于编译器足够聪明,可以处理C语法中内置的高级优化技巧,因此它们现在只是语法上的便利。

Python没有技巧来向汇编器传达意图,因为它不使用汇编器。

This original answer I wrote is a myth from the folklore of computing: debunked by Dennis Ritchie as “historically impossible” as noted in the letters to the editors of Communications of the ACM July 2012 doi:10.1145/2209249.2209251


The C increment/decrement operators were invented at a time when the C compiler wasn’t very smart and the authors wanted to be able to specify the direct intent that a machine language operator should be used which saved a handful of cycles for a compiler which might do a

load memory
load 1
add
store memory

instead of

inc memory 

and the PDP-11 even supported “autoincrement” and “autoincrement deferred” instructions corresponding to *++p and *p++, respectively. See section 5.3 of the manual if horribly curious.

As compilers are smart enough to handle the high-level optimization tricks built into the syntax of C, they are just a syntactic convenience now.

Python doesn’t have tricks to convey intentions to the assembler because it doesn’t use one.


回答 2

我一直以为这与python禅的这一行有关:

应该有一种(最好只有一种)明显的方式来做到这一点。

x ++和x + = 1做完全相同的事情,因此没有理由同时使用两者。

I always assumed it had to do with this line of the zen of python:

There should be one — and preferably only one — obvious way to do it.

x++ and x+=1 do the exact same thing, so there is no reason to have both.


回答 3

当然,我们可以说“圭多岛就是这样决定的”,但我认为问题实际上是做出该决定的原因。我认为有以下几个原因:

  • 它将陈述和表达式混合在一起,这不是一个好习惯。参见http://norvig.com/python-iaq.html
  • 它通常会鼓励人们编写可读性较低的代码
  • 如前所述,语言实现的额外复杂性在Python中是不必要的

Of course, we could say “Guido just decided that way”, but I think the question is really about the reasons for that decision. I think there are several reasons:

  • It mixes together statements and expressions, which is not good practice. See http://norvig.com/python-iaq.html
  • It generally encourages people to write less readable code
  • Extra complexity in the language implementation, which is unnecessary in Python, as already mentioned

回答 4

因为在Python中,整数是不可变的(int的+ =实际上返回了一个不同的对象)。

同样,使用++ /-时,您需要担心增量前后的递增和递减,并且只需要再写一次按键即可x+=1。换句话说,它避免了潜在的混乱,但付出的代价却很小。

Because, in Python, integers are immutable (int’s += actually returns a different object).

Also, with ++/– you need to worry about pre- versus post- increment/decrement, and it takes only one more keystroke to write x+=1. In other words, it avoids potential confusion at the expense of very little gain.


回答 5

明晰!

Python有很多关于清晰度--a的知识,除非他/她学习了具有这种构造的语言,否则任何程序员都不可能正确地猜测的含义。

Python还有很多关于避免引发错误的构造的知识,并且++已知运算符是缺陷的丰富来源。这两个原因足以在Python中没有这些运算符。

Python使用缩进来标记块而不是诸如某种形式的开始/结束方括号或强制结束标记之类的句法手段的决定很大程度上基于相同的考虑。

作为说明,请看一下有关在2005年向Python中引入条件运算符(在C:中cond ? resultif : resultelse)的讨论。至少请阅读该讨论第一条消息决策消息(之前有相同主题的多个先驱)。

琐事: 其中经常提到的PEP是“ Python扩展建议” PEP 308。LC表示列表理解,GE表示生成器表达式(不要担心,如果它们使您感到困惑,它们不是Python的少数复杂地方)。

Clarity!

Python is a lot about clarity and no programmer is likely to correctly guess the meaning of --a unless s/he’s learned a language having that construct.

Python is also a lot about avoiding constructs that invite mistakes and the ++ operators are known to be rich sources of defects. These two reasons are enough not to have those operators in Python.

The decision that Python uses indentation to mark blocks rather than syntactical means such as some form of begin/end bracketing or mandatory end marking is based largely on the same considerations.

For illustration, have a look at the discussion around introducing a conditional operator (in C: cond ? resultif : resultelse) into Python in 2005. Read at least the first message and the decision message of that discussion (which had several precursors on the same topic previously).

Trivia: The PEP frequently mentioned therein is the “Python Extension Proposal” PEP 308. LC means list comprehension, GE means generator expression (and don’t worry if those confuse you, they are none of the few complicated spots of Python).


回答 6

我对python为什么没有++运算符的理解如下:当您在python中编写此代码时,a=b=c=1您将获得三个变量(标签),它们指向同一对象(值为1)。您可以使用id函数进行验证,该函数将返回对象内存地址:

In [19]: id(a)
Out[19]: 34019256

In [20]: id(b)
Out[20]: 34019256

In [21]: id(c)
Out[21]: 34019256

所有三个变量(标签)都指向同一对象。现在递增变量之一,看看它如何影响内存地址:

In [22] a = a + 1

In [23]: id(a)
Out[23]: 34019232

In [24]: id(b)
Out[24]: 34019256

In [25]: id(c)
Out[25]: 34019256

您可以看到该变量a现在指向另一个对象,为bc。因为您已经使用a = a + 1它,所以它很明显。换句话说,您将另一个对象完全分配给label a。想象一下,您可以编写a++它,这表明您没有分配给变量a新对象,而是增加了旧对象的数量。所有这些东西都是恕我直言,以尽量减少混乱。为了更好地理解,请参见python变量如何工作:

在Python中,为什么函数可以修改调用者认为的某些参数,而不能修改其他参数?

Python是按值调用还是按引用调用?都不行

Python是按值传递还是按引用传递?

Python是按引用传递还是按值传递?

Python:如何通过引用传递变量?

了解Python变量和内存管理

在python中模拟按值传递行为

Python函数通过引用调用

像Pythonista一样的代码:惯用的Python

My understanding of why python does not have ++ operator is following: When you write this in python a=b=c=1 you will get three variables (labels) pointing at same object (which value is 1). You can verify this by using id function which will return an object memory address:

In [19]: id(a)
Out[19]: 34019256

In [20]: id(b)
Out[20]: 34019256

In [21]: id(c)
Out[21]: 34019256

All three variables (labels) point to the same object. Now increment one of variable and see how it affects memory addresses:

In [22] a = a + 1

In [23]: id(a)
Out[23]: 34019232

In [24]: id(b)
Out[24]: 34019256

In [25]: id(c)
Out[25]: 34019256

You can see that variable a now points to another object as variables b and c. Because you’ve used a = a + 1 it is explicitly clear. In other words you assign completely another object to label a. Imagine that you can write a++ it would suggest that you did not assign to variable a new object but ratter increment the old one. All this stuff is IMHO for minimization of confusion. For better understanding see how python variables works:

In Python, why can a function modify some arguments as perceived by the caller, but not others?

Is Python call-by-value or call-by-reference? Neither.

Does Python pass by value, or by reference?

Is Python pass-by-reference or pass-by-value?

Python: How do I pass a variable by reference?

Understanding Python variables and Memory Management

Emulating pass-by-value behaviour in python

Python functions call by reference

Code Like a Pythonista: Idiomatic Python


回答 7

它就是这样设计的。递增和递减运算符只是的快捷方式x = x + 1。Python通常采用了一种设计策略,该策略减少了执行操作的替代方法的数量。 增量分配是Python中最接近递增/递减运算符的东西,直到Python 2.0才添加。

It was just designed that way. Increment and decrement operators are just shortcuts for x = x + 1. Python has typically adopted a design strategy which reduces the number of alternative means of performing an operation. Augmented assignment is the closest thing to increment/decrement operators in Python, and they weren’t even added until Python 2.0.


回答 8

我是python的新手,但我怀疑原因是由于该语言中的可变对象和不可变对象之间的强调。现在,我知道x ++可以很容易地解释为x = x + 1,但是它看起来就像您就地递增一个不可变的对象一样。

只是我的猜测/感觉/预感。

I’m very new to python but I suspect the reason is because of the emphasis between mutable and immutable objects within the language. Now, I know that x++ can easily be interpreted as x = x + 1, but it LOOKS like you’re incrementing in-place an object which could be immutable.

Just my guess/feeling/hunch.


回答 9

首先,Python仅受C间接影响。它在很大程度上受到影响ABC,这显然不具备这些运营商,所以它不应该有任何巨大的惊喜不会找到它们在Python两种。

其次,正如其他人所说,递增和递减由支持+=-=了。

第三,对++and --运算符集的完全支持通常包括同时支持它们的前缀和后缀版本。在C和C ++中,这可能导致各种“可爱”的构造(在我看来)与Python所包含的简单性和直截了当的精神背道而驰。

例如,尽管C语句while(*t++ = *s++);对于有经验的程序员而言似乎简单而优雅,但对于学习它的人来说,却绝非简单。混合使用前缀和后缀增量和减量,甚至许多专业人士也必须停下来思考一下。

First, Python is only indirectly influenced by C; it is heavily influenced by ABC, which apparently does not have these operators, so it should not be any great surprise not to find them in Python either.

Secondly, as others have said, increment and decrement are supported by += and -= already.

Third, full support for a ++ and -- operator set usually includes supporting both the prefix and postfix versions of them. In C and C++, this can lead to all kinds of “lovely” constructs that seem (to me) to be against the spirit of simplicity and straight-forwardness that Python embraces.

For example, while the C statement while(*t++ = *s++); may seem simple and elegant to an experienced programmer, to someone learning it, it is anything but simple. Throw in a mixture of prefix and postfix increments and decrements, and even many pros will have to stop and think a bit.


回答 10

我认为这源于Python的信条,即“明确胜于隐含”。

I believe it stems from the Python creed that “explicit is better than implicit”.


回答 11

这可能是因为@GlennMaynard正在将问题与其他语言进行比较,但是在Python中,您是以python方式进行操作的。这不是一个“为什么”的问题。在那里,您可以使用达到相同的效果x+=。在《 Python的禅宗》中,给出了:“只有一种解决问题的方法。” 多种选择在艺术上(表达自由)很棒,但在工程上却很​​糟糕。

This may be because @GlennMaynard is looking at the matter as in comparison with other languages, but in Python, you do things the python way. It’s not a ‘why’ question. It’s there and you can do things to the same effect with x+=. In The Zen of Python, it is given: “there should only be one way to solve a problem.” Multiple choices are great in art (freedom of expression) but lousy in engineering.


回答 12

++运算符的类别是具有副作用的表达式。这是Python中通常找不到的东西。

出于同样的原因,赋值不是Python中的表达式,因此防止了通用 if (a = f(...)) { /* using a here */ }用法。

最后,我怀疑操作符与Python的参考语义不是很一致。请记住,Python没有具有C / C ++已知语义的变量(或指针)。

The ++ class of operators are expressions with side effects. This is something generally not found in Python.

For the same reason an assignment is not an expression in Python, thus preventing the common if (a = f(...)) { /* using a here */ } idiom.

Lastly I suspect that there operator are not very consistent with Pythons reference semantics. Remember, Python does not have variables (or pointers) with the semantics known from C/C++.


回答 13

也许更好的问题是问为什么这些运算符存在于C中。K&R调用增量和减量运算符为“异常”(第2.8页第2.8节)。导言称它们“更简洁,通常更高效”。我怀疑这些操作总是在指针操作中出现的事实也影响了它们的引入。在Python中,可能已经决定尝试优化增量没有任何意义(事实上,我只是在C中进行了测试,而且似乎gcc生成的程序集在两种情况下都使用addl而不是incl),并且没有指针算法;因此,它本来只是另一种实现方式,而我们知道Python不愿这样做。

Maybe a better question would be to ask why do these operators exist in C. K&R calls increment and decrement operators ‘unusual’ (Section 2.8page 46). The Introduction calls them ‘more concise and often more efficient’. I suspect that the fact that these operations always come up in pointer manipulation also has played a part in their introduction. In Python it has been probably decided that it made no sense to try to optimise increments (in fact I just did a test in C, and it seems that the gcc-generated assembly uses addl instead of incl in both cases) and there is no pointer arithmetic; so it would have been just One More Way to Do It and we know Python loathes that.


回答 14

据我了解,所以您不会认为内存中的值已更改。在c中,当执行x ++时,内存中x的值会更改。但是在python中,所有数字都是不可变的,因此x指向的地址仍然具有x而不是x + 1。当您编写x ++时,您可能会认为x发生了改变,实际上是x引用更改为x + 1存储在内存中的位置,或者如果doe不存在,则重新创建该位置。

as i understood it so you won’t think the value in memory is changed. in c when you do x++ the value of x in memory changes. but in python all numbers are immutable hence the address that x pointed as still has x not x+1. when you write x++ you would think that x change what really happens is that x refrence is changed to a location in memory where x+1 is stored or recreate this location if doe’s not exists.


回答 15

要在该页面上完成已经很好的答案:

假设我们决定这样做,在前缀(++i)处打乱一元+和-运算符。

今天,以++--做任何前缀都没有,因为它使一元加号运算符两次(不执行任何操作)或一元减号两次(两次:取消自身)成为可能

>>> i=12
>>> ++i
12
>>> --i
12

这样可能会破坏这种逻辑。

To complete already good answers on that page:

Let’s suppose we decide to do this, prefix (++i) that would break the unary + and – operators.

Today, prefixing by ++ or -- does nothing, because it enables unary plus operator twice (does nothing) or unary minus twice (twice: cancels itself)

>>> i=12
>>> ++i
12
>>> --i
12

So that would potentially break that logic.


回答 16

其他答案描述了为什么迭代器不需要它,但是有时在分配以增加内联变量时它很有用,您可以使用元组和多重分配来达到相同的效果:

b = ++a 变成:

a,b = (a+1,)*2

b = a++成为:

a,b = a+1, a

Python的3.8引入了分配:=操作,使我们能够实现foo(++a)

foo(a:=a+1)

foo(a++) 虽然仍然难以捉摸。

Other answers have described why it’s not needed for iterators, but sometimes it is useful when assigning to increase a variable in-line, you can achieve the same effect using tuples and multiple assignment:

b = ++a becomes:

a,b = (a+1,)*2

and b = a++ becomes:

a,b = a+1, a

Python 3.8 introduces the assignment := operator, allowing us to achievefoo(++a) with

foo(a:=a+1)

foo(a++) is still elusive though.


回答 17

我认为这涉及对象的可变性和不可变性的概念。2,3,4,5在python中是不可变的。请参考下图。2具有固定的ID,直到此python进程为止。

x ++本质上意味着像C的就地增量。在C中,x ++执行就地增量。因此,x = 3,并且x ++会将内存中的3增加到4,这与python中内存中仍然存在3的情况不同。

因此,在python中,您无需在内存中重新创建值。这可能会导致性能优化。

这是基于预感的答案。

I think this relates to the concepts of mutability and immutability of objects. 2,3,4,5 are immutable in python. Refer to the image below. 2 has fixed id until this python process.

x++ would essentially mean an in-place increment like C. In C, x++ performs in-place increments. So, x=3, and x++ would increment 3 in the memory to 4, unlike python where 3 would still exist in memory.

Thus in python, you don’t need to recreate a value in memory. This may lead to performance optimizations.

This is a hunch based answer.


回答 18

我知道这是一个旧线程,但是没有涵盖++ i的最常见用例,即在没有提供索引的情况下手动索引集。这就是为什么python提供enumerate()的原因

示例:在任何给定的语言中,当您使用诸如foreach之类的结构来遍历一个集合时,出于示例的考虑,我们甚至会说它是无序的集合,并且您需要一个唯一的索引来区分所有内容,例如

i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
  uniquestuff[key] = '{0}{1}'.format(val, i)
  i += 1

在这种情况下,python提供了一个枚举方法,例如

for i, (key, val) in enumerate(stuff.items()) :

I know this is an old thread, but the most common use case for ++i is not covered, that being manually indexing sets when there are no provided indices. This situation is why python provides enumerate()

Example : In any given language, when you use a construct like foreach to iterate over a set – for the sake of the example we’ll even say it’s an unordered set and you need a unique index for everything to tell them apart, say

i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
  uniquestuff[key] = '{0}{1}'.format(val, i)
  i += 1

In cases like this, python provides an enumerate method, e.g.

for i, (key, val) in enumerate(stuff.items()) :

Python中是否存在“不相等”运算符?

问题:Python中是否存在“不相等”运算符?

你怎么说不等于?

喜欢

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

是否有等同于==“不平等”的东西?

How would you say does not equal?

Like

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

Is there something equivalent to == that means “not equal”?


回答 0

使用!=。请参阅比较运算符。为了比较对象身份,可以使用关键字is及其否定词is not

例如

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

Use !=. See comparison operators. For comparing object identities, you can use the keyword is and its negation is not.

e.g.

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

回答 1

不等于 != (vs等于==

您是否在问这样的事情?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

Python-基本运算符图表可能会有所帮助。

Not equal != (vs equal ==)

Are you asking about something like this?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

This Python – Basic Operators chart might be helpful.


回答 2

当两个值不同时,有一个!=(不相等)运算符返回True,尽管要小心类型,因为"1" != 1"1" == 1由于类型不同,它将始终返回True,并且始终返回False。Python是动态的但是强类型的,而其他静态类型的语言会抱怨比较不同的类型。

还有else子句:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

is运算符是对象标识运算符,用于检查两个对象实际上是否相同:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

There’s the != (not equal) operator that returns True when two values differ, though be careful with the types because "1" != 1. This will always return True and "1" == 1 will always return False, since the types differ. Python is dynamically, but strongly typed, and other statically typed languages would complain about comparing different types.

There’s also the else clause:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

The is operator is the object identity operator used to check if two objects in fact are the same:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

回答 3

您可以同时使用!=<>

但是,请注意,不建议!=<>不推荐的地方使用它。

You can use both != or <>.

However, note that != is preferred where <> is deprecated.


回答 4

看到其他所有人都已经列出了大多数其他方式来表示不平等,我将添加:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

在这种情况下,很容易将正==(true)的检查切换为负,反之亦然…

Seeing as everyone else has already listed most of the other ways to say not equal I will just add:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

in this case it is simple switching the check of positive == (true) to negative and vise versa…


回答 5

您可以将“不等于”用于“不等于”或“!=“。请参见以下示例:

a = 2
if a == 2:
   print("true")
else:
   print("false")

上面的代码将在“ if”条件之前将“ true”打印为a = 2。现在,请参见下面的“不等于”代码

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

上面的代码将打印“不等于”,即早先分配的a = 2。

You can use “is not” for “not equal” or “!=”. Please see the example below:

a = 2
if a == 2:
   print("true")
else:
   print("false")

The above code will print “true” as a = 2 assigned before the “if” condition. Now please see the code below for “not equal”

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

The above code will print “not equal” as a = 2 as assigned earlier.


回答 6

Python中有两个用于“不相等”条件的运算符-

a。)!=如果两个操作数的值不相等,则条件变为true。(a!= b)是正确的。

b。)<>如果两个操作数的值不相等,则条件变为true。(a <> b)是正确的。这类似于!=运算符。

There are two operators in Python for the “not equal” condition –

a.) != If values of the two operands are not equal, then the condition becomes true. (a != b) is true.

b.) <> If values of the two operands are not equal, then the condition becomes true. (a <> b) is true. This is similar to the != operator.


回答 7

使用!=<>。两者代表不平等。

比较运算符<>!=是相同运算符的替代拼写。!=是首选拼写;<>是过时的。[参考:Python语言参考]

Use != or <>. Both stands for not equal.

The comparison operators <> and != are alternate spellings of the same operator. != is the preferred spelling; <> is obsolescent. [Reference: Python language reference]


回答 8

您可以简单地执行以下操作:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"

You can simply do:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"