List.join (string) के बजाय इसे string.join (सूची) क्यों है?


1761

इसने मुझे हमेशा भ्रमित किया है। ऐसा लगता है कि यह अच्छा होगा:

my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"

उसके बाद यह:

my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"

क्या कोई विशिष्ट कारण है जो इस तरह है?


1
आसान स्मृति और समझ के लिए, -घोषणा करता है कि आप एक सूची में शामिल हो रहे हैं और एक स्ट्रिंग में परिवर्तित कर रहे हैं। यह परिणाम उन्मुख है।
पथरी

11
@ जवासा: यह सिर्फ मेम को और अधिक भ्रमित करता है।
einpoklum

32
मुझे लगता है कि संक्षिप्त उत्तर यह है कि यह इसलिए है क्योंकि पायथन का प्रकार प्रणाली पर्याप्त मजबूत नहीं है, और इस कार्यक्षमता को एक बार strलागू करने की तुलना में इसे हर प्रकार के प्रकार पर लागू करना आसान था ।
बॉलपॉइंटबैन

3
मुझे लगता है कि मूल विचार यह है कि क्योंकि जुड़ने () एक स्ट्रिंग लौटाता है, इसे स्ट्रिंग संदर्भ से कॉल करना होगा। किसी सूची में शामिल होने () में एक टन का अर्थ यह नहीं है कि एक सूची वस्तुओं का एक कंटेनर है और केवल तारों के लिए विशिष्ट एक-बंद फ़ंक्शन नहीं होना चाहिए।
जोशुआ

जवाबों:


1247

यह इसलिए है क्योंकि किसी भी चलने योग्य को शामिल किया जा सकता है (जैसे, सूची, टपल, तानाशाही, सेट), लेकिन परिणाम और "जॉइनर" तार होना चाहिए

उदाहरण के लिए:

'_'.join(['welcome', 'to', 'stack', 'overflow'])
'_'.join(('welcome', 'to', 'stack', 'overflow'))
'welcome_to_stack_overflow'

स्ट्रिंग्स की तुलना में कुछ और का उपयोग करना निम्न त्रुटि को बढ़ाएगा:

TypeError: अनुक्रम आइटम 0: अपेक्षित str उदाहरण, int पाया


55
मैं अवधारणा से सहमत नहीं हूं भले ही यह समझ में आता हो। list.join(string)अधिक वस्तु-उन्मुख दृष्टिकोण प्रकट होता है जबकि string.join(list)मेरे लिए बहुत अधिक प्रक्रियात्मक लगता है।
एडुआर्डो पिगनैटेली

21
तो क्यों इसे लागू नहीं किया गया है?
स्टीन स्कुट

10
@TimeSheep: पूर्णांक की एक सूची में एक सार्थक जुड़ाव नहीं है, भले ही यह चलने योग्य हो।
पुनरावर्ती

16
मैंने उपयोग करने की कोशिश की है print(str.join('-', my_list))और यह काम करता है, बेहतर महसूस करता है।
pimgeek

13
@TimeSheep क्योंकि iterable एक ठोस प्रकार नहीं है, iterable एक इंटरफ़ेस है, कोई भी प्रकार जो किसी __iter__विधि को परिभाषित करता है । लागू करने के लिए सभी पुनरावृत्तियों की आवश्यकता joinएक बहुत ही विशेष उपयोग के मामले के लिए एक सामान्य इंटरफ़ेस (जो गैर-तार पर पुनरावृत्तियों को भी शामिल करता है) को जटिल करेगा। " joinअनजाने" आदेश की कीमत पर स्ट्रेन के पक्ष में इस समस्या को परिभाषित करना । एक बेहतर विकल्प यह हो सकता है कि इसे एक फ़ंक्शन रखें जिसमें पहला तर्क चलने योग्य हो और दूसरा (वैकल्पिक एक) जॉइनर स्ट्रिंग हो - लेकिन वह जहाज रवाना हो चुका है।
user4815162342

318

यह स्ट्रिंग के तरीकों पर चर्चा की गई थी ... आखिरकार पायथन-देव अचीव में धागा, और गुइडो द्वारा स्वीकार किया गया था। यह धागा जून 1999 में शुरू हुआ था, और str.joinइसे पायथन 1.6 में शामिल किया गया था जिसे सितंबर 2000 में जारी किया गया था (और यूनिकोड समर्थित)। पायथन 2.0 (समर्थित strविधियों सहित join) अक्टूबर 2000 में जारी किया गया था।

  • इस धागे में चार विकल्प प्रस्तावित थे:
    • str.join(seq)
    • seq.join(str)
    • seq.reduce(str)
    • join एक अंतर्निहित कार्य के रूप में
  • गुइडो न केवल listएस, tupleएस, बल्कि सभी दृश्यों / पुनरावृत्तियों का समर्थन करना चाहता था ।
  • seq.reduce(str) नए लोगों के लिए मुश्किल है।
  • seq.join(str) अनुक्रमों से लेकर str / यूनिकोड तक अप्रत्याशित निर्भरता का परिचय देता है।
  • join()एक अंतर्निहित फ़ंक्शन के रूप में केवल विशिष्ट डेटा प्रकारों का समर्थन करेगा। इसलिए निर्मित नेमस्पेस का उपयोग करना अच्छा नहीं है। यदि join()कई डेटाटिप्स का समर्थन करता है, तो अनुकूलित कार्यान्वयन बनाना मुश्किल होगा, यदि __add__विधि का उपयोग करके कार्यान्वित किया जाता है तो यह O (n²) है।
  • विभाजक स्ट्रिंग ( sep) को छोड़ा नहीं जाना चाहिए। निहितार्थ की तुलना में स्पष्ट है।

इस सूत्र में कोई अन्य कारण नहीं दिए गए हैं।

यहाँ कुछ अतिरिक्त विचार हैं (मेरे अपने, और मेरे मित्र के):

  • यूनिकोड समर्थन आ रहा था, लेकिन यह अंतिम नहीं था। उस समय UTF-8 UCS2 / 4 को बदलने के बारे में सबसे अधिक संभावना थी। UTF-8 स्ट्रिंग्स की कुल बफर लंबाई की गणना करने के लिए इसे वर्ण कोडिंग नियम जानना आवश्यक है।
  • उस समय, पायथन ने पहले से ही एक सामान्य अनुक्रम इंटरफ़ेस नियम पर निर्णय लिया था, जहां उपयोगकर्ता अनुक्रम-जैसा (चलने योग्य) वर्ग बना सकता है। लेकिन पायथन ने 2.2 तक अंतर्निहित प्रकारों का विस्तार करने का समर्थन नहीं किया। उस समय मूल चलने योग्य वर्ग (जो किसी अन्य टिप्पणी में उल्लिखित है) प्रदान करना मुश्किल था।

गुइडो का निर्णय एक ऐतिहासिक मेल में दर्ज किया गया है , जिस पर निर्णय लिया गया है str.join(seq):

अजीब बात है, लेकिन यह सही लगता है! बैरी, इसके लिए जाओ ... -
ग्यूडो वैन रोसुम


251

क्योंकि join()विधि स्ट्रिंग वर्ग में है, सूची वर्ग के बजाय?

मैं मानता हूं कि यह मजाकिया लग रहा है।

Http://www.faqs.org/docs/diveintopython/odbchelper_join.html देखें :

ऐतिहासिक नोट।जब मैंने पहली बार पायथन को सीखा, तो मुझे उम्मीद थी कि मैं एक सूची में शामिल हो जाऊंगा, जो परिसीमनक को एक तर्क के रूप में लेगा। बहुत से लोग उसी तरह महसूस करते हैं, और इसमें शामिल होने के तरीके के पीछे एक कहानी है। अजगर 1.6 से पहले, तार में ये सभी उपयोगी तरीके नहीं थे। एक अलग स्ट्रिंग मॉड्यूल था जिसमें सभी स्ट्रिंग फ़ंक्शन शामिल थे; प्रत्येक फ़ंक्शन ने पहले तर्क के रूप में एक स्ट्रिंग ली। फंक्शंस को महत्वपूर्ण रूप से स्ट्रिंग्स पर डालने के लिए पर्याप्त माना जाता था, जो निचले, ऊपरी और विभाजन जैसे कार्यों के लिए समझ में आता था। लेकिन कई हार्ड-कोर पायथन प्रोग्रामर्स ने नए जॉइन मेथड पर आपत्ति जताई, यह तर्क देते हुए कि यह सूची की एक विधि होनी चाहिए, या यह कि यह बिल्कुल भी नहीं चलना चाहिए, लेकिन बस पुराने स्ट्रिंग मॉड्यूल का एक हिस्सा रहें (जो अभी भी बहुत सारे हैं इसमें उपयोगी सामान)।

--- मार्क तीर्थयात्री, अजगर में कूदो


12
पायथन 3 stringलाइब्रेरी ने सभी अनावश्यक strतरीकों को हटा दिया है , इसलिए आप अब उपयोग नहीं कर सकते हैं string.join()। व्यक्तिगत रूप से, मैंने कभी भी इसे 'मजाकिया' नहीं समझा, यह सही अर्थ है, क्योंकि आप सिर्फ सूचियों की तुलना में बहुत अधिक शामिल हो सकते हैं, लेकिन जुड़ने वाला हमेशा एक स्ट्रिंग होता है!
मार्टिन पीटर्स

67

मैं मानता हूं कि यह पहली बार में प्रतिशोधात्मक है, लेकिन एक अच्छा कारण है। शामिल होने की सूची का एक तरीका नहीं हो सकता क्योंकि:

  • यह विभिन्न पुनरावृत्तियों के लिए भी काम करना चाहिए (टुपल्स, जनरेटर, आदि)
  • विभिन्न प्रकार के तारों के बीच अलग-अलग व्यवहार होना चाहिए।

वास्तव में दो जुड़ने के तरीके हैं (पायथन 3.0):

>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>

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


45

इसके string.join(list)बजाय क्यों है list.join(string)?

ऐसा इसलिए है क्योंकि joinएक "स्ट्रिंग" विधि है! यह किसी भी चलने योग्य से एक स्ट्रिंग बनाता है। यदि हम सूचियों पर विधि अटक जाते हैं, तो क्या होगा जब हमारे पास पुनरावृत्तियाँ हैं जो सूचियाँ नहीं हैं?

क्या होगा यदि आपके पास तार का एक टुकड़ा है? यदि यह एक listविधि थी, तो आपको स्ट्रिंग्स के प्रत्येक ऐसे पुनरावृत्तिकर्ता को listपहले लाना होगा क्योंकि आप तत्वों को एक स्ट्रिंग में शामिल कर सकते हैं! उदाहरण के लिए:

some_strings = ('foo', 'bar', 'baz')

आइए हम अपनी सूची में शामिल होने की विधि को रोल करें:

class OurList(list): 
    def join(self, s):
        return s.join(self)

और इसका उपयोग करने के लिए, ध्यान दें कि हमें सबसे पहले प्रत्येक पुनरावृत्ति से एक सूची बनानी होगी जो उस पुनरावृत्ति में तार जुड़ने के लिए स्मृति और प्रसंस्करण शक्ति दोनों को बर्बाद कर दे:

>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'

इसलिए हम देखते हैं कि हमें अपनी सूची विधि का उपयोग करने के लिए एक अतिरिक्त कदम जोड़ना होगा, बजाय केवल अंतर्निहित स्ट्रिंग विधि का उपयोग करने के लिए:

>>> ' | '.join(some_strings) # a single step!
'foo | bar | baz'

जेनरेटर के लिए प्रदर्शन कैवेट

एल्गोरिथ्म पाइथन अंतिम स्ट्रिंग बनाने के लिए उपयोग करता है जिसके साथ str.joinवास्तव में दो बार से अधिक चलना पड़ता है, इसलिए यदि आप इसे जनरेटर अभिव्यक्ति प्रदान करते हैं, तो इसे अंतिम स्ट्रिंग बनाने से पहले इसे पहले सूची में बदलना होगा।

इस प्रकार, जेनरेटरों के आसपास से गुजरना आमतौर पर सूची की समझ से बेहतर है, str.joinएक अपवाद है:

>>> import timeit
>>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
3.839168446022086
>>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
3.339879313018173

फिर भी, str.joinऑपरेशन अभी भी शब्दशः एक "स्ट्रिंग" ऑपरेशन है, इसलिए यह अभी भी यह है कि यह strवस्तु पर विविध iterables की तुलना में है।


24

इसे विभाजित करने के लिए प्राकृतिक ऑर्थोगोनल ऑपरेशन के रूप में सोचें।

मैं समझता हूं कि यह कुछ भी लागू होने योग्य नहीं है और इसलिए इसे आसानी से सिर्फ सूची में लागू नहीं किया जा सकता है ।

पठनीयता के लिए, मैं इसे भाषा में देखना चाहता हूं, लेकिन मुझे नहीं लगता कि यह वास्तव में संभव है - अगर पुनरावृत्ति एक इंटरफ़ेस था, तो इसे इंटरफ़ेस में जोड़ा जा सकता है, लेकिन यह सिर्फ एक सम्मेलन है और इसलिए इसका कोई केंद्रीय तरीका नहीं है इसे उन चीजों के सेट में जोड़ें जो चलने योग्य हैं।


13

मुख्य रूप से क्योंकि एक का परिणाम someString.join()एक स्ट्रिंग है।

अनुक्रम (सूची या तुच्छ या जो भी) परिणाम में प्रकट नहीं होता है, बस एक स्ट्रिंग। क्योंकि परिणाम एक स्ट्रिंग है, यह एक स्ट्रिंग की विधि के रूप में समझ में आता है।


10

- "-" में शामिल हों (my_list) घोषित करता है कि आप तत्वों को एक सूची में शामिल होने से एक स्ट्रिंग में परिवर्तित कर रहे हैं। यह परिणाम-उन्मुख है (सिर्फ आसान स्मृति और समझ के लिए)।

मैं आपके संदर्भ के लिए मेथड्स_of_string की एक विस्तृत धोखा देती हूं।

string_methonds_44 = {
    'convert': ['join','split', 'rsplit','splitlines', 'partition', 'rpartition'],
    'edit': ['replace', 'lstrip', 'rstrip', 'strip'],
    'search': ['endswith', 'startswith', 'count', 'index', 'find','rindex', 'rfind',],
    'condition': ['isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isnumeric','isidentifier',
                  'islower','istitle', 'isupper','isprintable', 'isspace', ],
    'text': ['lower', 'upper', 'capitalize', 'title', 'swapcase',
             'center', 'ljust', 'rjust', 'zfill', 'expandtabs','casefold'],
    'encode': ['translate', 'maketrans', 'encode'],
    'format': ['format', 'format_map']}

3

दोनों अच्छे नहीं हैं।

string.join (xs, delimit) का मतलब है कि स्ट्रिंग मॉड्यूल एक सूची के अस्तित्व से अवगत है, जिसके बारे में यह जानने का कोई व्यवसाय नहीं है, क्योंकि स्ट्रिंग मॉड्यूल केवल स्ट्रिंग्स के साथ काम करता है।

list.join (delimit) थोड़ा अच्छा है क्योंकि हम एक मौलिक प्रकार होने के लिए उपयोग कर रहे हैं (और भाषाई रूप से, वे हैं)। हालांकि इसका मतलब यह है कि जुड़ने को गतिशील रूप से भेजने की आवश्यकता है क्योंकि a.split("\n")अजगर संकलक के मनमाने संदर्भ में पता नहीं हो सकता है कि एक क्या है, और इसे देखने की आवश्यकता होगी (अनुरूप रूप से देखने के लिए), जो महंगा है यदि आप इसे बहुत करते हैं बार।

अगर पायथन रनटाइम कंपाइलर जानता है कि सूची एक मॉड्यूल में बनाया गया है, तो यह डायनेमिक लुकअप को छोड़ सकता है और आशय को सीधे बायटेकोड में एनकोड कर सकता है, जबकि अन्यथा इसे गतिशील रूप से "ए" के "ज्वाइन" को हल करने की आवश्यकता होती है, जो कई परतों में हो सकती है। प्रति कॉल की विरासत (कॉल के बीच से, जुड़ने का अर्थ बदल गया हो सकता है, क्योंकि अजगर एक गतिशील भाषा है)।

दुख की बात है, यह अमूर्तता का अंतिम दोष है; कोई फर्क नहीं पड़ता कि आप क्या अमूर्त चुनते हैं, आपकी अमूर्तता केवल उस समस्या के संदर्भ में समझ में आएगी जिसे आप हल करने की कोशिश कर रहे हैं, और जैसे कि आप कभी भी एक सुसंगत अमूर्त नहीं हो सकते हैं जो अंतर्निहित विचारधाराओं के साथ असंगत नहीं बनते हैं क्योंकि आप उन्हें gluing करना शुरू करते हैं साथ में उन्हें एक विचार में लपेटे बिना जो आपकी विचारधारा के अनुरूप है। यह जानने के बाद, अजगर का दृष्टिकोण अधिक लचीला है क्योंकि यह सस्ता है, यह आप पर निर्भर है कि आप इसे "अच्छे" बनाने के लिए अधिक भुगतान करें, या तो अपने स्वयं के आवरण, या अपने स्वयं के प्रीप्रोसेसर द्वारा।


0

चरों my_listऔर "-"दोनों वस्तुएं हैं। विशेष रूप से, वे क्रमशः कक्षाओं के उदाहरण हैं listऔर strjoinसमारोह वर्ग के अंतर्गत आता है str। इसलिए, सिंटैक्स "-".join(my_list)का उपयोग किया जाता है क्योंकि ऑब्जेक्ट एक इनपुट के रूप "-"में ले रहा है my_list

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.