'और' (बूलियन) बनाम 'और' (बिटवाइज़) - सूचियों बनाम खस्ता सरणियों के साथ व्यवहार में अंतर क्यों?


142

बनाम वीपीआई सरणियों की सूची में बूलियन और बिटवाइज़ संचालन के व्यवहार में अंतर क्या है?

मैं निम्नलिखित उदाहरणों में सचित्र पाइथन में &बनाम के उपयुक्त उपयोग के बारे में उलझन में हूँ and

mylist1 = [True,  True,  True, False,  True]
mylist2 = [False, True, False,  True, False]

>>> len(mylist1) == len(mylist2)
True

# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]

# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?

>>> import numpy as np

# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?

# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False,  True, False, False, False], dtype=bool)
# This is the output I was expecting!

इस जवाब और इस उत्तर ने मुझे यह समझने में मदद की कि andयह एक बूलियन ऑपरेशन है लेकिन &एक बिटवाइज़ ऑपरेशन है।

मैंने अवधारणा को बेहतर ढंग से समझने के लिए बिटवाइज़ ऑपरेशंस के बारे में पढ़ा , लेकिन मैं अपने उपरोक्त 4 उदाहरणों की समझ बनाने के लिए उस जानकारी का उपयोग करने के लिए संघर्ष कर रहा हूं।

उदाहरण 4 ने मुझे मेरे वांछित आउटपुट तक पहुंचाया, इसलिए यह ठीक है, लेकिन मैं अभी भी उलझन में हूं कि मुझे कब / कैसे / क्यों andबनाम का उपयोग करना चाहिए &। इन ऑपरेटरों के साथ सूचियाँ और NumPy सरणियाँ अलग-अलग व्यवहार क्यों करती हैं?

क्या कोई मुझे यह समझने के लिए बूलियन और बिटवाइज़ ऑपरेशंस के बीच के अंतर को समझने में मदद कर सकता है कि वे सूचियों और NumPy सरणियों को अलग-अलग क्यों हैंडल करते हैं?


2
Numpy में वहाँ है np.bitwise_and()और np.logical_and()और दोस्तों के भ्रम से बचने के।
डिट्रीच

1
उदाहरण 1 में, mylist1 and mylist2उसी परिणाम का उत्पादन नहीं करता है mylist2 and mylist1, जैसा कि लौटाया जा रहा है, दूसरी सूची है जैसा कि डेलन ने बताया है।
user2015487

जवाबों:


113

andचाहे दोनों भाव परीक्षण तार्किक हैं True, जबकि &(जब साथ प्रयोग किया जाता True/ Falseमान) परीक्षण करता है, तो दोनों कर रहे हैं True

पायथन में, खाली बिल्ट-इन ऑब्जेक्ट्स को आमतौर पर तार्किक रूप से माना जाता है Falseजबकि गैर-खाली बिल्ट-इन तार्किक रूप से होते हैं True। यह सामान्य उपयोग के मामले को सुगम बनाता है जहाँ आप कुछ करना चाहते हैं यदि सूची खाली है और सूची नहीं है तो कुछ और। ध्यान दें कि इसका मतलब है कि सूची [गलत] तार्किक रूप से है True:

>>> if [False]:
...    print 'True'
...
True

इसलिए उदाहरण 1 में, पहली सूची गैर-रिक्त है और इसलिए तार्किक रूप से True, इसलिए सत्य का मूल्य andदूसरी सूची के समान है। (हमारे मामले में, दूसरी सूची गैर-रिक्त है और इसलिए तार्किक रूप से True, लेकिन यह पहचान कर कि गणना के अनावश्यक चरण की आवश्यकता होगी।)

उदाहरण 2 के लिए, सूचियों को सार्थक रूप से एक बिटवाइज़ फैशन में नहीं जोड़ा जा सकता क्योंकि वे तत्वों के विपरीत मनमाना हो सकते हैं। जिन चीजों को बिटवाइज़ में जोड़ा जा सकता है, उनमें शामिल हैं: ट्रूज़ एंड फ़ल्स, पूर्णांक।

NumPy ऑब्जेक्ट, इसके विपरीत, वेक्टर की गई गणनाओं का समर्थन करते हैं। यही है, वे आपको डेटा के कई टुकड़ों पर समान संचालन करने देते हैं।

उदाहरण 3 विफल रहता है क्योंकि NumPy सरणियों (लंबाई> 1) का कोई सत्य मूल्य नहीं है क्योंकि यह वेक्टर-आधारित तर्क भ्रम को रोकता है।

उदाहरण 4 बस एक सदिश बिट andऑपरेशन है।

जमीनी स्तर

  • यदि आप सरणियों के साथ काम नहीं कर रहे हैं और पूर्णांक के गणित जोड़तोड़ नहीं कर रहे हैं, तो आप शायद चाहते हैं and

  • यदि आपके पास सत्य मूल्यों के वैक्टर हैं जिन्हें आप गठबंधन करना चाहते हैं, तो उपयोग numpyकरें &


26

के बारे में list

सबसे पहले एक बहुत ही महत्वपूर्ण बिंदु, जिसमें से सब कुछ का पालन होगा (मुझे आशा है)।

साधारण पायथन में, listकिसी भी तरह से विशेष नहीं है (निर्माण के लिए प्यारा सिंटैक्स होने के अलावा, जो ज्यादातर एक ऐतिहासिक दुर्घटना है)। एक बार एक सूची [3,2,6]बना लेने के बाद, यह सभी इरादों और उद्देश्यों के लिए होता है, बस एक साधारण पायथन ऑब्जेक्ट, जैसे एक संख्या 3, सेट {3,7}या एक फ़ंक्शन lambda x: x+5

(हां, यह अपने तत्वों को बदलने का समर्थन करता है, और यह पुनरावृत्ति, और कई अन्य चीजों का समर्थन करता है, लेकिन यह सिर्फ एक प्रकार है: यह कुछ कार्यों का समर्थन करता है, जबकि कुछ अन्य का समर्थन नहीं करते। इंट एक शक्ति बढ़ाने का समर्थन करता है, लेकिन ऐसा नहीं है। इसे बहुत खास बनाएं - यह सिर्फ एक इंट है। लैंबडा कॉलिंग का समर्थन करता है, लेकिन यह इसे बहुत खास नहीं बनाता है - यही लैम्बडा के लिए है, आखिरकार :)।

के बारे में and

andएक ऑपरेटर नहीं है (आप इसे "ऑपरेटर" कह सकते हैं, लेकिन आप "ऑपरेटर" के लिए भी कॉल कर सकते हैं :)। पायथन में ऑपरेटर्स कुछ प्रकार की वस्तुओं पर बुलाए गए (के माध्यम से कार्यान्वित) तरीके हैं, जो आमतौर पर उस प्रकार के हिस्से के रूप में लिखे जाते हैं। इसके कुछ ऑपरेंड का मूल्यांकन करने के लिए कोई तरीका नहीं है, लेकिन ऐसा andकर सकते हैं (और चाहिए)।

उस का परिणाम यह है कि andअतिभारित नहीं किया जा सकता है, जैसे forअतिभारित नहीं किया जा सकता है। यह पूरी तरह से सामान्य है, और एक निर्दिष्ट प्रोटोकॉल के माध्यम से संचार करता है। आप जो कर सकते हैं वह प्रोटोकॉल के आपके हिस्से को अनुकूलित करता है, लेकिन इसका मतलब यह नहीं है कि आप andपूरी तरह से व्यवहार को बदल सकते हैं । प्रोटोकॉल है:

पायथन की कल्पना "ए और बी" की व्याख्या करें (यह सचमुच इस तरह से नहीं होता है, लेकिन यह समझने में मदद करता है)। जब यह "और" की बात आती है, तो यह उस वस्तु को देखता है जिसका उसने अभी मूल्यांकन किया है (ए), और उससे पूछता है: क्या आप सच हैं? ( नहीं : आप हैं True?) यदि आप एक वर्ग के लेखक हैं, तो आप इस उत्तर को अनुकूलित कर सकते हैं। यदि aउत्तर "नहीं", and(पूरी तरह से ख को छोड़ दिया जाता है, तो इसका बिल्कुल भी मूल्यांकन नहीं किया जाता है, और) कहता है: aमेरा परिणाम है ( नहीं : गलत मेरा परिणाम है)।

यदि aउत्तर नहीं है, तो andयह पूछता है: आपकी लंबाई क्या है? (फिर, आप इसे एक लेखक के aवर्ग के रूप में अनुकूलित कर सकते हैं )। यदि aउत्तर 0 है, andतो ऊपर जैसा ही है - इसे गलत मानते हैं (गलत नहीं ), ख को छोड़ देता है, और aपरिणाम के रूप में देता है ।

अगर aदूसरे प्रश्न का उत्तर ("आपकी लंबाई क्या है") के अलावा कुछ है, या यह बिल्कुल भी जवाब नहीं देता है, या यह पहले वाले को "हाँ" का जवाब देता है ("आप सच हैं"), andबी का मूल्यांकन करता है, और कहता है: bमेरा परिणाम है। ध्यान दें कि यह कोई प्रश्न नहीं पूछता है b

यह सब कहने का दूसरा तरीका यह है कि a and bलगभग एक ही है b if a else a, केवल एक बार मूल्यांकन करने के अलावा।

अब एक पेन और पेपर के साथ कुछ मिनट के लिए बैठें, और अपने आप को समझाएं कि जब {a, b} {ट्रू, फाल्स} का सबसेट है, तो यह ठीक उसी तरह काम करता है जैसा आप बूलियन ऑपरेटर्स से उम्मीद करते हैं। लेकिन मुझे आशा है कि मैंने आपको आश्वस्त किया है कि यह बहुत अधिक सामान्य है, और जैसा कि आप देखेंगे, इस तरह से बहुत अधिक उपयोगी है।

उन दोनों को एक साथ रखना

अब मुझे आशा है कि आप अपने उदाहरण को समझेंगे। 1. andयदि कोई सूची, सूची, भेड़ का बच्चा या एक वर्ग Argmhbl की वस्तु है तो परवाह नहीं करता है। यह सिर्फ mylist1 प्रोटोकॉल के सवालों के जवाब के बारे में परवाह है। और हां, mylist1 लंबाई के बारे में सवाल का 5 जवाब देता है, इसलिए mylist2 लौटाता है। और बस। इसका mylist1 और mylist2 के तत्वों से कोई लेना-देना नहीं है - वे कहीं भी तस्वीर में प्रवेश नहीं करते हैं।

दूसरा उदाहरण: &परlist

दूसरी ओर, उदाहरण के लिए &, किसी भी अन्य की तरह एक ऑपरेटर है +। इसे उस वर्ग पर एक विशेष विधि को परिभाषित करके एक प्रकार के लिए परिभाषित किया जा सकता है। intइसे बिटवाइज़ "और" के रूप में परिभाषित करता है, और बूल इसे तार्किक "और" के रूप में परिभाषित करता है, लेकिन यह सिर्फ एक विकल्प है: उदाहरण के लिए, सेट्स और कुछ अन्य ऑब्जेक्ट जैसे तानाशाह कुंजी दृश्य इसे एक सेट चौराहे के रूप में परिभाषित करते हैं। listबस इसे परिभाषित नहीं करता है, शायद क्योंकि गुइडो इसे परिभाषित करने के किसी भी स्पष्ट तरीके के बारे में नहीं सोचते थे।

numpy

दूसरे पैर पर: डी, NumPy सरणी हैं विशेष, या कम से कम वे बनने की कोशिश कर रहे हैं। बेशक, numpy.array सिर्फ एक वर्ग है, यह andकिसी भी तरह से ओवरराइड नहीं कर सकता है , इसलिए यह अगली सबसे अच्छी बात करता है: जब आपसे पूछा जाता है "क्या आप सच हैं", numpy.array एक ValueError को उठाता है, प्रभावी रूप से कह रहा है "कृपया सवाल को फिर से लिखें।" सच्चाई का दृश्य आपके मॉडल में फिट नहीं होता है "। (ध्यान दें कि ValueError संदेश के बारे में बात नहीं करता है and- क्योंकि numpy.array नहीं जानता कि यह सवाल कौन पूछ रहा है; यह सिर्फ सच के बारे में बोलता है।)

के लिए &, यह पूरी तरह से अलग कहानी है। numpy.array इसे अपनी इच्छानुसार परिभाषित कर सकता है, और यह &अन्य ऑपरेटरों के साथ लगातार परिभाषित करता है : पॉइंटवाइज़। तो आप अंत में वही प्राप्त करें जो आप चाहते हैं।

HTH,


23

शॉर्ट-सर्किट बूलियन ऑपरेटरों ( and, or) ओवरराइड नहीं किया जा सकता नई भाषा सुविधाओं को शुरू करने या कम सर्किटिंग त्याग के बिना यह करने के लिए कोई संतोषजनक तरीका है क्योंकि वहाँ। जैसा कि आप जानते हैं या नहीं जानते हैं, वे इसके सत्य मूल्य के लिए पहले ऑपरेंड का मूल्यांकन करते हैं, और उस मूल्य के आधार पर, या तो दूसरे तर्क का मूल्यांकन करते हैं और वापस करते हैं, या दूसरे तर्क का मूल्यांकन नहीं करते हैं और पहले वापस करते हैं:

something_true and x -> x
something_false and x -> something_false
something_true or x -> something_true
something_false or x -> x

ध्यान दें कि (वास्तविक का मूल्यांकन करने का परिणाम) वास्तविक ऑपरेंड लौटाया गया है, सत्य मूल्य नहीं।

उनके व्यवहार को अनुकूलित करने का एकमात्र तरीका ओवरराइड __nonzero__( __bool__पायथन 3 में बदला हुआ ) है, इसलिए आप प्रभावित कर सकते हैं कि कौन सा ऑपरेंड वापस लौटता है, लेकिन कुछ अलग नहीं लौटाता है। सूची (और अन्य संग्रह) को "सत्य" के रूप में परिभाषित किया जाता है जब वे कुछ भी होते हैं, और "फ़ासी" जब वे खाली होते हैं।

NumPy सरणियाँ उस धारणा को अस्वीकार करती हैं: वे उपयोग के मामले जिनके लिए वे लक्ष्य करते हैं, सत्य की दो अलग-अलग धारणाएँ आम हैं: (1) क्या कोई तत्व सत्य है, और (2) क्या सभी तत्व सत्य हैं। इन दो पूरी तरह से (और चुपचाप) असंगत हैं, और न तो स्पष्ट रूप से अधिक सही या अधिक आम है के बाद से, NumPy अनुमान लगाना मना कर दिया और आप स्पष्ट रूप से उपयोग करने के लिए की आवश्यकता है .any()या .all()

&और |(और not, वैसे) कर सकते हैं पूरी तरह से ओवरराइड किया सकता है, क्योंकि वे शॉर्ट सर्किट नहीं करते हैं। ओवरराइड होने पर वे कुछ भी वापस कर सकते हैं, और नुम्पी उस का अच्छा उपयोग करते हैं जो तत्व-वार संचालन करते हैं, जैसा कि वे व्यावहारिक रूप से किसी अन्य स्केलर ऑपरेशन के साथ करते हैं। दूसरी ओर, लिस्ट, उनके तत्वों के संचालन को प्रसारित नहीं करती हैं। जिस तरह mylist1 - mylist2कुछ भी मतलब नहीं है और mylist1 + mylist2पूरी तरह से कुछ अलग मतलब है, &सूचियों के लिए कोई ऑपरेटर नहीं है ।


3
क्या यह कर सकते हैं उपज है में से एक विशेष रूप से दिलचस्प उदाहरण [False] or [True]के लिए मूल्यांकन करता है [False], और [False] and [True]करने के लिए मूल्यांकन करता है [True]
रॉब वॉट्स

16

उदाहरण 1:

इस प्रकार है काम करता है और ऑपरेटर काम करता है।

x और y => यदि x गलत है, तो x , और y

तो दूसरे शब्दों में, चूंकि mylist1नहीं है False, अभिव्यक्ति का परिणाम है mylist2। (केवल खाली सूचियों का मूल्यांकन करना है False।)

उदाहरण 2:

&के रूप में आप का उल्लेख ऑपरेटर एक बिटवाइज़ के लिए है और,। बिटवाइज़ ऑपरेशन केवल संख्याओं पर काम करते हैं। का परिणाम एक और बिट्स है कि दोनों में 1 हैं में 1s से बना एक नंबर है एक और । उदाहरण के लिए:

>>> 3 & 1
1

यह देखना आसान है कि द्विआधारी शाब्दिक (ऊपर के समान संख्या) का उपयोग करके क्या हो रहा है :

>>> 0b0011 & 0b0001
0b0001

बूलवाइज ऑपरेशन बूलियन (सत्य) ऑपरेशन की अवधारणा के समान हैं, लेकिन वे केवल बिट्स पर काम करते हैं।

तो, मेरी कार के बारे में कुछ बयान दिया

  1. मेरी कार लाल है
  2. मेरी गाड़ी के पहिए हैं

इन दो कथनों का तार्किक "और" है:

(मेरी कार लाल है?) और (क्या कार में पहिए हैं?) => गलत मूल्य का तार्किक सच

दोनों जो सच हैं, मेरी कार के लिए कम से कम। तो एक पूरे के रूप में बयान का मूल्य तार्किक है सच है।

इन दोनों कथनों का "और" थोड़ा और अस्पष्ट है:

('मेरी कार लाल है' कथन का सांख्यिक मान) और (कथन 'मेरी कार के पहिए हैं' का संख्यात्मक मान) => संख्या

यदि अजगर जानता है कि बयानों को संख्यात्मक मूल्यों में कैसे परिवर्तित किया जाए, तो यह ऐसा करेगा और दो मानों के बिटवाइज़-और की गणना करेगा। यह आपको विश्वास दिला सकता है कि &इसके साथ विनिमेय है and, लेकिन उपरोक्त उदाहरण के साथ वे अलग चीजें हैं। इसके अलावा, उन वस्तुओं के लिए जिन्हें परिवर्तित नहीं किया जा सकता है, आपको बस एक मिल जाएगा TypeError

उदाहरण 3 और 4:

Numpy सरणियों के लिए अंकगणितीय संचालन लागू करता है :

Ndarrays पर अंकगणितीय और तुलनात्मक संचालन को तत्व-वार संचालन के रूप में परिभाषित किया गया है, और आमतौर पर परिणाम के रूप में ndarray वस्तुओं का उत्पादन होता है।

लेकिन सरणियों के लिए तार्किक संचालन को लागू नहीं करता है, क्योंकि आप अजगर में तार्किक ऑपरेटरों को अधिभार नहीं दे सकते हैं । इसलिए उदाहरण तीन काम नहीं करता है, लेकिन उदाहरण चार करता है।

तो अपने andबनाम &प्रश्न का उत्तर देने के लिए: उपयोग करें and

बिटवाइज़ ऑपरेशंस का उपयोग किसी नंबर की संरचना की जांच के लिए किया जाता है (जो बिट सेट होते हैं, जो बिट सेट नहीं होते हैं)। इस तरह की जानकारी ज्यादातर निम्न-स्तरीय ऑपरेटिंग सिस्टम इंटरफेस ( उदाहरण के लिए यूनिक्स अनुमति बिट्स ) में उपयोग की जाती है। अधिकांश अजगर कार्यक्रमों को यह जानने की आवश्यकता नहीं होगी।

तार्किक आपरेशन ( and, or, not), तथापि, हर समय किया जाता है।


14
  1. पायथन में X and Yरिटर्न की एक अभिव्यक्ति Y, जो कि bool(X) == Trueया किसी भी Xया Yगलत, जैसे मूल्यांकन:

    True and 20 
    >>> 20
    
    False and 20
    >>> False
    
    20 and []
    >>> []
  2. बिटवाइज़ ऑपरेटर बस सूचियों के लिए परिभाषित नहीं है। लेकिन यह पूर्णांक के लिए परिभाषित किया गया है - संख्याओं के द्विआधारी प्रतिनिधित्व पर परिचालन। 16 (01000) और 31 (11111) पर विचार करें:

    16 & 31
    >>> 16
  3. NumPy एक मानसिक नहीं है, यह नहीं जानता है, क्या आपका मतलब यह है कि उदाहरण तार्किक अभिव्यक्ति में [False, False]समान होना चाहिए True। "के साथ कोई भी खाली संग्रह: इस में यह एक मानक अजगर व्यवहार है, जो है ओवरराइड करता है len(collection) == 0है False"।

  4. शायद NumPy के सरणियों और ऑपरेटर के एक अपेक्षित व्यवहार।


झूठी और 20 रिटर्न झूठी
राहुल

4

Django के डॉक पर पहला उदाहरण और आधार के लिए,
यह हमेशा दूसरी सूची लौटाएगा, वास्तव में एक गैर खाली सूची को पायथन के लिए एक सच्चे मूल्य के रूप में देखा जाता है, इस प्रकार अजगर 'अंतिम' सही मान लौटाता है इसलिए दूसरी सूची

In [74]: mylist1 = [False]
In [75]: mylist2 = [False, True, False,  True, False]
In [76]: mylist1 and mylist2
Out[76]: [False, True, False, True, False]
In [77]: mylist2 and mylist1
Out[77]: [False]

4

एक अजगर की सूची के साथ संचालन पर काम सूचीlist1 and list2अगर जाँच करेगा list1खाली है, और वापसी list1अगर ऐसा है, और list2अगर यह नहीं है। list1 + list2संलग्न कर देगा list2करने के लिए list1है, तो आप के साथ एक नई सूची प्राप्त len(list1) + len(list2)तत्वों।

ऑपरेटर जो केवल तत्व-वार लागू करते समय समझ में आते हैं, जैसे कि &, TypeErrorतत्वों के माध्यम से लूपिंग के बिना तत्व-वार संचालन समर्थित नहीं हैं।

Numpy सरणियाँ तत्व-वार संचालन का समर्थन करती हैं । array1 & array2में प्रत्येक इसी तत्व के लिए बिटवाइज़ गणना या जाएगा array1और array2array1 + array2में प्रत्येक इसी तत्व के लिए राशि की गणना करेगा array1और array2

यह andऔर के लिए काम नहीं करता है or

array1 and array2 निम्नलिखित कोड के लिए अनिवार्य रूप से एक छोटा हाथ है:

if bool(array1):
    return array2
else:
    return array1

इसके लिए आपको एक अच्छी परिभाषा की आवश्यकता है bool(array1)। पायथन सूचियों पर उपयोग किए जाने वाले वैश्विक संचालन के लिए, परिभाषा यह है कि bool(list) == Trueयदि listखाली नहीं है, और Falseयदि यह खाली है। सुपीरियर के तत्व-वार संचालन के लिए, यह जांचने के लिए कि क्या कोई तत्व मूल्यांकन करता है True, या सभी तत्व इसका मूल्यांकन करते हैं या नहीं, कुछ असंतोष है True। क्योंकि दोनों निश्चित रूप से सही हैं, सुन्न नहीं लगता है और ValueErrorजब bool()एक सरणी पर (अप्रत्यक्ष रूप से) कहा जाता है तो उठाता है ।


0

अच्छा प्रश्न। अवलोकन के समान आपके पास उदाहरण 1 और 4 के बारे में है (या मुझे तार्किक andबिटवाइज़ &ऑपरेटरों पर 1 और 4 :) कहना चाहिए) , मुझे sumऑपरेटर पर अनुभव हुआ । सुन्न sumऔर पाई sumअलग-अलग तरह से व्यवहार करते हैं। उदाहरण के लिए:

मान लीजिए कि "चटाई" एक सुन्न 5x5 2d सरणी है जैसे:

array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10],
       [11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20],
       [21, 22, 23, 24, 25]])

तब numpy.sum (मैट) पूरे मैट्रिक्स का कुल योग देता है। जबकि पाइथन से निर्मित राशि जैसे योग (मैट) केवल अक्ष के साथ योग है। निचे देखो:

np.sum(mat)  ## --> gives 325
sum(mat)     ## --> gives array([55, 60, 65, 70, 75])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.