Làm cách nào để lấy ngược lại (phủ định) của Boolean trong Python?


106

Đối với mẫu sau:

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

Có cách nào để bỏ qua câu lệnh if thứ hai không? Chỉ để yêu cầu máy tính trả về điều ngược lại của boolean bool?


6
Đây có thể chỉ là mã giả, nhưng intboolđều là tên nội trang (cho các loại mà chúng đại diện), và không được sử dụng làm tên biến.
SingleNegationElimination

vâng, nó chỉ là một pseudo-code ,, mục đích cuộc biểu tình chỉ ...
amyassin

7
if x == True:nên được viết if x:.
Mike Graham

Câu trả lời:


180

Bạn chỉ có thể sử dụng:

return not bool

4
Ngoài ra, int in range (....)là không hiệu quả. Nó sẽ tạo một danh sách và sau đó thực hiện tìm kiếm tuyến tính. Tốt hơn x in range(low, high)là tốt hơn low <= x < high.
MRAB

Lưu ý rằng not Nonesẽ trả về False. Ít nhất đối với tôi đó không phải là những gì tôi mong đợi. Tôi mong đợi not NoneNonenhư vậy notcó thể được sử dụng để phủ định ngay cả khi giá trị trả về có thể là None. Cách nó được triển khai bằng Python, bạn sẽ phải xác minh rằng bạn thực sự có boolean trước.
masi

54

Các notnhà điều hành (phủ định logic)

Có lẽ cách tốt nhất là sử dụng toán tử not:

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

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

Vì vậy, thay vì mã của bạn:

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

Bạn đã có thể sử dụng:

return not bool

Sự phủ định lôgic như một chức năng

Ngoài ra còn có hai hàm trong operatormô-đun operator.not_và đó là bí danh operator.__not__trong trường hợp bạn cần nó dưới dạng hàm thay vì dưới dạng toán tử:

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

Những điều này có thể hữu ích nếu bạn muốn sử dụng một hàm yêu cầu một hàm vị từ hoặc một hàm gọi lại.

Ví dụ maphoặc 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]

Tất nhiên, điều tương tự cũng có thể đạt được với một lambdachức năng tương đương :

>>> my_not_function = lambda item: not item

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

Không sử dụng toán tử đảo ngược bitwise ~trên boolean

Người ta có thể muốn sử dụng toán tử đảo ngược bit ~hoặc hàm toán tử tương đương operator.inv(hoặc một trong 3 bí danh khác ở đó). Nhưng vì boollà một lớp con của intkết quả có thể không mong muốn vì nó không trả về "inverse boolean", nó trả về "số nguyên nghịch đảo":

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

Đó là bởi vì Truetương đương với 1Falseđến 0và nghịch đảo bit hoạt động dựa trên biểu diễn theo chiều bit của các số nguyên 10.

Vì vậy, những điều này không thể được sử dụng để "phủ định" a bool.

Phủ định với mảng NumPy (và các lớp con)

Nếu bạn đang xử lý mảng NumPy (hoặc các lớp con như pandas.Serieshoặc pandas.DataFrame) có chứa boolean, bạn thực sự có thể sử dụng toán tử nghịch đảo bit ( ~) để phủ định tất cả boolean trong một mảng:

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

Hoặc hàm NumPy tương đương:

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

Bạn không thể sử dụng nottoán tử hoặc operator.nothàm trên các mảng NumPy vì chúng yêu cầu chúng trả về một hàm duy nhất bool(không phải mảng boolean), tuy nhiên NumPy cũng chứa một hàm không logic hoạt động theo phần tử:

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

Điều đó cũng có thể được áp dụng cho các mảng không phải boolean:

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

Tùy chỉnh các lớp học của riêng bạn

nothoạt động bằng cách gọi boolgiá trị và phủ định kết quả. Trong trường hợp đơn giản nhất, giá trị true sẽ chỉ gọi __bool__đối tượng.

Vì vậy, bằng cách triển khai __bool__(hoặc __nonzero__trong Python 2), bạn có thể tùy chỉnh giá trị sự thật và do đó kết quả của 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)

Tôi đã thêm một printtuyên bố để bạn có thể xác minh rằng nó thực sự gọi phương thức:

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

Tương tự như vậy, bạn có thể triển khai __invert__phương pháp để triển khai hành vi khi ~được áp dụng:

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)

Một lần nữa với một printcuộc gọi để thấy rằng nó thực sự được gọi là:

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

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

Tuy nhiên, việc triển khai __invert__như vậy có thể gây nhầm lẫn vì hành vi của nó khác với hành vi Python "bình thường". Nếu bạn từng làm điều đó, hãy ghi lại rõ ràng nó và đảm bảo rằng nó có một trường hợp sử dụng khá tốt (và phổ biến).


11

Python có một toán tử "not", phải không? Nó không chỉ là "không"? Như trong,

  return not bool

2

Bạn chỉ có thể so sánh mảng boolean. Ví dụ

X = [True, False, True]

sau đó

Y = X == False

sẽ cho bạn

Y = [False, True, False]

1
Đối với một mảng Numpy, có thể, nhưng đối với một danh sách Python chuẩn, điều này không chính xác. Vì OP cũng không đề cập đến, tôi không biết điều này trả lời câu hỏi như thế nào.
SiHa

2

Nếu bạn đang cố gắng triển khai một nút chuyển đổi , để bất cứ lúc nào bạn chạy lại một mã liên tục mà nó bị phủ định, bạn có thể đạt được điều đó như sau:

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

Chạy mã này đầu tiên sẽ thiết lập toggleđể Truevà bất cứ lúc nào ist đoạn này được gọi là, chuyển đổi sẽ được phủ nhận.


2

Câu trả lời được chấp nhận ở đây là đúng nhất cho kịch bản đã cho.

Nó làm cho tôi tự hỏi mặc dù chỉ đơn giản là đảo ngược một giá trị boolean nói chung. Hóa ra giải pháp được chấp nhận ở đây hoạt động như một lớp lót và có một lớp lót khác cũng hoạt động. Giả sử bạn có một biến "n" mà bạn biết là boolean, các cách dễ nhất để đảo ngược nó là:

n = n is False

đó là giải pháp ban đầu của tôi và sau đó là câu trả lời được chấp nhận từ câu hỏi này:

n = not n

IS thứ hai rõ ràng hơn, nhưng tôi băn khoăn về hiệu suất và giấu nó timeit- và hóa ra n = not nnó cũng là cách NHANH hơn để đảo ngược giá trị boolean.


Không sử dụng n is Falseđể kiểm tra sự thật.
gerrit

0

Một cách khác để đạt được kết quả tương tự, mà tôi thấy hữu ích cho khung dữ liệu gấu trúc.

Theo gợi ý dưới đây của mousetail:

bool(1 - False)

bool(1 - True)

Tại sao không bool(1 - False)?
bẫy chuột

Đúng. Điều đó tốt hơn và ngắn hơn.
Candide

Không có sự đảo ngược hợp lý của khung dữ liệu gấu trúc, giống như với các mảng không?
gerrit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.