标签归档:boolean

简洁的书写方式(a + b == c或a + c == b或b + c == a)

问题:简洁的书写方式(a + b == c或a + c == b或b + c == a)

是否有更紧凑或Pythonic的方式来编写布尔表达式

a + b == c or a + c == b or b + c == a

我想出了

a + b + c in (2*a, 2*b, 2*c)

但这有点奇怪。

Is there a more compact or pythonic way to write the boolean expression

a + b == c or a + c == b or b + c == a

I came up with

a + b + c in (2*a, 2*b, 2*c)

but that is a little strange.


回答 0

如果我们看一下Python的Zen,请强调一下:

提姆·彼得斯(Tim Peters)撰写的《 Python之禅》

美丽胜于丑陋。
显式胜于隐式。
简单胜于复杂。
复杂胜于复杂。
扁平比嵌套更好。
稀疏胜于密集。
可读性很重要。
特殊情况还不足以打破规则。
尽管实用性胜过纯度。
错误绝不能默默传递。
除非明确地保持沉默。
面对模棱两可的想法,拒绝猜测的诱惑。
应该有一种-最好只有一种-显而易见的方法。
尽管除非您是荷兰人,否则一开始这种方式可能并不明显。
现在总比没有好。
虽然从来没有比这更好正确的现在。
如果实现难以解释,那是个坏主意。
如果实现易于解释,则可能是个好主意。
命名空间是一个很棒的主意-让我们做更多这些吧!

最Python化的解决方案是最清晰,最简单和最容易解释的解决方案:

a + b == c or a + c == b or b + c == a

更好的是,您甚至不需要了解Python就能理解此代码!就这么简单。这是毫无保留的最佳解决方案。其他一切都是智力上的自慰。

此外,这可能也是性能最佳的解决方案,因为它是所有短路建议中的唯一解决方案。如果为a + b == c,则仅进行一次加法和比较。

If we look at the Zen of Python, emphasis mine:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

The most Pythonic solution is the one that is clearest, simplest, and easiest to explain:

a + b == c or a + c == b or b + c == a

Even better, you don’t even need to know Python to understand this code! It’s that easy. This is, without reservation, the best solution. Anything else is intellectual masturbation.

Furthermore, this is likely the best performing solution as well, as it is the only one out of all the proposals that short circuits. If a + b == c, only a single addition and comparison is done.


回答 1

解决以下三个等式:

a in (b+c, b-c, c-b)

Solving the three equalities for a:

a in (b+c, b-c, c-b)

回答 2

Python具有对序列的所有元素any执行的功能or。在这里,我已经将您的陈述转换为3元素元组。

any((a + b == c, a + c == b, b + c == a))

请注意,这or是短路的,因此,如果计算单个条件的成本很高,则最好保留原始结构。

Python has an any function that does an or on all the elements of a sequence. Here I’ve converted your statement into a 3-element tuple.

any((a + b == c, a + c == b, b + c == a))

Note that or is short circuiting, so if calculating the individual conditions is expensive it might be better to keep your original construct.


回答 3

如果您知道只处理正数,则可以使用,并且很干净:

a, b, c = sorted((a, b, c))
if a + b == c:
    do_stuff()

正如我所说,这仅适用于正数;但是,如果您知道它们将是肯定的,那么这是一个非常易读的IMO解决方案,即使直接在代码中而不是在函数中。

您可以执行此操作,这可能需要进行一些重复的计算。但是您没有将性能指定为目标:

from itertools import permutations

if any(x + y == z for x, y, z in permutations((a, b, c), 3)):
    do_stuff()

有无permutations()重复计算的可能性:

if any(x + y == z for x, y, z in [(a, b, c), (a, c, b), (b, c, a)]:
    do_stuff()

我可能会将此函数或任何其他解决方案放入函数中。然后,您可以在代码中干净地调用该函数。

就个人而言,除非我需要代码提供更多的灵活性,否则我只会在您的问题中使用第一种方法。简单高效。我仍然可以将其放入函数中:

def two_add_to_third(a, b, c):
    return a + b == c or a + c == b or b + c == a

if two_add_to_third(a, b, c):
    do_stuff()

那是相当Pythonic的,并且可能是最有效的方式(除了额外的函数调用);尽管您无论如何也不必太担心性能,除非它确实引起了问题。

If you know you’re only dealing with positive numbers, this will work, and is pretty clean:

a, b, c = sorted((a, b, c))
if a + b == c:
    do_stuff()

As I said, this only works for positive numbers; but if you know they’re going to be positive, this is a very readable solution IMO, even directly in the code as opposed to in a function.

You could do this, which might do a bit of repeated computation; but you didn’t specify performance as your goal:

from itertools import permutations

if any(x + y == z for x, y, z in permutations((a, b, c), 3)):
    do_stuff()

Or without permutations() and the possibility of repeated computations:

if any(x + y == z for x, y, z in [(a, b, c), (a, c, b), (b, c, a)]:
    do_stuff()

I would probably put this, or any other solution, into a function. Then you can just cleanly call the function in your code.

Personally, unless I needed more flexibility from the code, I would just use the first method in your question. It’s simple and efficient. I still might put it into a function:

def two_add_to_third(a, b, c):
    return a + b == c or a + c == b or b + c == a

if two_add_to_third(a, b, c):
    do_stuff()

That’s pretty Pythonic, and it’s quite possibly the most efficient way to do it (the extra function call aside); although you shouldn’t worry too much about performance anyway, unless it’s actually causing an issue.


回答 4

如果仅使用三个变量,则使用初始方法:

a + b == c or a + c == b or b + c == a

已经很pythonic了。

如果您打算使用更多的变量,那么您的推理方法如下:

a + b + c in (2*a, 2*b, 2*c)

非常聪明,但请考虑一下原因。为什么这样做?
通过一些简单的算法,我们看到:

a + b = c
c = c
a + b + c == c + c == 2*c
a + b + c == 2*c

而这将不得不为任何一个,b或c保持为真,这意味着是的,它会等于2*a2*b2*c。任何数量的变量都是如此。

因此,快速编写此代码的一种好方法是只包含一个变量列表,并对照一倍的值列表检查它们的总和。

values = [a,b,c,d,e,...]
any(sum(values) in [2*x for x in values])

这样,要将更多变量添加到方程式中,您要做的就是通过“ n”个新变量来编辑值列表,而不是编写“ n”个方程式

If you will only be using three variables then your initial method:

a + b == c or a + c == b or b + c == a

Is already very pythonic.

If you plan on using more variables then your method of reasoning with:

a + b + c in (2*a, 2*b, 2*c)

Is very smart but lets think about why. Why does this work?
Well through some simple arithmetic we see that:

a + b = c
c = c
a + b + c == c + c == 2*c
a + b + c == 2*c

And this will have to hold true for either a,b, or c, meaning that yes it will equal 2*a, 2*b, or 2*c. This will be true for any number of variables.

So a good way to write this quickly would be to simply have a list of your variables and check their sum against a list of the doubled values.

values = [a,b,c,d,e,...]
any(sum(values) in [2*x for x in values])

This way, to add more variables into the equation all you have to do is edit your values list by ‘n’ new variables, not write ‘n’ equations


回答 5

以下代码可用于将每个元素与其他元素的总和进行迭代比较,这是根据整个列表的总和(不包括该元素)计算得出的。

 l = [a,b,c]
 any(sum(l)-e == e for e in l)

The following code can be used to iteratively compare each element with the sum of the others, which is computed from sum of the whole list, excluding that element.

 l = [a,b,c]
 any(sum(l)-e == e for e in l)

回答 6

不要尝试简化它。取而代之的是使用函数命名

def any_two_sum_to_third(a, b, c):
  return a + b == c or a + c == b or b + c == a

if any_two_sum_to_third(foo, bar, baz):
  ...

将条件替换为“聪明”可能会使它更短,但不会使其更具可读性。但是,如何保留它也不是很容易理解,因为要知道为什么要一眼检查这三个条件是很棘手的。这使您可以清楚地确定要检查的内容。

关于性能,这种方法的确增加了函数调用的开销,但是除非您发现了绝对必须解决的瓶颈,否则不要牺牲性能的可读性。并始终进行测量,因为某些巧妙的实现能够在某些情况下优化并内联某些函数调用。

Don’t try and simplify it. Instead, name what you’re doing with a function:

def any_two_sum_to_third(a, b, c):
  return a + b == c or a + c == b or b + c == a

if any_two_sum_to_third(foo, bar, baz):
  ...

Replace the condition with something “clever” might make it shorter, but it won’t make it more readable. Leaving it how it is isn’t very readable either however, because it’s tricky to know why you’re checking those three conditions at a glance. This makes it absolutely crystal clear what you’re checking for.

Regarding performance, this approach does add the overhead of a function call, but never sacrifice readability for performance unless you’ve found a bottleneck you absolutely must fix. And always measure, as some clever implementations are capable of optimizing away and inlining some function calls in some circumstances.


回答 7

Python 3:

(a+b+c)/2 in (a,b,c)
(a+b+c+d)/2 in (a,b,c,d)
...

它可以缩放为任意数量的变量:

arr = [a,b,c,d,...]
sum(arr)/2 in arr

但是,总的来说,我同意除非您拥有三个以上的变量,否则原始版本更具可读性。

Python 3:

(a+b+c)/2 in (a,b,c)
(a+b+c+d)/2 in (a,b,c,d)
...

It scales to any number of variables:

arr = [a,b,c,d,...]
sum(arr)/2 in arr

However, in general I agree that unless you have more than three variables, the original version is more readable.


回答 8

(a+b-c)*(a+c-b)*(b+c-a) == 0

如果任意两项的总和等于第三项,则其中一个因子将为零,从而使整个乘积为零。

(a+b-c)*(a+c-b)*(b+c-a) == 0

If the sum of any two terms is equal to the third term, then one of the factors will be zero, making the entire product zero.


回答 9

怎么样:

a == b + c or abs(a) == abs(b - c)

请注意,如果变量是无符号的,这将不起作用。

从代码优化的角度(至少在x86平台上),这似乎是最有效的解决方案。

现代编译器将内联两个abs()函数调用,并通过使用巧妙的CDQ,XOR和SUB指令序列来避免符号测试和随后的条件分支。因此,上面的高级代码将仅由低延迟,高吞吐量的ALU指令和仅两个条件表示。

How about just:

a == b + c or abs(a) == abs(b - c)

Note that this won’t work if variables are unsigned.

From the viewpoint of code optimization (at least on x86 platform) this seems to be the most efficient solution.

Modern compilers will inline both abs() function calls and avoid sign testing and subsequent conditional branch by using a clever sequence of CDQ, XOR, and SUB instructions. The above high-level code will thus be represented with only low-latency, high-throughput ALU instructions and just two conditionals.


回答 10

Alex Varga提供的解决方案“ a in(b + c,bc,cb)”是紧凑的,并且在数学上很漂亮,但实际上我不会那样写代码,因为下一个开发人员不会立即理解代码的目的。

马克·兰瑟姆(Mark Ransom)的解决方案

any((a + b == c, a + c == b, b + c == a))

比它更清晰,但不比它更简洁

a + b == c or a + c == b or b + c == a

当编写代码时,别人不得不去看,或者当我忘记了编写代码时的想法时,我将不得不花很长时间去看,太短或太聪明往往弊大于利。代码应可读。简洁是件好事,但不是那么简洁,以致下一个程序员无法理解。

The solution provided by Alex Varga “a in (b+c, b-c, c-b)” is compact and mathematically beautiful, but I wouldn’t actually write code that way because the next developer coming along would not immediately understand the purpose of the code.

Mark Ransom’s solution of

any((a + b == c, a + c == b, b + c == a))

is more clear but not much more succinct than

a + b == c or a + c == b or b + c == a

When writing code that someone else will have to look at, or that I will have to look at a long time later when I have forgotten what I was thinking when I wrote it, being too short or clever tends to do more harm than good. Code should be readable. So succinct is good, but not so succinct that the next programmer can’t understand it.


回答 11

请求的是更紧凑或更Pythonic-我尝试了更紧凑。

给定

import functools, itertools
f = functools.partial(itertools.permutations, r = 3)
def g(x,y,z):
    return x + y == z

比原版少2个字符

any(g(*args) for args in f((a,b,c)))

测试:

assert any(g(*args) for args in f((a,b,c))) == (a + b == c or a + c == b or b + c == a)

另外,给出:

h = functools.partial(itertools.starmap, g)

这是等效的

any(h(f((a,b,c))))

Request is for more compact OR more pythonic – I tried my hand at more compact.

given

import functools, itertools
f = functools.partial(itertools.permutations, r = 3)
def g(x,y,z):
    return x + y == z

This is 2 characters less than the original

any(g(*args) for args in f((a,b,c)))

test with:

assert any(g(*args) for args in f((a,b,c))) == (a + b == c or a + c == b or b + c == a)

additionally, given:

h = functools.partial(itertools.starmap, g)

This is equivalent

any(h(f((a,b,c))))

回答 12

我想介绍一下我认为是最pythonic的答案:

def one_number_is_the_sum_of_the_others(a, b, c):
    return any((a == b + c, b == a + c, c == a + b))

一般情况,未优化:

def one_number_is_the_sum_of_the_others(numbers):
    for idx in range(len(numbers)):
        remaining_numbers = numbers[:]
        sum_candidate = remaining_numbers.pop(idx)
        if sum_candidate == sum(remaining_numbers):
            return True
    return False 

就Python Zen而言,我认为强调的陈述比其他答案更受关注:

提姆·彼得斯(Tim Peters)撰写的《 Python之禅》

美丽胜于丑陋。
显式胜于隐式。
简单胜于复杂。
复杂胜于复杂。
扁平比嵌套更好。
稀疏胜于密集。
可读性很重要。
特殊情况还不足以打破规则。
尽管实用性胜过纯度。
错误绝不能默默传递。
除非明确地保持沉默。
面对模棱两可的想法,拒绝猜测的诱惑。
应该有一种-最好只有一种-显而易见的方法。
尽管除非您是荷兰人,否则一开始这种方式可能并不明显。
现在总比没有好。
虽然从来没有比这更好正确的现在。
如果实现难以解释,那是个坏主意。
如果实现易于解释,则可能是个好主意。
命名空间是一个很棒的主意-让我们做更多这些吧!

I want to present what I see as the most pythonic answer:

def one_number_is_the_sum_of_the_others(a, b, c):
    return any((a == b + c, b == a + c, c == a + b))

The general case, non-optimized:

def one_number_is_the_sum_of_the_others(numbers):
    for idx in range(len(numbers)):
        remaining_numbers = numbers[:]
        sum_candidate = remaining_numbers.pop(idx)
        if sum_candidate == sum(remaining_numbers):
            return True
    return False 

In terms of the Zen of Python I think the emphasized statements are more followed than from other answer:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!


回答 13

作为我编程的一个老习惯,我认为将复杂的表达式放在子句中可以使其更具可读性,如下所示:

a == b+c or b == a+c or c == a+b

加号()

((a == b+c) or (b == a+c) or (c == a+b))

而且我认为使用多行也可以使更多的感觉像这样:

((a == b+c) or 
 (b == a+c) or 
 (c == a+b))

As an old habit of my programming, I think placing complex expression at right in a clause can make it more readable like this:

a == b+c or b == a+c or c == a+b

Plus ():

((a == b+c) or (b == a+c) or (c == a+b))

And also I think using multi-lines can also make more senses like this:

((a == b+c) or 
 (b == a+c) or 
 (c == a+b))

回答 14

以一般方式

m = a+b-c;
if (m == 0 || m == 2*a || m == 2*b) do_stuff ();

如果您可以操作输入变量,

c = a+b-c;
if (c==0 || c == 2*a || c == 2*b) do_stuff ();

如果要使用位hack进行利用,则可以使用“!”,“ >> 1”和“ << 1”

我避免了除法,尽管它可以避免两次乘法以避免舍入错误。但是,检查溢出

In a generic way,

m = a+b-c;
if (m == 0 || m == 2*a || m == 2*b) do_stuff ();

if, manipulating an input variable is OK for you,

c = a+b-c;
if (c==0 || c == 2*a || c == 2*b) do_stuff ();

if you want to exploit using bit hacks, you can use “!”, “>> 1” and “<< 1”

I avoided division though it enables use to avoid two multiplications to avoid round off errors. However, check for overflows


回答 15

def any_sum_of_others (*nums):
    num_elements = len(nums)
    for i in range(num_elements):
        discriminating_map = map(lambda j: -1 if j == i else 1, range(num_elements))
        if sum(n * u for n, u in zip(nums, discriminating_map)) == 0:
            return True
    return False

print(any_sum_of_others(0, 0, 0)) # True
print(any_sum_of_others(1, 2, 3)) # True
print(any_sum_of_others(7, 12, 5)) # True
print(any_sum_of_others(4, 2, 2)) # True
print(any_sum_of_others(1, -1, 0)) # True
print(any_sum_of_others(9, 8, -4)) # False
print(any_sum_of_others(4, 3, 2)) # False
print(any_sum_of_others(1, 1, 1, 1, 4)) # True
print(any_sum_of_others(0)) # True
print(any_sum_of_others(1)) # False
def any_sum_of_others (*nums):
    num_elements = len(nums)
    for i in range(num_elements):
        discriminating_map = map(lambda j: -1 if j == i else 1, range(num_elements))
        if sum(n * u for n, u in zip(nums, discriminating_map)) == 0:
            return True
    return False

print(any_sum_of_others(0, 0, 0)) # True
print(any_sum_of_others(1, 2, 3)) # True
print(any_sum_of_others(7, 12, 5)) # True
print(any_sum_of_others(4, 2, 2)) # True
print(any_sum_of_others(1, -1, 0)) # True
print(any_sum_of_others(9, 8, -4)) # False
print(any_sum_of_others(4, 3, 2)) # False
print(any_sum_of_others(1, 1, 1, 1, 4)) # True
print(any_sum_of_others(0)) # True
print(any_sum_of_others(1)) # False

如何将布尔数组转换为int数组

问题:如何将布尔数组转换为int数组

我使用Scilab,并希望将布尔数组转换为整数数组:

>>> x = np.array([4, 3, 2, 1])
>>> y = 2 >= x
>>> y
array([False, False,  True,  True], dtype=bool)

在Scilab中,我可以使用:

>>> bool2s(y)
0.    0.    1.    1.  

甚至只是将其乘以1:

>>> 1*y
0.    0.    1.    1.  

在Python中是否有一个简单的命令,还是我必须使用循环?

I use Scilab, and want to convert an array of booleans into an array of integers:

>>> x = np.array([4, 3, 2, 1])
>>> y = 2 >= x
>>> y
array([False, False,  True,  True], dtype=bool)

In Scilab I can use:

>>> bool2s(y)
0.    0.    1.    1.  

or even just multiply it by 1:

>>> 1*y
0.    0.    1.    1.  

Is there a simple command for this in Python, or would I have to use a loop?


回答 0

numpy数组有一个astype方法。做吧y.astype(int)

请注意,根据您使用数组的目的,甚至可能没有必要执行此操作。在许多情况下,Bool会自动提升为int,因此您可以将其添加到int数组中,而无需显式转换它:

>>> x
array([ True, False,  True], dtype=bool)
>>> x + [1, 2, 3]
array([2, 2, 4])

Numpy arrays have an astype method. Just do y.astype(int).

Note that it might not even be necessary to do this, depending on what you’re using the array for. Bool will be autopromoted to int in many cases, so you can add it to int arrays without having to explicitly convert it:

>>> x
array([ True, False,  True], dtype=bool)
>>> x + [1, 2, 3]
array([2, 2, 4])

回答 1

1*y方法也适用于Numpy:

>>> import numpy as np
>>> x = np.array([4, 3, 2, 1])
>>> y = 2 >= x
>>> y
array([False, False,  True,  True], dtype=bool)
>>> 1*y                      # Method 1
array([0, 0, 1, 1])
>>> y.astype(int)            # Method 2
array([0, 0, 1, 1]) 

如果您正在寻求一种将Python列表从Boolean转换为int的方法,则可以使用以下map方法:

>>> testList = [False, False,  True,  True]
>>> map(lambda x: 1 if x else 0, testList)
[0, 0, 1, 1]
>>> map(int, testList)
[0, 0, 1, 1]

或使用列表推导:

>>> testList
[False, False, True, True]
>>> [int(elem) for elem in testList]
[0, 0, 1, 1]

The 1*y method works in Numpy too:

>>> import numpy as np
>>> x = np.array([4, 3, 2, 1])
>>> y = 2 >= x
>>> y
array([False, False,  True,  True], dtype=bool)
>>> 1*y                      # Method 1
array([0, 0, 1, 1])
>>> y.astype(int)            # Method 2
array([0, 0, 1, 1]) 

If you are asking for a way to convert Python lists from Boolean to int, you can use map to do it:

>>> testList = [False, False,  True,  True]
>>> map(lambda x: 1 if x else 0, testList)
[0, 0, 1, 1]
>>> map(int, testList)
[0, 0, 1, 1]

Or using list comprehensions:

>>> testList
[False, False, True, True]
>>> [int(elem) for elem in testList]
[0, 0, 1, 1]

回答 2

使用numpy,您可以执行以下操作:

y = x.astype(int)

如果您使用的是非numpy数组,则可以使用列表推导

y = [int(val) for val in x]

Using numpy, you can do:

y = x.astype(int)

If you were using a non-numpy array, you could use a list comprehension:

y = [int(val) for val in x]

回答 3

大多数时候,您不需要转换:

>>>array([True,True,False,False]) + array([1,2,3,4])
array([2, 3, 3, 4])

正确的方法是:

yourArray.astype(int)

要么

yourArray.astype(float)

Most of the time you don’t need conversion:

>>>array([True,True,False,False]) + array([1,2,3,4])
array([2, 3, 3, 4])

The right way to do it is:

yourArray.astype(int)

or

yourArray.astype(float)

回答 4

我知道您要求使用非循环解决方案,但无论如何,我能想到的唯一解决方案可能是内部循环的:

map(int,y)

要么:

[i*1 for i in y]

要么:

import numpy
y=numpy.array(y)
y*1

I know you asked for non-looping solutions, but the only solutions I can come up with probably loop internally anyway:

map(int,y)

or:

[i*1 for i in y]

or:

import numpy
y=numpy.array(y)
y*1

回答 5

一个有趣的方法是

>>> np.array([True, False, False]) + 0 
np.array([1, 0, 0])

A funny way to do this is

>>> np.array([True, False, False]) + 0 
np.array([1, 0, 0])

如何在Python中获得布尔值的相反(否定)?

问题:如何在Python中获得布尔值的相反(否定)?

对于以下示例:

def fuctionName(int, bool):
    if int in range(...):
        if bool == True:
            return False
        else:
            return True

有什么办法可以跳过第二个if语句?只是为了告诉计算机返回布尔值的相反值bool

For the following sample:

def fuctionName(int, bool):
    if int in range(...):
        if bool == True:
            return False
        else:
            return True

Is there any way to skip the second if-statement? Just to tell the computer to return the opposite of the boolean bool?


回答 0

您可以使用:

return not bool

You can just use:

return not bool

回答 1

not操作者(逻辑否定)

最好的方法可能是使用运算符not

>>> value = True
>>> not value
False

>>> value = False
>>> not value
True

因此,而不是您的代码:

if bool == True:
    return False
else:
    return True

您可以使用:

return not bool

逻辑否定为函数

operator模块中还有两个函数,如果需要将其作为函数而不是运算符,operator.not_则为别名operator.__not__

>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False

如果您要使用需要谓词功能或回调的功能,这些功能将很有用。

例如mapfilter

>>> lst = [True, False, True, False]
>>> list(map(operator.not_, lst))
[False, True, False, True]

>>> lst = [True, False, True, False]
>>> list(filter(operator.not_, lst))
[False, False]

当然,使用等效lambda功能也可以实现相同的效果:

>>> my_not_function = lambda item: not item

>>> list(map(my_not_function, lst))
[False, True, False, True]

不要~在布尔值上使用按位求反运算符

一个人可能很想使用按位取反运算符~或等效的运算符功能operator.inv(或那里的其他三个别名之一)。但是由于结果bool的子类int可能是意外的,因为它不返回“反布尔”,而是返回“反整数”:

>>> ~True
-2
>>> ~False
-1

这是因为,True就相当于1False0和位反转上的按位表示操作整数 10

因此,这些不能用于“否定” a bool

NumPy数组(和子类)的求反

如果您要处理包含布尔值的NumPy数组(或子类,例如pandas.Seriespandas.DataFrame),则实际上可以使用按位逆运算符(~)来消除数组中的所有布尔值:

>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False,  True, False,  True])

或等效的NumPy函数:

>>> np.bitwise_not(arr)
array([False,  True, False,  True])

您不能在NumPy数组上使用not运算符或operator.not函数,因为它们要求它们返回一个bool(而不是布尔数组),但是NumPy还包含一个逻辑非函数,可以在元素上起作用:

>>> np.logical_not(arr)
array([False,  True, False,  True])

这也可以应用于非布尔数组:

>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False,  True])

自定义自己的Class

not通过调用bool值并取反结果来工作。在最简单的情况下,真值将仅调用__bool__对象。

因此,通过实现__bool__(或__nonzero__在Python 2中),您可以自定义true值,从而自定义结果not

class Test(object):
    def __init__(self, value):
        self._value = value

    def __bool__(self):
        print('__bool__ called on {!r}'.format(self))
        return bool(self._value)

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return '{self.__class__.__name__}({self._value!r})'.format(self=self)

我添加了一条print语句,以便您可以验证它是否确实调用了该方法:

>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False

同样,您可以实现应用__invert__方法以在~应用时实现行为:

class Test(object):
    def __init__(self, value):
        self._value = value

    def __invert__(self):
        print('__invert__ called on {!r}'.format(self))
        return not self._value

    def __repr__(self):
        return '{self.__class__.__name__}({self._value!r})'.format(self=self)

再次print调用以查看它实际上是否被调用:

>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False

>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True

但是,这样的实现__invert__可能会造成混淆,因为它的行为不同于“常规” Python行为。如果您这样做的话,请清楚地记录下来,并确保它有一个很好的(和常见的)用例。

The not operator (logical negation)

Probably the best way is using the operator not:

>>> value = True
>>> not value
False

>>> value = False
>>> not value
True

So instead of your code:

if bool == True:
    return False
else:
    return True

You could use:

return not bool

The logical negation as function

There are also two functions in the operator module operator.not_ and it’s alias operator.__not__ in case you need it as function instead of as operator:

>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False

These can be useful if you want to use a function that requires a predicate-function or a callback.

For example map or filter:

>>> lst = [True, False, True, False]
>>> list(map(operator.not_, lst))
[False, True, False, True]

>>> lst = [True, False, True, False]
>>> list(filter(operator.not_, lst))
[False, False]

Of course the same could also be achieved with an equivalent lambda function:

>>> my_not_function = lambda item: not item

>>> list(map(my_not_function, lst))
[False, True, False, True]

Do not use the bitwise invert operator ~ on booleans

One might be tempted to use the bitwise invert operator ~ or the equivalent operator function operator.inv (or one of the other 3 aliases there). But because bool is a subclass of int the result could be unexpected because it doesn’t return the “inverse boolean”, it returns the “inverse integer”:

>>> ~True
-2
>>> ~False
-1

That’s because True is equivalent to 1 and False to 0 and bitwise inversion operates on the bitwise representation of the integers 1 and 0.

So these cannot be used to “negate” a bool.

Negation with NumPy arrays (and subclasses)

If you’re dealing with NumPy arrays (or subclasses like pandas.Series or pandas.DataFrame) containing booleans you can actually use the bitwise inverse operator (~) to negate all booleans in an array:

>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False,  True, False,  True])

Or the equivalent NumPy function:

>>> np.bitwise_not(arr)
array([False,  True, False,  True])

You cannot use the not operator or the operator.not function on NumPy arrays because these require that these return a single bool (not an array of booleans), however NumPy also contains a logical not function that works element-wise:

>>> np.logical_not(arr)
array([False,  True, False,  True])

That can also be applied to non-boolean arrays:

>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False,  True])

Customizing your own classes

not works by calling bool on the value and negate the result. In the simplest case the truth value will just call __bool__ on the object.

So by implementing __bool__ (or __nonzero__ in Python 2) you can customize the truth value and thus the result of not:

class Test(object):
    def __init__(self, value):
        self._value = value

    def __bool__(self):
        print('__bool__ called on {!r}'.format(self))
        return bool(self._value)

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return '{self.__class__.__name__}({self._value!r})'.format(self=self)

I added a print statement so you can verify that it really calls the method:

>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False

Likewise you could implement the __invert__ method to implement the behavior when ~ is applied:

class Test(object):
    def __init__(self, value):
        self._value = value

    def __invert__(self):
        print('__invert__ called on {!r}'.format(self))
        return not self._value

    def __repr__(self):
        return '{self.__class__.__name__}({self._value!r})'.format(self=self)

Again with a print call to see that it is actually called:

>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False

>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True

However implementing __invert__ like that could be confusing because it’s behavior is different from “normal” Python behavior. If you ever do that clearly document it and make sure that it has a pretty good (and common) use-case.


回答 2

Python有一个“非”运​​算符,对吗?不仅仅是“不是”吗?如

  return not bool

Python has a “not” operator, right? Is it not just “not”? As in,

  return not bool

回答 3

您可以只比较布尔数组。例如

X = [True, False, True]

然后

Y = X == False

会给你

Y = [False, True, False]

You can just compare the boolean array. For example

X = [True, False, True]

then

Y = X == False

would give you

Y = [False, True, False]

回答 4

对于给定的情况,此处可接受的答案是最正确的。

但是,这使我想知道一般只将布尔值取反。事实证明,这里公认的解决方案可以用作一种衬板,而另一种衬板也可以使用。假设您有一个已知为布尔值的变量“ n”,那么将其取反的最简单方法是:

n = n is False

这是我最初的解决方案,然后是这个问题的公认答案:

n = not n

后者更清晰,但是我想知道性能,并一直坚持下去timeit-事实证明,n = not n这也是反转布尔值的更快方法。

The accepted answer here is the most correct for the given scenario.

It made me wonder though about simply inverting a boolean value in general. It turns out the accepted solution here works as one liner, and there’s another one-liner that works as well. Assuming you have a variable “n” that you know is a boolean, the easiest ways to invert it are:

n = n is False

which was my original solution, and then the accepted answer from this question:

n = not n

The latter IS more clear, but I wondered about performance and hucked it through timeit – and it turns out at n = not n is also the FASTER way to invert the boolean value.


回答 5

如果您尝试实现一个toggle,那么无论何时只要重新运行一个持久化的代码,它都会被否定,则可以实现以下目标:

try:
    toggle = not toggle
except NameError:
    toggle = True

运行此代码将首先将设置为toggleTrue并且每当此代码段调用时,切换都会被取消。

If you are trying to implement a toggle, so that anytime you re-run a persistent code its being negated, you can achieve that as following:

try:
    toggle = not toggle
except NameError:
    toggle = True

Running this code will first set the toggle to True and anytime this snippet ist called, toggle will be negated.


如何在Python中使用布尔值?

问题:如何在Python中使用布尔值?

Python实际上包含布尔值吗?我知道您可以做到:

checker = 1
if checker:
    #dostuff

但是我相当学究,喜欢在Java中看到布尔值。例如:

Boolean checker;
if (someDecision)
{
    checker = true;
}
if(checker)
{
    //some stuff
}

Python中是否有布尔值之类的东西?我似乎在文档中找不到类似的内容。

Does Python actually contain a Boolean value? I know that you can do:

checker = 1
if checker:
    #dostuff

But I’m quite pedantic and enjoy seeing booleans in Java. For instance:

Boolean checker;
if (someDecision)
{
    checker = true;
}
if(checker)
{
    //some stuff
}

Is there such a thing as a Boolean in Python? I can’t seem to find anything like it in the documentation.


回答 0

checker = None 

if some_decision:
    checker = True

if checker:
    # some stuff

[编辑]

有关更多信息:http : //docs.python.org/library/functions.html#bool

您的代码也可以工作,因为在需要时1会转换为True。实际上,Python很长一段时间没有布尔类型了(就像在旧的C语言中一样),并且一些程序员仍然使用整数而不是布尔值。

checker = None 

if some_decision:
    checker = True

if checker:
    # some stuff

[Edit]

For more information: http://docs.python.org/library/functions.html#bool

Your code works too, since 1 is converted to True when necessary. Actually Python didn’t have a boolean type for a long time (as in old C), and some programmers still use integers instead of booleans.


回答 1

布尔内建函数大写:TrueFalse

另请注意,您可以做checker = bool(some_decision)一些速记- bool只会返回TrueFalse

很高兴知道这些类定义了__nonzero____len__将要成为TrueFalse取决于这些函数的结果以供将来参考,但是实际上每个其他对象的布尔结果都是TrueNone对象,空序列和数字零除外)。

The boolean builtins are capitalized: True and False.

Note also that you can do checker = bool(some_decision) as a bit of shorthand — bool will only ever return True or False.

It’s good to know for future reference that classes defining __nonzero__ or __len__ will be True or False depending on the result of those functions, but virtually every other object’s boolean result will be True (except for the None object, empty sequences, and numeric zeros).


回答 2

True…而且False显然。

否则,None计算结果为False,整数0和浮点数也将计算为False 0.0(尽管我不会那样使用浮点数)。此外,空列表[],空tuplet ()和空字符串''""评估为False。

使用以下函数自己尝试bool()

bool([])
bool(['a value'])
bool('')
bool('A string')
bool(True)  # ;-)
bool(False)
bool(0)
bool(None)
bool(0.0)
bool(1)

等等..

True … and False obviously.

Otherwise, None evaluates to False, as does the integer 0 and also the float 0.0 (although I wouldn’t use floats like that). Also, empty lists [], empty tuplets (), and empty strings '' or "" evaluate to False.

Try it yourself with the function bool():

bool([])
bool(['a value'])
bool('')
bool('A string')
bool(True)  # ;-)
bool(False)
bool(0)
bool(None)
bool(0.0)
bool(1)

etc..


回答 3

布尔类型在文档中定义:http :
//docs.python.org/library/stdtypes.html#boolean-values

引用自doc:

布尔值是两个常量对象False和True。它们用于表示真值(尽管其他值也可以视为假或真)。在数字上下文中(例如,当用作算术运算符的参数时),它们的行为分别类似于整数0和1。如果可以将该值解释为真值,则可以使用内置函数bool()将任何值转换为布尔值(请参见上面的真值测试部分)。

它们分别写为False和True。

因此,在Java代码中,删除括号,将其更改trueTrue,就可以了:)

Boolean types are defined in documentation:
http://docs.python.org/library/stdtypes.html#boolean-values

Quoted from doc:

Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true). In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively. The built-in function bool() can be used to cast any value to a Boolean, if the value can be interpreted as a truth value (see section Truth Value Testing above).

They are written as False and True, respectively.

So in java code remove braces, change true to True and you will be ok :)


回答 4

是的,有一个bool数据类型(继承自int并且只有两个值:TrueFalse)。

但是,Python也具有boolean-able每个对象的概念,在调用函数时会使用该概念bool([x])

查看更多:对象。Python中的非零布尔值对象

Yes, there is a bool data type (which inherits from int and has only two values: True and False).

But also Python has the boolean-able concept for every object, which is used when function bool([x]) is called.

See more: object.nonzero and boolean-value-of-objects-in-python.


回答 5

与您要声明的Java不同boolean flag = True,在Python中,您可以声明myFlag = True

Python会将其解释为布尔变量

Unlike Java where you would declare boolean flag = True, in Python you can just declare myFlag = True

Python would interpret this as a boolean variable


为什么“ a == b或c或d”总是评估为True?

问题:为什么“ a == b或c或d”总是评估为True?

我正在编写一个拒绝对未授权用户进行访问的安全系统。

import sys

print("Hello. Please enter your name:")
name = sys.stdin.readline().strip()
if name == "Kevin" or "Jon" or "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

它可以按预期授予授权用户访问权限,但也允许未经授权的用户使用!

Hello. Please enter your name:
Bob
Access granted.

为什么会发生这种情况?我已经明确指出仅在name等于Kevin,Jon或Inbar 时才授予访问权限。我也尝试过相反的逻辑if "Kevin" or "Jon" or "Inbar" == name,但是结果是一样的。

I am writing a security system that denies access to unauthorized users.

import sys

print("Hello. Please enter your name:")
name = sys.stdin.readline().strip()
if name == "Kevin" or "Jon" or "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

It grants access to authorized users as expected, but it also lets in unauthorized users!

Hello. Please enter your name:
Bob
Access granted.

Why does this occur? I’ve plainly stated to only grant access when name equals Kevin, Jon, or Inbar. I have also tried the opposite logic, if "Kevin" or "Jon" or "Inbar" == name, but the result is the same.


回答 0

在许多情况下,Python的外观和行为都像自然的英语,但这是这种抽象失败的一种情况。人们可以使用上下文线索来确定“ Jon”和“ Inbar”是与动词“ equals”连接的对象,但是Python解释器具有更多的字面意义。

if name == "Kevin" or "Jon" or "Inbar":

在逻辑上等效于:

if (name == "Kevin") or ("Jon") or ("Inbar"):

对于用户Bob而言,这等效于:

if (False) or ("Jon") or ("Inbar"):

or运营商选择以积极的第一个参数真值

if ("Jon"):

并且由于“ Jon”具有正的真值,因此if执行该块。这就是导致无论给定名称如何都将打印“授予访问权限”的原因。

所有这些推理也适用于表达式if "Kevin" or "Jon" or "Inbar" == name。第一个值,"Kevin"则为true,因此将if执行该块。


正确构造此条件有两种常用方法。

  1. 使用多个==运算符来显式检查每个值:
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. 组成一个有效值序列,并使用in运算符测试成员资格:
    if name in {"Kevin", "Jon", "Inbar"}:

一般而言,第二个应该是首选,因为它更易于阅读,而且速度更快:

>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265

对于那些可能想要if a == b or c or d or e: ...如此解析的证据的人。内置ast模块提供了答案:

>>> import ast
>>> ast.parse("if a == b or c or d or e: ...")
<_ast.Module object at 0x1031ae6a0>
>>> ast.dump(_)
"Module(body=[If(test=BoolOp(op=Or(), values=[Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), Name(id='c', ctx=Load()), Name(id='d', ctx=Load()), Name(id='e', ctx=Load())]), body=[Expr(value=Ellipsis())], orelse=[])])"
>>>

因此test,该if语句的如下所示:

BoolOp(
 op=Or(),
 values=[
  Compare(
   left=Name(id='a', ctx=Load()),
   ops=[Eq()],
   comparators=[Name(id='b', ctx=Load())]
  ),
  Name(id='c', ctx=Load()),
  Name(id='d', ctx=Load()),
  Name(id='e', ctx=Load())
 ]
)

人们可以看到,它的布尔运算符or应用于多个values,即a == bcde

In many cases, Python looks and behaves like natural English, but this is one case where that abstraction fails. People can use context clues to determine that “Jon” and “Inbar” are objects joined to the verb “equals”, but the Python interpreter is more literal minded.

if name == "Kevin" or "Jon" or "Inbar":

is logically equivalent to:

if (name == "Kevin") or ("Jon") or ("Inbar"):

Which, for user Bob, is equivalent to:

if (False) or ("Jon") or ("Inbar"):

The or operator chooses the first argument with a positive truth value:

if ("Jon"):

And since “Jon” has a positive truth value, the if block executes. That is what causes “Access granted” to be printed regardless of the name given.

All of this reasoning also applies to the expression if "Kevin" or "Jon" or "Inbar" == name. the first value, "Kevin", is true, so the if block executes.


There are two common ways to properly construct this conditional.

  1. Use multiple == operators to explicitly check against each value:
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. Compose a sequence of valid values, and use the in operator to test for membership:
    if name in {"Kevin", "Jon", "Inbar"}:

In general of the two the second should be preferred as it’s easier to read and also faster:

>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265

For those who may want proof that if a == b or c or d or e: ... is indeed parsed like this. The built-in ast module provides an answer:

>>> import ast
>>> ast.parse("if a == b or c or d or e: ...")
<_ast.Module object at 0x1031ae6a0>
>>> ast.dump(_)
"Module(body=[If(test=BoolOp(op=Or(), values=[Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), Name(id='c', ctx=Load()), Name(id='d', ctx=Load()), Name(id='e', ctx=Load())]), body=[Expr(value=Ellipsis())], orelse=[])])"
>>>

So the test of the if statement looks like this:

BoolOp(
 op=Or(),
 values=[
  Compare(
   left=Name(id='a', ctx=Load()),
   ops=[Eq()],
   comparators=[Name(id='b', ctx=Load())]
  ),
  Name(id='c', ctx=Load()),
  Name(id='d', ctx=Load()),
  Name(id='e', ctx=Load())
 ]
)

As one can see, it’s the boolean operator or applied to multiple values, namely, a == b and c, d, and e.


回答 1

简单的工程问题,让我们再简单一点。

In [1]: a,b,c,d=1,2,3,4
In [2]: a==b
Out[2]: False

但是,Python继承自语言C,因此将非零整数的逻辑值评估为True。

In [11]: if 3:
    ...:     print ("yey")
    ...:
yey

现在,Python建立在该逻辑的基础上,让您使用诸如或基于整数的逻辑文字。

In [9]: False or 3
Out[9]: 3

最后

In [4]: a==b or c or d
Out[4]: 3

编写它的正确方法是:

In [13]: if a in (b,c,d):
    ...:     print('Access granted')

为了安全起见,我还建议您不要对密码进行硬编码。

Simple engineering problem, let’s simply it a bit further.

In [1]: a,b,c,d=1,2,3,4
In [2]: a==b
Out[2]: False

But, inherited from the language C, Python evaluates the logical value of a non zero integer as True.

In [11]: if 3:
    ...:     print ("yey")
    ...:
yey

Now, Python builds on that logic and let you use logic literals such as or on integers, and so

In [9]: False or 3
Out[9]: 3

Finally

In [4]: a==b or c or d
Out[4]: 3

The proper way to write it would be:

In [13]: if a in (b,c,d):
    ...:     print('Access granted')

For safety I’d also suggest you don’t hard code passwords.


回答 2

有3个条件检查 if name == "Kevin" or "Jon" or "Inbar":

  • 名称==“凯文”
  • “乔恩”
  • “ Inbar”

这个if语句等效于

if name == "Kevin":
    print("Access granted.")
elif "Jon":
    print("Access granted.")
elif "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

由于elif "Jon"将始终为真,因此授予对任何用户的访问权限


您可以使用以下任何一种方法

快速

if name in ["Kevin", "Jon", "Inbar"]:
    print("Access granted.")
else:
    print("Access denied.")

if name == "Kevin" or name == "Jon" or name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

慢+不必要的代码

if name == "Kevin":
    print("Access granted.")
elif name == "Jon":
    print("Access granted.")
elif name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

There are 3 condition checks in if name == "Kevin" or "Jon" or "Inbar":

  • name == “Kevin”
  • “Jon”
  • “Inbar”

and this if statement is equivalent to

if name == "Kevin":
    print("Access granted.")
elif "Jon":
    print("Access granted.")
elif "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

Since elif "Jon" will always be true so access to any user is granted

Solution


You can use any one method below

Fast

if name in ["Kevin", "Jon", "Inbar"]:
    print("Access granted.")
else:
    print("Access denied.")

Slow

if name == "Kevin" or name == "Jon" or name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

Slow + Unnecessary code

if name == "Kevin":
    print("Access granted.")
elif name == "Jon":
    print("Access granted.")
elif name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

布尔在Python中如何格式化为字符串?

问题:布尔在Python中如何格式化为字符串?

我看到我做不到:

"%b %b" % (True, False)

在Python中。我猜%b是b(oolean)。有这样的东西吗?

I see I can’t do:

"%b %b" % (True, False)

in Python. I guessed %b for b(oolean). Is there something like this?


回答 0

>>> print "%r, %r" % (True, False)
True, False

这不是特定于布尔值的- 在参数上%r调用__repr__方法。 %s(对于str)也应该起作用。

>>> print "%r, %r" % (True, False)
True, False

This is not specific to boolean values – %r calls the __repr__ method on the argument. %s (for str) should also work.


回答 1

如果要True False使用:

"%s %s" % (True, False)

因为str(True)'True'str(False)'False'

或者如果您想1 0使用:

"%i %i" % (True, False)

因为int(True)1int(False)0

If you want True False use:

"%s %s" % (True, False)

because str(True) is 'True' and str(False) is 'False'.

or if you want 1 0 use:

"%i %i" % (True, False)

because int(True) is 1 and int(False) is 0.


回答 2

您也可以使用字符串的Formatter类

print "{0} {1}".format(True, False);
print "{0:} {1:}".format(True, False);
print "{0:d} {1:d}".format(True, False);
print "{0:f} {1:f}".format(True, False);
print "{0:e} {1:e}".format(True, False);

这些是结果

True False
True False
1 0
1.000000 0.000000
1.000000e+00 0.000000e+00

某些%-format类型说明符(%r%i)不可用。有关详细信息,请参见格式规范迷你语言

You may also use the Formatter class of string

print "{0} {1}".format(True, False);
print "{0:} {1:}".format(True, False);
print "{0:d} {1:d}".format(True, False);
print "{0:f} {1:f}".format(True, False);
print "{0:e} {1:e}".format(True, False);

These are the results

True False
True False
1 0
1.000000 0.000000
1.000000e+00 0.000000e+00

Some of the %-format type specifiers (%r, %i) are not available. For details see the Format Specification Mini-Language


回答 3

要针对Python-3更新此代码,您可以执行此操作

"{} {}".format(True, False)

但是,如果要实际格式化字符串(例如,添加空格),则会遇到Python将布尔值强制转换为基础C值(即int)的情况,例如

>>> "{:<8} {}".format(True, False)
'1        False'

为了解决这个问题,您可以将True其转换为字符串,例如

>>> "{:<8} {}".format(str(True), False)
'True     False'

To update this for Python-3 you can do this

"{} {}".format(True, False)

However if you want to actually format the string (e.g. add white space), you encounter Python casting the boolean into the underlying C value (i.e. an int), e.g.

>>> "{:<8} {}".format(True, False)
'1        False'

To get around this you can cast True as a string, e.g.

>>> "{:<8} {}".format(str(True), False)
'True     False'

计算Python列表中的True布尔数

问题:计算Python列表中的True布尔数

我有一个布尔值列表:

[True, True, False, False, False, True]

并且我正在寻找一种方法来计算True列表中的数目(因此,在上面的示例中,我希望返回值是3。)我已经找到了一些示例,这些示例寻找特定元素的出现次数。因为我正在使用布尔运算,所以有效的方法吗?我在想类似all或的东西any

I have a list of Booleans:

[True, True, False, False, False, True]

and I am looking for a way to count the number of True in the list (so in the example above, I want the return to be 3.) I have found examples of looking for the number of occurrences of specific elements, but is there a more efficient way to do it since I’m working with Booleans? I’m thinking of something analogous to all or any.


回答 0

True等于1

>>> sum([True, True, False, False, False, True])
3

True is equal to 1.

>>> sum([True, True, False, False, False, True])
3

回答 1

list有一个count方法:

>>> [True,True,False].count(True)
2

这实际上比效率更高sum,并且对意图更明确,因此没有理由使用sum

In [1]: import random

In [2]: x = [random.choice([True, False]) for i in range(100)]

In [3]: %timeit x.count(True)
970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit sum(x)
1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

list has a count method:

>>> [True,True,False].count(True)
2

This is actually more efficient than sum, as well as being more explicit about the intent, so there’s no reason to use sum:

In [1]: import random

In [2]: x = [random.choice([True, False]) for i in range(100)]

In [3]: %timeit x.count(True)
970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit sum(x)
1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

回答 2

如果只关心常量True,那么简单sum就可以了。但是,请记住,在Python中,其他值True也会计算。一个更可靠的解决方案是使用bool内置的:

>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3

更新:这是另一个类似的健壮解决方案,具有更透明的优点:

>>> sum(1 for x in l if x)
3

PS Python琐事:True 可能不为1 可能为真。警告:请勿在工作中尝试!

>>> True = 2
>>> if True: print('true')
... 
true
>>> l = [True, True, False, True]
>>> sum(l)
6
>>> sum(bool(x) for x in l)
3
>>> sum(1 for x in l if x)
3

更多邪恶:

True = False

If you are only concerned with the constant True, a simple sum is fine. However, keep in mind that in Python other values evaluate as True as well. A more robust solution would be to use the bool builtin:

>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3

UPDATE: Here’s another similarly robust solution that has the advantage of being more transparent:

>>> sum(1 for x in l if x)
3

P.S. Python trivia: True could be true without being 1. Warning: do not try this at work!

>>> True = 2
>>> if True: print('true')
... 
true
>>> l = [True, True, False, True]
>>> sum(l)
6
>>> sum(bool(x) for x in l)
3
>>> sum(1 for x in l if x)
3

Much more evil:

True = False

回答 3

您可以使用sum()

>>> sum([True, True, False, False, False, True])
3

You can use sum():

>>> sum([True, True, False, False, False, True])
3

回答 4

仅出于完整性考虑(sum通常更可取),我想提一下我们也可以filter用来获取真实值。在通常情况下,filter接受一个函数作为第一个参数,但是如果传递它None,它将为所有“真实的”值过滤。这个功能有些令人惊讶,但是有充分的文档记录,并且可以在Python 2和3中使用。

版本之间的区别在于,在Python 2中filter返回一个列表,因此我们可以使用len

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
[True, True, True]
>>> len(filter(None, bool_list))
3

但是在Python 3中,filter返回了一个迭代器,因此我们不能使用len,并且如果我们想避免使用sum(出于任何原因),我们需要求助于将迭代器转换为列表(这使它变得不那么美观了):

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

Just for completeness’ sake (sum is usually preferable), I wanted to mention that we can also use filter to get the truthy values. In the usual case, filter accepts a function as the first argument, but if you pass it None, it will filter for all “truthy” values. This feature is somewhat surprising, but is well documented and works in both Python 2 and 3.

The difference between the versions, is that in Python 2 filter returns a list, so we can use len:

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
[True, True, True]
>>> len(filter(None, bool_list))
3

But in Python 3, filter returns an iterator, so we can’t use len, and if we want to avoid using sum (for any reason) we need to resort to converting the iterator to a list (which makes this much less pretty):

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

回答 5

阅读有关该问题的所有答案和评论后,我想做一个小实验。

我产生50000个随机布尔值,并呼吁sumcount他们。

这是我的结果:

>>> a = [bool(random.getrandbits(1)) for x in range(50000)]
>>> len(a)
50000
>>> a.count(False)
24884
>>> a.count(True)
25116
>>> def count_it(a):
...   curr = time.time()
...   counting = a.count(True)
...   print("Count it = " + str(time.time() - curr))
...   return counting
... 
>>> def sum_it(a):
...   curr = time.time()
...   counting = sum(a)
...   print("Sum it = " + str(time.time() - curr))
...   return counting
... 
>>> count_it(a)
Count it = 0.00121307373046875
25015
>>> sum_it(a)
Sum it = 0.004102230072021484
25015

可以肯定的是,我又重复了几次:

>>> count_it(a)
Count it = 0.0013530254364013672
25015
>>> count_it(a)
Count it = 0.0014507770538330078
25015
>>> count_it(a)
Count it = 0.0013344287872314453
25015
>>> sum_it(a)
Sum it = 0.003480195999145508
25015
>>> sum_it(a)
Sum it = 0.0035257339477539062
25015
>>> sum_it(a)
Sum it = 0.003350496292114258
25015
>>> sum_it(a)
Sum it = 0.003744363784790039
25015

如您所见,count速度比快3倍sum。因此,我建议count像在一样使用count_it

Python版本:3.6.7
CPU核心:4
RAM大小:16 GB
操作系统:Ubuntu 18.04.1 LTS

After reading all the answers and comments on this question, I thought to do a small experiment.

I generated 50,000 random booleans and called sum and count on them.

Here are my results:

>>> a = [bool(random.getrandbits(1)) for x in range(50000)]
>>> len(a)
50000
>>> a.count(False)
24884
>>> a.count(True)
25116
>>> def count_it(a):
...   curr = time.time()
...   counting = a.count(True)
...   print("Count it = " + str(time.time() - curr))
...   return counting
... 
>>> def sum_it(a):
...   curr = time.time()
...   counting = sum(a)
...   print("Sum it = " + str(time.time() - curr))
...   return counting
... 
>>> count_it(a)
Count it = 0.00121307373046875
25015
>>> sum_it(a)
Sum it = 0.004102230072021484
25015

Just to be sure, I repeated it several more times:

>>> count_it(a)
Count it = 0.0013530254364013672
25015
>>> count_it(a)
Count it = 0.0014507770538330078
25015
>>> count_it(a)
Count it = 0.0013344287872314453
25015
>>> sum_it(a)
Sum it = 0.003480195999145508
25015
>>> sum_it(a)
Sum it = 0.0035257339477539062
25015
>>> sum_it(a)
Sum it = 0.003350496292114258
25015
>>> sum_it(a)
Sum it = 0.003744363784790039
25015

And as you can see, count is 3 times faster than sum. So I would suggest to use count as I did in count_it.

Python version: 3.6.7
CPU cores: 4
RAM size: 16 GB
OS: Ubuntu 18.04.1 LTS


回答 6

首先进行比较安全bool。这很容易做到:

>>> sum(map(bool,[True, True, False, False, False, True]))
3

然后,您将在适当的存储区中捕获Python认为是或否的所有内容:

>>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
>>> list(map(bool,allTrue))
[True, True, True, True, True, True, True, True, True]

如果您愿意,可以使用一种理解:

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]

It is safer to run through bool first. This is easily done:

>>> sum(map(bool,[True, True, False, False, False, True]))
3

Then you will catch everything that Python considers True or False into the appropriate bucket:

>>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
>>> list(map(bool,allTrue))
[True, True, True, True, True, True, True, True, True]

If you prefer, you can use a comprehension:

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]

回答 7

我更喜欢len([b for b in boollist if b is True])(或等效的generator-expression),因为它很容易解释。比伊格纳西奥·巴斯克斯(Ignacio Vazquez-Abrams)提出的答案更“神奇”。

或者,您可以执行此操作,该操作仍假定bool可转换为int,但不对True的值进行任何假设: ntrue = sum(boollist) / int(True)

I prefer len([b for b in boollist if b is True]) (or the generator-expression equivalent), as it’s quite self-explanatory. Less ‘magical’ than the answer proposed by Ignacio Vazquez-Abrams.

Alternatively, you can do this, which still assumes that bool is convertable to int, but makes no assumptions about the value of True: ntrue = sum(boollist) / int(True)


熊猫中布尔索引的逻辑运算符

问题:熊猫中布尔索引的逻辑运算符

我正在Pandas中使用布尔值索引。问题是为什么声明:

a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]

工作正常而

a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]

退出错误?

例:

a=pd.DataFrame({'x':[1,1],'y':[10,20]})

In: a[(a['x']==1)&(a['y']==10)]
Out:    x   y
     0  1  10

In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous.     Use a.any() or a.all()

I’m working with boolean index in Pandas. The question is why the statement:

a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]

works fine whereas

a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]

exits with error?

Example:

a=pd.DataFrame({'x':[1,1],'y':[10,20]})

In: a[(a['x']==1)&(a['y']==10)]
Out:    x   y
     0  1  10

In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous.     Use a.any() or a.all()

回答 0

当你说

(a['x']==1) and (a['y']==10)

您暗中要求Python进行转换(a['x']==1)并转换(a['y']==10)为布尔值。

NumPy数组(长度大于1)和Pandas对象(例如Series)没有布尔值-换句话说,它们引发

ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().

当用作布尔值时。这是因为尚不清楚何时应为True或False。如果某些用户的长度非零,则可能会认为它们为True,例如Python列表。其他人可能只希望它的所有元素都为真,才希望它为真。如果其他任何元素为True,则其他人可能希望它为True。

由于期望值如此之多,因此NumPy和Pandas的设计师拒绝猜测,而是提出了ValueError。

相反,你必须是明确的,通过调用empty()all()any()方法来表示你的愿望是什么行为。

但是,在这种情况下,您似乎不希望布尔值求值,而是希望按元素进行逻辑与。这就是&二进制运算符执行的操作:

(a['x']==1) & (a['y']==10)

返回一个布尔数组。


顺便说一句,正如alexpmil所指出的,括号是强制性的,因为&运算符优先级高于==。如果没有括号,a['x']==1 & a['y']==10则将被评估为a['x'] == (1 & a['y']) == 10等效于链式比较(a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10)。那是形式的表达Series and Seriesand与两个Series一起使用将再次触发与ValueError上述相同的操作。这就是为什么括号是强制性的。

When you say

(a['x']==1) and (a['y']==10)

You are implicitly asking Python to convert (a['x']==1) and (a['y']==10) to boolean values.

NumPy arrays (of length greater than 1) and Pandas objects such as Series do not have a boolean value — in other words, they raise

ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().

when used as a boolean value. That’s because its unclear when it should be True or False. Some users might assume they are True if they have non-zero length, like a Python list. Others might desire for it to be True only if all its elements are True. Others might want it to be True if any of its elements are True.

Because there are so many conflicting expectations, the designers of NumPy and Pandas refuse to guess, and instead raise a ValueError.

Instead, you must be explicit, by calling the empty(), all() or any() method to indicate which behavior you desire.

In this case, however, it looks like you do not want boolean evaluation, you want element-wise logical-and. That is what the & binary operator performs:

(a['x']==1) & (a['y']==10)

returns a boolean array.


By the way, as alexpmil notes, the parentheses are mandatory since & has a higher operator precedence than ==. Without the parentheses, a['x']==1 & a['y']==10 would be evaluated as a['x'] == (1 & a['y']) == 10 which would in turn be equivalent to the chained comparison (a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10). That is an expression of the form Series and Series. The use of and with two Series would again trigger the same ValueError as above. That’s why the parentheses are mandatory.


回答 1

TLDR;在熊猫逻辑运算符&|~和括号(...)是很重要的!

Python的andornot逻辑运算符的设计与标量的工作。因此,Pandas必须做得更好,并覆盖按位运算符,以实现此功能的矢量化(逐元素)版本。

因此,以下是python中的(exp1以及exp2是计算结果为布尔结果的表达式)…

exp1 and exp2              # Logical AND
exp1 or exp2               # Logical OR
not exp1                   # Logical NOT

…将转换为…

exp1 & exp2                # Element-wise logical AND
exp1 | exp2                # Element-wise logical OR
~exp1                      # Element-wise logical NOT

大熊猫。

如果在执行逻辑运算的过程中得到ValueError,则需要使用括号进行分组:

(exp1) op (exp2)

例如,

(df['col1'] == x) & (df['col2'] == y) 

等等。


布尔索引:常见的操作是通过逻辑条件来计算布尔掩码,以过滤数据。熊猫提供了三种运算符:&用于逻辑与,|逻辑或,以及~逻辑非。

请考虑以下设置:

np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df

   A  B  C
0  5  0  3
1  3  7  9
2  3  5  2
3  4  7  6
4  8  8  1

逻辑与

对于df上面的内容,假设您想返回A <5和B> 5的所有行。这是通过分别计算每个条件的掩码并将它们与与完成的。

重载的按位&运算符
在继续之前,请注意文档的此特定摘录,其中指出

另一个常见的操作是使用布尔向量来过滤数据。运算符是:|for or&for and~for not这些必须通过使用括号来分组,由于由默认的Python将评估的表达式如df.A > 2 & df.B < 3df.A > (2 & df.B) < 3,而所期望的评价顺序是(df.A > 2) & (df.B < 3)

因此,考虑到这一点,可以使用按位运算符实现按元素逻辑与&

df['A'] < 5

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'] > 5

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

(df['A'] < 5) & (df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

接下来的过滤步骤很简单,

df[(df['A'] < 5) & (df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

括号用于覆盖按位运算符的默认优先级顺序,后者比条件运算符<和具有更高的优先级>。请参阅python文档中的“ 运算符优先级 ”部分。

如果不使用括号,则表达式的计算不正确。例如,如果您不小心尝试了诸如

df['A'] < 5 & df['B'] > 5

它被解析为

df['A'] < (5 & df['B']) > 5

变成

df['A'] < something_you_dont_want > 5

变成了(请参阅有关链接运算符比较的python文档),

(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)

变成

# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2

哪个抛出

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

所以,不要犯那个错误!1个

避免括号分组
该修补程序实际上非常简单。大多数运算符都有对应的DataFrame绑定方法。如果使用函数而不是条件运算符来构建单个掩码,则不再需要按括号分组以指定评估顺序:

df['A'].lt(5)

0     True
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'].gt(5)

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

df['A'].lt(5) & df['B'].gt(5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

请参阅“ 灵活比较 ”部分。总而言之,我们有

╒════╤════════════╤════════════╕
     Operator    Function   
╞════╪════════════╪════════════╡
  0  >           gt         
├────┼────────────┼────────────┤
  1  >=          ge         
├────┼────────────┼────────────┤
  2  <           lt         
├────┼────────────┼────────────┤
  3  <=          le         
├────┼────────────┼────────────┤
  4  ==          eq         
├────┼────────────┼────────────┤
  5  !=          ne         
╘════╧════════════╧════════════╛

避免括号的另一种方法是使用DataFrame.query(或eval):

df.query('A < 5 and B > 5')

   A  B  C
1  3  7  9
3  4  7  6

我已经广泛地记录queryeval使用pd.eval动态表达评价大熊猫()

operator.and_
允许您以功能方式执行此操作。内部调用Series.__and__,它对应于按位运算符。

import operator 

operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5) 

0    False
1     True
2    False
3     True
4    False
dtype: bool

df[operator.and_(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

您通常不需要此功能,但了解它很有用。

概括:(np.logical_andlogical_and.reduce
另一种替代方法是使用 np.logical_and,它也不需要括号分组:

np.logical_and(df['A'] < 5, df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
Name: A, dtype: bool

df[np.logical_and(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

np.logical_and是ufunc (通用函数),大多数ufunc都有一个reduce方法。这意味着logical_and如果对AND有多个掩码,则更容易一概而论。例如,对于AND遮罩m1以及m2m3&,您必须要做

m1 & m2 & m3

但是,一个更简单的选择是

np.logical_and.reduce([m1, m2, m3])

这很强大,因为它使您可以使用更复杂的逻辑在此基础上构建(例如,在列表理解中动态生成掩码并添加所有掩码):

import operator

cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]

m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m 
# array([False,  True, False,  True, False])

df[m]
   A  B  C
1  3  7  9
3  4  7  6

1-我知道我在这一点上很困难,但是请耐心等待。这是一个非常非常常见的初学者的错误,必须非常有详尽的解释。


逻辑或

对于df上述内容,假设您想返回A == 3或B == 7的所有行。

按位重载 |

df['A'] == 3

0    False
1     True
2     True
3    False
4    False
Name: A, dtype: bool

df['B'] == 7

0    False
1     True
2    False
3     True
4    False
Name: B, dtype: bool

(df['A'] == 3) | (df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[(df['A'] == 3) | (df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

如果您还没有阅读过,请同时阅读上面“ 逻辑与 ”部分,所有注意事项均在此处适用。

或者,可以使用

df[df['A'].eq(3) | df['B'].eq(7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

operator.or_
在后台调用Series.__or__

operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[operator.or_(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

np.logical_or
对于两个条件,请使用logical_or

np.logical_or(df['A'] == 3, df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df[np.logical_or(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

对于多个口罩,请使用logical_or.reduce

np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False,  True,  True,  True, False])

df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

逻辑非

给定口罩,例如

mask = pd.Series([True, True, False])

如果您需要反转每个布尔值(以使最终结果为[False, False, True]),则可以使用以下任何方法。

按位 ~

~mask

0    False
1    False
2     True
dtype: bool

同样,表达式需要加上括号。

~(df['A'] == 3)

0     True
1    False
2    False
3     True
4     True
Name: A, dtype: bool

这在内部调用

mask.__invert__()

0    False
1    False
2     True
dtype: bool

但是不要直接使用它。

operator.inv
内部调用__invert__该系列。

operator.inv(mask)

0    False
1    False
2     True
dtype: bool

np.logical_not
这是numpy的变体。

np.logical_not(mask)

0    False
1    False
2     True
dtype: bool

注意,np.logical_and可以代替np.bitwise_andlogical_orbitwise_or,并logical_notinvert

TLDR; Logical Operators in Pandas are &, | and ~, and parentheses (...) is important!

Python’s and, or and not logical operators are designed to work with scalars. So Pandas had to do one better and override the bitwise operators to achieve vectorized (element-wise) version of this functionality.

So the following in python (exp1 and exp2 are expressions which evaluate to a boolean result)…

exp1 and exp2              # Logical AND
exp1 or exp2               # Logical OR
not exp1                   # Logical NOT

…will translate to…

exp1 & exp2                # Element-wise logical AND
exp1 | exp2                # Element-wise logical OR
~exp1                      # Element-wise logical NOT

for pandas.

If in the process of performing logical operation you get a ValueError, then you need to use parentheses for grouping:

(exp1) op (exp2)

For example,

(df['col1'] == x) & (df['col2'] == y) 

And so on.


Boolean Indexing: A common operation is to compute boolean masks through logical conditions to filter the data. Pandas provides three operators: & for logical AND, | for logical OR, and ~ for logical NOT.

Consider the following setup:

np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df

   A  B  C
0  5  0  3
1  3  7  9
2  3  5  2
3  4  7  6
4  8  8  1

Logical AND

For df above, say you’d like to return all rows where A < 5 and B > 5. This is done by computing masks for each condition separately, and ANDing them.

Overloaded Bitwise & Operator
Before continuing, please take note of this particular excerpt of the docs, which state

Another common operation is the use of boolean vectors to filter the data. The operators are: | for or, & for and, and ~ for not. These must be grouped by using parentheses, since by default Python will evaluate an expression such as df.A > 2 & df.B < 3 as df.A > (2 & df.B) < 3, while the desired evaluation order is (df.A > 2) & (df.B < 3).

So, with this in mind, element wise logical AND can be implemented with the bitwise operator &:

df['A'] < 5

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'] > 5

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

(df['A'] < 5) & (df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

And the subsequent filtering step is simply,

df[(df['A'] < 5) & (df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

The parentheses are used to override the default precedence order of bitwise operators, which have higher precedence over the conditional operators < and >. See the section of Operator Precedence in the python docs.

If you do not use parentheses, the expression is evaluated incorrectly. For example, if you accidentally attempt something such as

df['A'] < 5 & df['B'] > 5

It is parsed as

df['A'] < (5 & df['B']) > 5

Which becomes,

df['A'] < something_you_dont_want > 5

Which becomes (see the python docs on chained operator comparison),

(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)

Which becomes,

# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2

Which throws

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

So, don’t make that mistake!1

Avoiding Parentheses Grouping
The fix is actually quite simple. Most operators have a corresponding bound method for DataFrames. If the individual masks are built up using functions instead of conditional operators, you will no longer need to group by parens to specify evaluation order:

df['A'].lt(5)

0     True
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'].gt(5)

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

df['A'].lt(5) & df['B'].gt(5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

See the section on Flexible Comparisons.. To summarise, we have

╒════╤════════════╤════════════╕
│    │ Operator   │ Function   │
╞════╪════════════╪════════════╡
│  0 │ >          │ gt         │
├────┼────────────┼────────────┤
│  1 │ >=         │ ge         │
├────┼────────────┼────────────┤
│  2 │ <          │ lt         │
├────┼────────────┼────────────┤
│  3 │ <=         │ le         │
├────┼────────────┼────────────┤
│  4 │ ==         │ eq         │
├────┼────────────┼────────────┤
│  5 │ !=         │ ne         │
╘════╧════════════╧════════════╛

Another option for avoiding parentheses is to use DataFrame.query (or eval):

df.query('A < 5 and B > 5')

   A  B  C
1  3  7  9
3  4  7  6

I have extensively documented query and eval in Dynamic Expression Evaluation in pandas using pd.eval().

operator.and_
Allows you to perform this operation in a functional manner. Internally calls Series.__and__ which corresponds to the bitwise operator.

import operator 

operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5) 

0    False
1     True
2    False
3     True
4    False
dtype: bool

df[operator.and_(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

You won’t usually need this, but it is useful to know.

Generalizing: np.logical_and (and logical_and.reduce)
Another alternative is using np.logical_and, which also does not need parentheses grouping:

np.logical_and(df['A'] < 5, df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
Name: A, dtype: bool

df[np.logical_and(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

np.logical_and is a ufunc (Universal Functions), and most ufuncs have a reduce method. This means it is easier to generalise with logical_and if you have multiple masks to AND. For example, to AND masks m1 and m2 and m3 with &, you would have to do

m1 & m2 & m3

However, an easier option is

np.logical_and.reduce([m1, m2, m3])

This is powerful, because it lets you build on top of this with more complex logic (for example, dynamically generating masks in a list comprehension and adding all of them):

import operator

cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]

m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m 
# array([False,  True, False,  True, False])

df[m]
   A  B  C
1  3  7  9
3  4  7  6

1 – I know I’m harping on this point, but please bear with me. This is a very, very common beginner’s mistake, and must be explained very thoroughly.


Logical OR

For the df above, say you’d like to return all rows where A == 3 or B == 7.

Overloaded Bitwise |

df['A'] == 3

0    False
1     True
2     True
3    False
4    False
Name: A, dtype: bool

df['B'] == 7

0    False
1     True
2    False
3     True
4    False
Name: B, dtype: bool

(df['A'] == 3) | (df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[(df['A'] == 3) | (df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

If you haven’t yet, please also read the section on Logical AND above, all caveats apply here.

Alternatively, this operation can be specified with

df[df['A'].eq(3) | df['B'].eq(7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

operator.or_
Calls Series.__or__ under the hood.

operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[operator.or_(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

np.logical_or
For two conditions, use logical_or:

np.logical_or(df['A'] == 3, df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df[np.logical_or(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

For multiple masks, use logical_or.reduce:

np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False,  True,  True,  True, False])

df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

Logical NOT

Given a mask, such as

mask = pd.Series([True, True, False])

If you need to invert every boolean value (so that the end result is [False, False, True]), then you can use any of the methods below.

Bitwise ~

~mask

0    False
1    False
2     True
dtype: bool

Again, expressions need to be parenthesised.

~(df['A'] == 3)

0     True
1    False
2    False
3     True
4     True
Name: A, dtype: bool

This internally calls

mask.__invert__()

0    False
1    False
2     True
dtype: bool

But don’t use it directly.

operator.inv
Internally calls __invert__ on the Series.

operator.inv(mask)

0    False
1    False
2     True
dtype: bool

np.logical_not
This is the numpy variant.

np.logical_not(mask)

0    False
1    False
2     True
dtype: bool

Note, np.logical_and can be substituted for np.bitwise_and, logical_or with bitwise_or, and logical_not with invert.


回答 2

熊猫中布尔索引的逻辑运算符

要认识到,你不能使用任何的Python是很重要的逻辑运算符andornot上)pandas.Seriespandas.DataFrameS(同样,你不能上使用它们numpy.array有一个以上的元素S)。之所以不能使用它们,是因为它们隐式地调用bool其操作数,从而引发异常,因为这些数据结构确定数组的布尔值是不明确的:

>>> import numpy as np
>>> import pandas as pd
>>> arr = np.array([1,2,3])
>>> s = pd.Series([1,2,3])
>>> df = pd.DataFrame([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> bool(df)
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

我确实在回答“系列的真值不明确。请使用a.empty,a.bool(),a.item(),a.any()或a.all()”时回答这个问题。 + A

NumPys逻辑功能

然而NumPy的提供逐元素的操作等同于这些运营商的功能,可以在被使用numpy.arraypandas.Seriespandas.DataFrame,或任何其他(符合)numpy.array亚类:

因此,从本质上讲,应该使用(假设df1并且df2是pandas DataFrames):

np.logical_and(df1, df2)
np.logical_or(df1, df2)
np.logical_not(df1)
np.logical_xor(df1, df2)

布尔的按位函数和按位运算符

但是,如果您具有布尔NumPy数组,pandas系列或pandas DataFrame,则也可以使用按元素逐位的函数(对于布尔,它们与逻辑函数是(或至少应该是)不可区分的):

通常使用运算符。但是,当与比较运算符组合使用时,必须记住将比较括在括号中,因为按位运算符的优先级高于比较运算符

(df1 < 10) | (df2 > 10)  # instead of the wrong df1 < 10 | df2 > 10

这可能很烦人,因为Python逻辑运算符的优先级比比较运算符的优先级低,因此您通常可以编写a < 10 and b > 10(其中a并且b是简单整数),并且不需要括号。

逻辑和按位运算之间的差异(非布尔值)

需要特别强调的是,位和逻辑运算仅对布尔NumPy数组(以及布尔Series和DataFrame)是等效的。如果这些不包含布尔值,则这些操作将给出不同的结果。我将包括使用NumPy数组的示例,但对于pandas数据结构,结果将相似:

>>> import numpy as np
>>> a1 = np.array([0, 0, 1, 1])
>>> a2 = np.array([0, 1, 0, 1])

>>> np.logical_and(a1, a2)
array([False, False, False,  True])
>>> np.bitwise_and(a1, a2)
array([0, 0, 0, 1], dtype=int32)

而且由于NumPy(和类似的pandas)对boolean(布尔或“掩码”索引数组)和integer(Index数组)索引所做的操作不同,因此索引的结果也将不同:

>>> a3 = np.array([1, 2, 3, 4])

>>> a3[np.logical_and(a1, a2)]
array([4])
>>> a3[np.bitwise_and(a1, a2)]
array([1, 1, 1, 2])

汇总表

Logical operator | NumPy logical function | NumPy bitwise function | Bitwise operator
-------------------------------------------------------------------------------------
       and       |  np.logical_and        | np.bitwise_and         |        &
-------------------------------------------------------------------------------------
       or        |  np.logical_or         | np.bitwise_or          |        |
-------------------------------------------------------------------------------------
                 |  np.logical_xor        | np.bitwise_xor         |        ^
-------------------------------------------------------------------------------------
       not       |  np.logical_not        | np.invert              |        ~

其中的逻辑运算符不适合与NumPy阵列工作,熊猫系列,和熊猫DataFrames。其他的则在这些数据结构(和普通的Python对象)上工作,并在元素方面工作。但是,请对纯Python上的按位取反要小心,bool因为在这种情况下,布尔将被解释为整数(例如~Falsereturn -1~Truereturn -2)。

Logical operators for boolean indexing in Pandas

It’s important to realize that you cannot use any of the Python logical operators (and, or or not) on pandas.Series or pandas.DataFrames (similarly you cannot use them on numpy.arrays with more than one element). The reason why you cannot use those is because they implicitly call bool on their operands which throws an Exception because these data structures decided that the boolean of an array is ambiguous:

>>> import numpy as np
>>> import pandas as pd
>>> arr = np.array([1,2,3])
>>> s = pd.Series([1,2,3])
>>> df = pd.DataFrame([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> bool(df)
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

I did cover this more extensively in my answer to the “Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()” Q+A.

NumPys logical functions

However NumPy provides element-wise operating equivalents to these operators as functions that can be used on numpy.array, pandas.Series, pandas.DataFrame, or any other (conforming) numpy.array subclass:

So, essentially, one should use (assuming df1 and df2 are pandas DataFrames):

np.logical_and(df1, df2)
np.logical_or(df1, df2)
np.logical_not(df1)
np.logical_xor(df1, df2)

Bitwise functions and bitwise operators for booleans

However in case you have boolean NumPy array, pandas Series, or pandas DataFrames you could also use the element-wise bitwise functions (for booleans they are – or at least should be – indistinguishable from the logical functions):

Typically the operators are used. However when combined with comparison operators one has to remember to wrap the comparison in parenthesis because the bitwise operators have a higher precedence than the comparison operators:

(df1 < 10) | (df2 > 10)  # instead of the wrong df1 < 10 | df2 > 10

This may be irritating because the Python logical operators have a lower precendence than the comparison operators so you normally write a < 10 and b > 10 (where a and b are for example simple integers) and don’t need the parenthesis.

Differences between logical and bitwise operations (on non-booleans)

It is really important to stress that bit and logical operations are only equivalent for boolean NumPy arrays (and boolean Series & DataFrames). If these don’t contain booleans then the operations will give different results. I’ll include examples using NumPy arrays but the results will be similar for the pandas data structures:

>>> import numpy as np
>>> a1 = np.array([0, 0, 1, 1])
>>> a2 = np.array([0, 1, 0, 1])

>>> np.logical_and(a1, a2)
array([False, False, False,  True])
>>> np.bitwise_and(a1, a2)
array([0, 0, 0, 1], dtype=int32)

And since NumPy (and similarly pandas) does different things for boolean (Boolean or “mask” index arrays) and integer (Index arrays) indices the results of indexing will be also be different:

>>> a3 = np.array([1, 2, 3, 4])

>>> a3[np.logical_and(a1, a2)]
array([4])
>>> a3[np.bitwise_and(a1, a2)]
array([1, 1, 1, 2])

Summary table

Logical operator | NumPy logical function | NumPy bitwise function | Bitwise operator
-------------------------------------------------------------------------------------
       and       |  np.logical_and        | np.bitwise_and         |        &
-------------------------------------------------------------------------------------
       or        |  np.logical_or         | np.bitwise_or          |        |
-------------------------------------------------------------------------------------
                 |  np.logical_xor        | np.bitwise_xor         |        ^
-------------------------------------------------------------------------------------
       not       |  np.logical_not        | np.invert              |        ~

Where the logical operator does not work for NumPy arrays, pandas Series, and pandas DataFrames. The others work on these data structures (and plain Python objects) and work element-wise. However be careful with the bitwise invert on plain Python bools because the bool will be interpreted as integers in this context (for example ~False returns -1 and ~True returns -2).


如何创建全为真或全为假的numpy数组?

问题:如何创建全为真或全为假的numpy数组?

在Python中,如何创建由全True或全False填充的任意形状的numpy数组?

In Python, how do I create a numpy array of arbitrary shape filled with all True or all False?


回答 0

numpy已经可以非常容易地创建全1或全0的数组:

例如numpy.ones((2, 2))numpy.zeros((2, 2))

由于TrueFalsePython中被表示为10,分别,我们只有指定这个数组应该是布尔使用可选dtype参数,我们正在这样做。

numpy.ones((2, 2), dtype=bool)

返回:

array([[ True,  True],
       [ True,  True]], dtype=bool)

更新:2013年10月30日

从numpy 版本1.8开始,我们可以使用full语法更清楚地表明我们意图的语法来达到相同的结果(如fmonegaglia指出):

numpy.full((2, 2), True, dtype=bool)

更新:2017年1月16日

因为至少numpy的1.12版full自动转换结果到了dtype第二个参数,所以我们可以这样写:

numpy.full((2, 2), True)

numpy already allows the creation of arrays of all ones or all zeros very easily:

e.g. numpy.ones((2, 2)) or numpy.zeros((2, 2))

Since True and False are represented in Python as 1 and 0, respectively, we have only to specify this array should be boolean using the optional dtype parameter and we are done.

numpy.ones((2, 2), dtype=bool)

returns:

array([[ True,  True],
       [ True,  True]], dtype=bool)

UPDATE: 30 October 2013

Since numpy version 1.8, we can use full to achieve the same result with syntax that more clearly shows our intent (as fmonegaglia points out):

numpy.full((2, 2), True, dtype=bool)

UPDATE: 16 January 2017

Since at least numpy version 1.12, full automatically casts results to the dtype of the second parameter, so we can just write:

numpy.full((2, 2), True)


回答 1

numpy.full((2,2), True, dtype=bool)
numpy.full((2,2), True, dtype=bool)

回答 2

ones和和zeros分别创建一个全为1和0的数组,它们带有一个可选dtype参数:

>>> numpy.ones((2, 2), dtype=bool)
array([[ True,  True],
       [ True,  True]], dtype=bool)
>>> numpy.zeros((2, 2), dtype=bool)
array([[False, False],
       [False, False]], dtype=bool)

ones and zeros, which create arrays full of ones and zeros respectively, take an optional dtype parameter:

>>> numpy.ones((2, 2), dtype=bool)
array([[ True,  True],
       [ True,  True]], dtype=bool)
>>> numpy.zeros((2, 2), dtype=bool)
array([[False, False],
       [False, False]], dtype=bool)

回答 3

如果它不是可写的,则可以使用以下方法创建这样的数组np.broadcast_to

>>> import numpy as np
>>> np.broadcast_to(True, (2, 5))
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]], dtype=bool)

如果需要可写,也可以fill自己创建一个空数组:

>>> arr = np.empty((2, 5), dtype=bool)
>>> arr.fill(1)
>>> arr
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]], dtype=bool)

这些方法只是替代建议。通常,您应该坚持np.fullnp.zeros或者np.ones像其他答案所建议的那样。

If it doesn’t have to be writeable you can create such an array with np.broadcast_to:

>>> import numpy as np
>>> np.broadcast_to(True, (2, 5))
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]], dtype=bool)

If you need it writable you can also create an empty array and fill it yourself:

>>> arr = np.empty((2, 5), dtype=bool)
>>> arr.fill(1)
>>> arr
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]], dtype=bool)

These approaches are only alternative suggestions. In general you should stick with np.full, np.zeros or np.ones like the other answers suggest.


回答 4

快速运行一个timeit,以查看np.full和之间是否有任何差异np.ones版本。

答:不可以

import timeit

n_array, n_test = 1000, 10000
setup = f"import numpy as np; n = {n_array};"

print(f"np.ones: {timeit.timeit('np.ones((n, n), dtype=bool)', number=n_test, setup=setup)}s")
print(f"np.full: {timeit.timeit('np.full((n, n), True)', number=n_test, setup=setup)}s")

结果:

np.ones: 0.38416870904620737s
np.full: 0.38430388597771525s


重要

关于帖子np.empty(由于声誉太低,我无法评论):

不要那样做。请勿使用np.empty初始化全True数组

由于数组为空,因此不会写入内存,也无法保证您的值是多少,例如

>>> print(np.empty((4,4), dtype=bool))
[[ True  True  True  True]
 [ True  True  True  True]
 [ True  True  True  True]
 [ True  True False False]]

Quickly ran a timeit to see, if there are any differences between the np.full and np.ones version.

Answer: No

import timeit

n_array, n_test = 1000, 10000
setup = f"import numpy as np; n = {n_array};"

print(f"np.ones: {timeit.timeit('np.ones((n, n), dtype=bool)', number=n_test, setup=setup)}s")
print(f"np.full: {timeit.timeit('np.full((n, n), True)', number=n_test, setup=setup)}s")

Result:

np.ones: 0.38416870904620737s
np.full: 0.38430388597771525s


IMPORTANT

Regarding the post about np.empty (and I cannot comment, as my reputation is too low):

DON’T DO THAT. DON’T USE np.empty to initialize an all-True array

As the array is empty, the memory is not written and there is no guarantee, what your values will be, e.g.

>>> print(np.empty((4,4), dtype=bool))
[[ True  True  True  True]
 [ True  True  True  True]
 [ True  True  True  True]
 [ True  True False False]]

回答 5

>>> a = numpy.full((2,4), True, dtype=bool)
>>> a[1][3]
True
>>> a
array([[ True,  True,  True,  True],
       [ True,  True,  True,  True]], dtype=bool)

numpy.full(大小,标量值,类型)。也可以传递其他参数,有关文档,请检查https://docs.scipy.org/doc/numpy/reference/produced/numpy.full.html

>>> a = numpy.full((2,4), True, dtype=bool)
>>> a[1][3]
True
>>> a
array([[ True,  True,  True,  True],
       [ True,  True,  True,  True]], dtype=bool)

numpy.full(Size, Scalar Value, Type). There is other arguments as well that can be passed, for documentation on that, check https://docs.scipy.org/doc/numpy/reference/generated/numpy.full.html


False == 0和True == 1是实现细节还是由语言保证?

问题:False == 0和True == 1是实现细节还是由语言保证?

是否可以保证False == 0True == 1,在Python中(假设用户没有重新分配它们)?例如,是否以任何方式保证以下代码将始终产生相同的结果,而不管Python的版本如何(既有现有版本,也可能是未来版本)?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

任何对官方文档的引用将不胜感激!

编辑:如许多答案所述,bool继承自int。因此,可以将问题改写为:“文档是否正式声明程序员可以依赖从整数(带有值01?)继承的布尔 ”。这个问题与编写不会因为实现细节而失败的健壮代码有关!

Is it guaranteed that False == 0 and True == 1, in Python (assuming that they are not reassigned by the user)? For instance, is it in any way guaranteed that the following code will always produce the same results, whatever the version of Python (both existing and, likely, future ones)?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Any reference to the official documentation would be much appreciated!

Edit: As noted in many answers, bool inherits from int. The question can therefore be recast as: “Does the documentation officially say that programmers can rely on booleans inheriting from integers, with the values 0 and 1?”. This question is relevant for writing robust code that won’t fail because of implementation details!


回答 0

在Python 2.x的,这是没有保证的,因为它是可能的True,并False重新分配。但是,即使发生这种情况,仍然正确返回布尔True和布尔False进行比较。

在Python 3.x中,TrueFalse是关键字,并且始终等于10

通常情况下,在Python 2中,并且始终在Python 3中:

False对象的类型bool是的子类int

object
   |
 int
   |
 bool

这是在您的示例['zero', 'one'][False]中起作用的唯一原因。它不适用于不是整数子类的对象,因为列表索引仅适用于整数或定义__index__方法的对象(感谢mark-dickinson)。

编辑:

当前的python版本和Python 3都是如此。python 2.6文档和python 3文档都说:

整数有两种类型:[…]整数(int)[…]布尔值(bool)

在布尔小节中:

布尔值:它们表示真值False和True布尔值在几乎所有上下文中的行为分别类似于值0和1,但exceptions是当转换为字符串时,字符串“ False”或“ True”分别返回。

对于Python 2也有:

在数字上下文中(例如,用作算术运算符的参数时),它们的[False和True]分别类似于整数0和1。

因此,布尔值在Python 2.6和3中被明确视为整数。

因此,在Python 4出现之前,您是安全的。;-)

In Python 2.x this is not guaranteed as it is possible for True and False to be reassigned. However, even if this happens, boolean True and boolean False are still properly returned for comparisons.

In Python 3.x True and False are keywords and will always be equal to 1 and 0.

Under normal circumstances in Python 2, and always in Python 3:

False object is of type bool which is a subclass of int:

object
   |
 int
   |
 bool

It is the only reason why in your example, ['zero', 'one'][False] does work. It would not work with an object which is not a subclass of integer, because list indexing only works with integers, or objects that define a __index__ method (thanks mark-dickinson).

Edit:

It is true of the current python version, and of that of Python 3. The docs for python 2.6 and the docs for Python 3 both say:

There are two types of integers: […] Integers (int) […] Booleans (bool)

and in the boolean subsection:

Booleans: These represent the truth values False and True […] Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings “False” or “True” are returned, respectively.

There is also, for Python 2:

In numeric contexts (for example when used as the argument to an arithmetic operator), they [False and True] behave like the integers 0 and 1, respectively.

So booleans are explicitly considered as integers in Python 2.6 and 3.

So you’re safe until Python 4 comes along. ;-)


回答 1

链接到PEP讨论Python 2.3中的新布尔类型:http : //www.python.org/dev/peps/pep-0285/

将布尔值转换为int时,整数值始终为0或1,但是将int值转换为bool时,除0以外的所有整数的布尔值均为True。

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

Link to the PEP discussing the new bool type in Python 2.3: http://www.python.org/dev/peps/pep-0285/.

When converting a bool to an int, the integer value is always 0 or 1, but when converting an int to a bool, the boolean value is True for all integers except 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

回答 2

在Python 2.x中,根本无法保证:

>>> False = 5
>>> 0 == False
False

因此它可能会改变。在Python 3.x中,True,False和None是保留字,因此上面的代码不起作用。

通常,使用布尔值时,您应该假设False始终具有0的整数值(只要您不进行上述更改即可),True可以具有任何其他值。我不一定要依靠True==1,但是在Python 3.x上,无论如何,情况总是如此。

In Python 2.x, it is not guaranteed at all:

>>> False = 5
>>> 0 == False
False

So it could change. In Python 3.x, True, False, and None are reserved words, so the above code would not work.

In general, with booleans you should assume that while False will always have an integer value of 0 (so long as you don’t change it, as above), True could have any other value. I wouldn’t necessarily rely on any guarantee that True==1, but on Python 3.x, this will always be the case, no matter what.


回答 3

很简单。由于布尔与将整数评估为布尔有关,因此只有0给出错误的答案。所有非零值,浮点数,整数(包括负数)或您拥有的所有值都将返回true。

一个为什么有用的很好的例子是确定设备的电源状态。On是任何非零值,off是零。从电子上讲,这是有道理的。

若要相对确定值之间的正确或错误,您必须将其与之进行比较。这适用于字符串和数值,使用==!=<> >=<=等。

您可以为变量分配一个整数,然后根据该变量值获得true或false。

Very simple. As bool relates to evaluating an integer as a bool, ONLY zero gives a false answer. ALL Non-Zero values, floats, integers, including negative numbers, or what have you, will return true.

A nice example of why this is useful is determining the power status of a device. On is any non-zero value, off is zero. Electronically speaking this makes sense.

To determine true or false relatively between values, you must have something to compare it to. This applies to strings and number values, using == or != or <, > >=, <=, etc.

You can assign an integer to a variable and then get true or false based on that variable value.


回答 4

只需编写int(False),您将得到0,如果键入int(True)它将输出1

Just write int(False) and you will get 0, if you type int(True) it will output 1


回答 5

假是布尔。它具有不同的类型。它是不同于整数的0的对象。

0 == False因为将False强制转换为整数,所以返回True。int(False)返回0

==运算符的python文档说(help(’==’)):

运营商<>==>=<=,和!=比较两个对象的值。这些对象不必具有相同的类型。如果两者都是数字,则它们将转换为通用类型。

结果,需要比较时将False转换为整数。但它不同于0。

>>> 0 is False
False

False is a bool. It has a different type. It is a different object from 0 which is an integer.

0 == False returns True because False is cast to an integer. int(False) returns 0

The python documentation of the == operator says (help(‘==’)):

The operators <, >, ==, >=, <=, and != compare the values of two objects. The objects need not have the same type. If both are numbers, they are converted to a common type.

As a consequence False is converted to an integer for the need of the comparison. But it is different from 0.

>>> 0 is False
False