ฉันจะได้รับสิ่งที่ตรงกันข้าม (การปฏิเสธ) ของบูลีนใน Python ได้อย่างไร


109

สำหรับตัวอย่างต่อไปนี้:

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

มีวิธีใดบ้างในการข้าม if-statement ที่สอง? เพียงเพื่อบอกให้คอมพิวเตอร์ส่งคืนสิ่งที่ตรงกันข้ามกับบูลีนbool?


6
นี้อาจเป็นเพียงแค่ pseudocode แต่intและboolมีทั้งชื่อ builtin (ประเภทพวกเขาเป็นตัวแทน) และไม่ควรนำมาใช้เป็นชื่อตัวแปร
SingleNegationElimination

ใช่มันเป็นเพียงรหัสหลอกเพื่อการสาธิตเท่านั้น ...
amyassin

8
if x == True:if x:ควรจะเขียน
Mike Graham

คำตอบ:


188

คุณสามารถใช้:

return not bool

4
นอกจากนี้ยังint in range (....)ไม่มีประสิทธิภาพ มันจะสร้างรายการจากนั้นทำการค้นหาเชิงเส้น ดีกว่ามีx in range(low, high) low <= x < high
MRAB

โปรดทราบว่าnot Noneจะส่งคืน False อย่างน้อยสำหรับฉันนั่นไม่ใช่สิ่งที่ฉันคาดหวัง ผมคาดว่าnot Noneจะเป็นNoneเพื่อให้สามารถใช้ในการลบล้างแม้ว่าค่าตอบแทนอาจจะnot Noneวิธีที่ใช้ใน Python คุณจะต้องตรวจสอบว่าคุณมีบูลีนจริงก่อน
รอบ

59

ตัว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

สิ่งเหล่านี้มีประโยชน์หากคุณต้องการใช้ฟังก์ชันที่ต้องใช้ฟังก์ชันเพรดิเคตหรือการเรียกกลับ

ตัวอย่างเช่นmapหรือ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]

แน่นอนว่าสามารถทำได้ด้วยlambdaฟังก์ชันที่เทียบเท่า:

>>> my_not_function = lambda item: not item

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

อย่าใช้ตัวดำเนินการกลับด้านบิต~ในบูลีน

อาจถูกล่อลวงให้ใช้ตัวดำเนินการสลับบิต~หรือฟังก์ชันตัวดำเนินการที่เทียบเท่ากันoperator.inv(หรือหนึ่งในนามแฝงอื่น ๆ อีก 3 นาม) แต่เนื่องจากboolเป็นคลาสย่อยของintผลลัพธ์อาจไม่คาดคิดเนื่องจากไม่ส่งคืน "บูลีนผกผัน" จึงส่งกลับ "จำนวนเต็มผกผัน":

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

นั่นเป็นเพราะTrueเทียบเท่ากับ1และFalseไป0และผกผันบิตดำเนินการในการแสดงค่าที่เหมาะสมของจำนวนเต็ม และ10

ดังนั้นจึงไม่สามารถใช้ "ลบล้าง" กbool.

การลบด้วยอาร์เรย์ NumPy (และคลาสย่อย)

หากคุณกำลังจัดการกับอาร์เรย์ NumPy (หรือคลาสย่อยเช่นpandas.Seriesหรือpandas.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])

คุณไม่สามารถใช้notโอเปอเรเตอร์หรือoperator.notฟังก์ชันบนอาร์เรย์ NumPy ได้เนื่องจากสิ่งเหล่านี้ต้องการให้สิ่งเหล่านี้ส่งคืนชุดเดียว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])

ปรับแต่งคลาสของคุณเอง

notทำงานโดยเรียกboolค่าและลบล้างผลลัพธ์ ในกรณีที่ง่ายที่สุดค่าความจริงจะเรียกใช้__bool__กับวัตถุ

ดังนั้นโดยการใช้งาน__bool__(หรือ__nonzero__ใน Python 2) คุณสามารถปรับแต่งค่าความจริงและผลลัพธ์ของ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 "ปกติ" หากคุณเคยทำเอกสารนั้นอย่างชัดเจนและตรวจสอบให้แน่ใจว่ามีการใช้งานที่ดี (และทั่วไป)



2

คุณสามารถเปรียบเทียบอาร์เรย์บูลีนได้ ตัวอย่างเช่น

X = [True, False, True]

แล้ว

Y = X == False

จะให้คุณ

Y = [False, True, False]

1
สำหรับอาร์เรย์ Numpy อาจจะ แต่สำหรับรายการ Python มาตรฐานสิ่งนี้ไม่ถูกต้อง เนื่องจาก OP ไม่ได้กล่าวถึงเช่นกันฉันจึงไม่เห็นว่าสิ่งนี้ตอบคำถามอย่างไร
SiHa

2

หากคุณกำลังพยายามใช้การสลับเพื่อให้เมื่อใดก็ตามที่คุณเรียกใช้รหัสถาวรซ้ำที่ถูกทำให้เป็นลบคุณสามารถทำได้ดังต่อไปนี้:

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

ใช้รหัสนี้เป็นครั้งแรกจะตั้งtoggleเพื่อTrueที่ทุกเวลา ist ข้อมูลโค้ดนี้เรียกว่าสลับจะถูกทำให้ไร้ผล


2

คำตอบที่ได้รับการยอมรับที่นี่ถูกต้องที่สุดสำหรับสถานการณ์ที่กำหนด

มันทำให้ฉันสงสัยว่าเกี่ยวกับการกลับค่าบูลีนโดยทั่วไป ปรากฎว่าโซลูชันที่ได้รับการยอมรับที่นี่ใช้งานได้เป็นซับเดียวและมีซับในอีกตัวที่ใช้งานได้เช่นกัน สมมติว่าคุณมีตัวแปร "n" ที่คุณรู้ว่าเป็นบูลีนวิธีที่ง่ายที่สุดในการสลับตัวแปรคือ:

n = n is False

ซึ่งเป็นคำตอบดั้งเดิมของฉันจากนั้นคำตอบที่ยอมรับจากคำถามนี้:

n = not n

อย่างหลังชัดเจนกว่า แต่ฉันสงสัยเกี่ยวกับประสิทธิภาพและซ่อนไว้timeit- และปรากฎว่าn = not nเป็นวิธีที่เร็วกว่าในการเปลี่ยนค่าบูลีน


อย่าใช้n is Falseสำหรับการทดสอบความจริง
gerrit

0

อีกวิธีหนึ่งในการบรรลุผลลัพธ์เดียวกันซึ่งฉันพบว่ามีประโยชน์สำหรับดาต้าเฟรมของแพนด้า

ตามคำแนะนำด้านล่างโดย mousetail:

bool(1 - False)

bool(1 - True)

ไม่มีการผกผันของแพนด้าดาต้าเฟรมแบบตรรกะเช่นเดียวกับอาร์เรย์จำนวนนับหรือไม่
gerrit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.