Python में x [x <2] = 0 का क्या अर्थ है?


85

मैं इसी तरह की एक पंक्ति के साथ कुछ कोड भर आया था

x[x<2]=0

विविधताओं के साथ खेलते हुए, मैं अब भी इस वाक्य रचना पर अड़ा हुआ हूं।

उदाहरण:

>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]

7
यह एक सूची के साथ ऐसा करने के लिए कभी भी समझ में नहीं आता है।
dbliss

12
यह केवल NumPy सरणियों या इसी तरह की वस्तुओं के साथ समझ में आता है, जो आपके प्रयोगों में व्यवहार से पूरी तरह से अलग व्यवहार करता है या सूची-आधारित व्यवहार या तो उत्तर में समझाया गया है।
user2357112

11
ध्यान दें, यह पायथन में काम नहीं करता है। 3. प्रकार केवल तभी तुलना करने में सक्षम होते हैं जब तुलना समझ में आती है। पायथन 3 में यह उदाहरण फेंकता है TypeError: unorderable types: list() < int()
मॉर्गन थ्रैप

2
बहुत कम जानकारी। उल्लेख किया है कि सरणी एक संख्यात्मक सरणी है।
लामाओओओ

3
मैं हैरान हूँ कि यह बहुत सारे अपवोट हो गए (हालांकि यह वास्तव में SO प्रारूप के लिए एक अच्छा सवाल है)।
पास्कलवीकूटेन

जवाबों:


120

यह केवल NumPy सरणियों के साथ समझ में आता है । सूचियों के साथ व्यवहार बेकार है, और पायथन 2 (पायथन 3 नहीं) के लिए विशिष्ट है। यदि मूल वस्तु वास्तव में न्यूमरी सरणी (नीचे देखें) और सूची नहीं है तो आप दोबारा जांच कर सकते हैं।

लेकिन यहाँ आपके कोड में, x एक साधारण सूची है।

जबसे

x < 2

गलत है, इसलिए 0 है

x[x<2] है x[0]

x[0] बदल जाता है।

इसके विपरीत, x[x>2]है x[True]याx[1]

तो, x[1]बदल जाता है।

क्यों होता है ऐसा?

तुलना के नियम हैं:

  1. जब आप दो स्ट्रिंग्स या दो न्यूमेरिक प्रकारों का ऑर्डर करते हैं, तो ऑर्डरिंग अपेक्षित तरीके से की जाती है (स्ट्रिंग के लिए लेक्सिकोग्राफ़िक ऑर्डरिंग, पूर्णांक के लिए संख्यात्मक ऑर्डरिंग)।

  2. जब आप एक संख्यात्मक और एक गैर-संख्यात्मक प्रकार का आदेश देते हैं, तो संख्यात्मक प्रकार पहले आता है।

  3. जब आप दो असंगत प्रकारों का आदेश देते हैं, जहां न तो संख्यात्मक होते हैं, तो वे उनके टाइपनामों के वर्णानुक्रम द्वारा आदेशित होते हैं:

इसलिए, हमारे पास निम्नलिखित आदेश हैं

संख्यात्मक <सूची <स्ट्रिंग <tuple

पायथन स्ट्रिंग और इंट की तुलना कैसे करता है, इसके लिए स्वीकृत उत्तर देखें

यदि x एक NumPy सरणी है , तो बूलियन सरणी अनुक्रमण के कारण सिंटैक्स अधिक समझ में आता है । उस मामले में, x < 2बूलियन बिल्कुल नहीं है; यह का प्रतिनिधित्व करने के लिए कि क्या के प्रत्येक तत्व बूलियन्स की एक सरणी है x2. से कम था x[x < 2] = 0तो चयन करता है के तत्वों xहै कि 2 की तुलना में कम थे और 0. देखें करने के लिए उन कोशिकाओं सेट अनुक्रमण

>>> x = np.array([1., -1., -2., 3])
>>> x < 0
array([False,  True,  True, False], dtype=bool)
>>> x[x < 0] += 20   # All elements < 0 get increased by 20
>>> x
array([  1.,  19.,  18.,   3.]) # Only elements < 0 are affected

11
यह देखते हुए कि ओपी विशेष रूप से कहता है "मैं इस तरह के कुछ कोड में आया था ...", मुझे लगता है कि आपके उत्तर का अंकुरण बूलियन अनुक्रमण बहुत उपयोगी है - यह इंगित करने के लायक हो सकता है कि यदि ओपी ने जिस कोड को देखा था, उसे स्क्रॉल किया तो वे ' लगभग निश्चित रूप से importसुन्न के लिए देखेंगे।
जे रिचर्ड स्नेप

2
अभी भी यह करने के लिए एक अति चतुर तरीका है, निश्चित रूप से? (जैसा कि कहा गया है, के साथ तुलना करें [0 if i < 2 else i for i in x]।) या यह नम्पी में प्रोत्साहित शैली है?
टिम पेडरिक 19

6
@TimPederick: NumPy के साथ सूची समझ का उपयोग करना एक बहुत बुरा विचार है। यह दर्जनों से सैकड़ों गुना धीमा है, यह मनमाना-आयामी सरणियों के साथ काम नहीं करता है, यह तत्व प्रकार को खराब करने के लिए आसान है, और यह एक सरणी के बजाय एक सूची बनाता है। बूलियन एरे इंडेक्सिंग पूरी तरह से सामान्य है और न्यूमपी में अपेक्षित है।
user2357112

@TimPederick प्रदर्शन हिट के अलावा, यह भी संभावना है कि जिसने भी कोड लिखा है वह एक सुस्पष्ट सरणी का उपयोग करते रहने का इरादा रखता है। x[x<2]एक संख्यात्मक सरणी लौटाएगा, जबकि [0 if i<2 else i for i in x]एक सूची देता है। ऐसा इसलिए है क्योंकि x[x<2]एक अनुक्रमण ऑपरेशन (डेटा को मास्क करने की क्षमता के कारण एक स्लाइसिंग ऑपरेशन के रूप में संख्यात्मक / स्कैपी / पांडा में संदर्भित किया जाता है), जबकि सूची की समझ एक नई वस्तु परिभाषा है। न्यूपे इंडेक्सिंग
माइकल डेलगाडो

45
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2

बूल बस एक पूर्णांक में बदल जाता है। सूचकांक या तो 0 या 1 है।


7
आप इसका उल्लेख कर सकते हैं xऔर " लगातार लेकिन मनमाने ढंग से आदेश दिया जाता है " और यह कि आदेश अलग-अलग पायथन कार्यान्वयन में बदल सकते हैं। 2
रोब

2
मैं यह भी जोड़ूंगा कि यह चीजों को करने का एक चतुर तरीका है और मेरी राय में इससे बचना चाहिए। यह स्पष्ट रूप से करें - तथ्य यह है कि ओपी को यह प्रश्न पूछना था, मेरी बात का समर्थन करता है।
क्रेटेंको

11
क्या आप अधिक विवरण जोड़ सकते हैं, क्यों x<2 == false?
इल्या बुर्सोव

15
boolएक पूर्णांक में परिवर्तित नहीं होता है, boolपायथन में एक पूर्णांक है
एंटी हवाला

2
बस किसी और के लिए @ AnttiHaapala के बयान को स्पष्ट करने के लिए जो साथ आता है, bool एक उपवर्ग है int
porglezomp

14

अपने प्रश्न में मूल कोड केवल अजगर 2 में काम करता है xएक listअजगर 2 में, तुलना x < yहै Falseअगर yएक है intइगर। ऐसा इसलिए है क्योंकि किसी सूची की पूर्णांक के साथ तुलना करने का कोई मतलब नहीं है। हालांकि पायथन 2 में, यदि ऑपरेंड्स तुलनीय नहीं हैं, तो तुलना CPython में प्रकारों के नामों के वर्णानुक्रमिक क्रम पर आधारित है ; इसके अलावा सभी संख्या मिश्रित प्रकार की तुलनाओं में पहले नंबर पर आती हैं । यह सीपीथॉन 2 के प्रलेखन में भी नहीं बताया गया है, और विभिन्न पायथन 2 कार्यान्वयन अलग परिणाम दे सकते हैं। इसका [1, 2, 3, 4, 5] < 2मूल्यांकन Falseइसीलिए किया जाता है क्योंकि 2यह एक संख्या है और इस प्रकार listसीपीथॉन की तुलना में "छोटा" है । यह मिश्रित तुलना अंततः थीएक विशेषता को बहुत अस्पष्ट माना जाता है , और इसे पायथन 3.0 में हटा दिया गया था।


अब, परिणाम <एक है bool; और boolइसका एक उपवर्ग हैint :

>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6

इसलिए मूल रूप से आप तत्व 0 या 1 ले रहे हैं, जो इस बात पर निर्भर करता है कि तुलना सही है या गलत।


आप अजगर 3 में उपरोक्त कोड प्रयास करेंगे तो आपको मिल जाएगा TypeError: unorderable types: list() < int()की वजह से अजगर 3.0 में बदलाव :

आदेशों की तुलना

तुलनात्मक आदेश देने के लिए पायथन 3.0 ने नियमों को सरल बनाया है:

आदेश तुलना ऑपरेटरों ( <, <=, >=, >) एक उठाना TypeErrorअपवाद ऑपरेंड एक सार्थक प्राकृतिक आदेश की जरूरत नहीं है जब। इस प्रकार, जैसे भाव 1 < '', 0 > Noneया len <= lenअब मान्य नहीं हैं, और उदाहरण के लिए वापस लौटने के बजाय None < Noneउठता है । एक कोरोलरी यह है कि विषम सूची को छाँटने से अब कोई मतलब नहीं है - सभी तत्वों को एक दूसरे से तुलना करनी चाहिए। ध्यान दें कि यह और ऑपरेटरों पर लागू नहीं होता है : विभिन्न अतुलनीय प्रकारों की वस्तुएं हमेशा एक दूसरे से असमान की तुलना करती हैं।TypeErrorFalse==!=


कई डेटाटिप्स हैं जो कुछ अलग करने के लिए तुलना ऑपरेटरों को अधिभारित करते हैं (पांडा, सुपीरियर के सरणियों से डेटाफ्रेम)। यदि आप जिस कोड का उपयोग कर रहे थे वह कुछ और था, ऐसा इसलिए था क्योंकि ऐसा नहीं था , लेकिन ऑपरेटर के साथ कुछ अन्य वर्ग का एक उदाहरण एक मान वापस करने के लिए ओवरराइड किया गया जो कि नहीं है ; और यह मान तब विशेष रूप से (उर्फ / ) द्वारा संभाला गया थाxlist<boolx[]__getitem____setitem__


6
+Falseहाय पर्ल, हे जावास्क्रिप्ट, आप कैसे कर रहे हैं?
बिल्ली

@ जावास्क्रिप्ट जावास्क्रिप्ट, पर्ल में, यह मान को संख्या के रूप में परिवर्तित करता है। पायथन में यह UNARY_POSITIVE__pos__
ओपकोड के

मुझे लगता है कि आपके अंतिम खंड के __setitem__बजाय आपका मतलब था __getitem__। इसके अलावा, मुझे आशा है कि आपको कोई आपत्ति नहीं है कि मेरा उत्तर आपके उत्तर के उस भाग से प्रेरित था।
MSeifert

नहीं, मेरा मतलब था और सोच रहा था __getitem__कि समान रूप से हो सकता है __setitem__और__delitem__
एंटि हापाला

9

इसका एक और उपयोग है: कोड गोल्फ। कोड गोल्फ उन कार्यक्रमों को लिखने की कला है जो कुछ समस्या को कुछ स्रोत कोड बाइट्स में हल करते हैं।

return(a,b)[c<d]

के बराबर है

if c < d:
    return b
else:
    return a

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

c<dका मूल्यांकन करता है Trueया False
(a, b)टपल है।
एक ट्यूपल पर अनुक्रमण एक सूची पर अनुक्रमण की तरह काम करता है: (3,5)[1]== 5
Trueके बराबर है 1और Falseबराबर है 0

  1. (a,b)[c<d]
  2. (a,b)[True]
  3. (a,b)[1]
  4. b

या इसके लिए False:

  1. (a,b)[c<d]
  2. (a,b)[False]
  3. (a,b)[0]
  4. a

ढेर सारी बाइट्स को बचाने के लिए आप बहुत से गंदे कामों के ढेरों नेटवर्क पर अच्छी सूची बना सकते हैं, जिन्हें आप कर सकते हैं। /codegolf/54/tips-for-golfing-in-python

हालांकि सामान्य कोड में इसका उपयोग कभी नहीं किया जाना चाहिए, और आपके मामले में इसका मतलब यह होगा कि xदोनों एक पूर्णांक के रूप में तुलना की जा सकती है और एक कंटेनर के रूप में कार्य किया जा सकता है जो स्लाइसिंग का समर्थन करता है, जो एक बहुत ही असामान्य संयोजन है। यह शायद Numpy कोड है, जैसा कि दूसरों ने बताया है।


6
Code Golf is the art of writing programs: ')
बिल्ली

1
माइनर nitpick: bool नहीं है डाली को पूर्णांक में, यह सिर्फ है एक (अन्य उत्तर देखें)
बिल्ली

6

सामान्य तौर पर इसका मतलब कुछ भी हो सकता है । यह पहले से ही था समझाया कि इसका क्या मतलब है, तो xएक listया numpy.ndarrayलेकिन सामान्य रूप में यह केवल कैसे तुलना ऑपरेटरों (पर निर्भर करता है <, >, ...) है और यह भी कैसे प्राप्त / सेट मद ( [...]-syntax) लागू किया जाता है।

x.__getitem__(x.__lt__(2))      # this is what x[x < 2] means!
x.__setitem__(x.__lt__(2), 0)   # this is what x[x < 2] = 0 means!

चूंकि:

  • x < value के बराबर है x.__lt__(value)
  • x[value] (लगभग) के बराबर है x.__getitem__(value)
  • x[value] = othervalue(भी लगभग) के बराबर है x.__setitem__(value, othervalue)

यह आप चाहते हैं कुछ भी करने के लिए अनुकूलित किया जा सकता है । बस एक उदाहरण के रूप में (थोड़ा सांकेतिक-बूलियन अनुक्रमण की नकल करता है):

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

    def __lt__(self, other):
        # You could do anything in here. For example create a new list indicating if that 
        # element is less than the other value
        res = [item < other for item in self.value]
        return self.__class__(res)

    def __repr__(self):
        return '{0} ({1})'.format(self.__class__.__name__, self.value)

    def __getitem__(self, item):
        # If you index with an instance of this class use "boolean-indexing"
        if isinstance(item, Test):
            res = self.__class__([i for i, index in zip(self.value, item) if index])
            return res
        # Something else was given just try to use it on the value
        return self.value[item]

    def __setitem__(self, item, value):
        if isinstance(item, Test):
            self.value = [i if not index else value for i, index in zip(self.value, item)]
        else:
            self.value[item] = value

तो अब देखते हैं कि इसका उपयोग करने पर क्या होता है:

>>> a = Test([1,2,3])
>>> a
Test ([1, 2, 3])
>>> a < 2  # calls __lt__
Test ([True, False, False])
>>> a[Test([True, False, False])] # calls __getitem__
Test ([1])
>>> a[a < 2] # or short form
Test ([1])

>>> a[a < 2] = 0  # calls __setitem__
>>> a
Test ([0, 2, 3])

ध्यान दें कि यह सिर्फ एक संभावना है। आप अपनी इच्छानुसार लगभग हर चीज को लागू करने के लिए स्वतंत्र हैं।


मैं कहूंगा कि किसी भी चीज़ का उपयोग करना वास्तव में स्वीकृत उत्तर की तरह तार्किक रूप से समझाने योग्य व्यवहार के लिए बहुत सामान्य है।
पास्कलवीकूटेन

@PascalvKooten क्या आप "कुछ भी" या सामान्यीकृत उत्तर से असहमत हैं? मुझे लगता है कि यह एक महत्वपूर्ण बिंदु है क्योंकि अजगर में सबसे तार्किक व्यवहार सिर्फ सम्मेलन द्वारा किया जाता है।
MSeifert
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.