पायथन 3 में स्ट्रिंग को बाइट में बदलने का सबसे अच्छा तरीका?


858

स्ट्रिंग को बाइट में बदलने के लिए दो अलग-अलग तरीके दिखाई देते हैं, जैसा कि TypeError के उत्तर में देखा गया है : 'str' बफर इंटरफ़ेस का समर्थन नहीं करता है

इनमें से कौन सा तरीका बेहतर या अधिक पायथोनिक होगा? या यह सिर्फ व्यक्तिगत पसंद की बात है?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')

42
एन्कोड / डिकोड का उपयोग अधिक सामान्य है, और शायद अधिक स्पष्ट है।
लेनार्ट रेगेब्र सिप

11
@ LennartRegebro मैं खारिज करता हूं। यहां तक ​​कि अगर यह अधिक सामान्य है, तो "बाइट्स ()" पढ़ना मुझे पता है कि इसका क्या करना है, जबकि एनकोड () मुझे ऐसा नहीं लगता कि यह बाइट्स के लिए एन्कोडिंग है।
m3nda

2
@ erm3nda इसका उपयोग करने का एक अच्छा कारण है जब तक कि ऐसा महसूस न हो , तब आप यूनिकोड जेन के करीब एक कदम हैं।
लेनार्ट रेगेब्रॉ

3
@ LennartRegebro मुझे केवल उपयोग करने के लिए काफी अच्छा लगता है bytes(item, "utf8"), जैसा कि स्पष्ट है कि निहितार्थ से बेहतर है, इसलिए ... str.encode( )चुपचाप बाइट्स के लिए चूक, आपको अधिक यूनिकोड-ज़ेन लेकिन कम स्पष्ट-ज़ेन बना देता है। इसके अलावा "आम" एक शब्द नहीं है जिसे मैं अनुसरण करना पसंद करता हूं। इसके अलावा, bytes(item, "utf8")और अधिक की तरह है str(), और b"string"अंकन। मेरे क्षमायाचना अगर मैं अपने कारणों को समझने के लिए इतना noob हूँ। धन्यवाद।
m3nda

4
@ erm3nda यदि आप स्वीकृत उत्तर पढ़ते हैं तो आप देख सकते हैं कि encode()यह कॉल नहीं करता है bytes(), यह दूसरा तरीका है। बेशक यह तुरंत स्पष्ट नहीं है, यही वजह है कि मैंने सवाल पूछा।
मार्क रैनसम

जवाबों:


570

यदि आप डॉक्स को देखते हैं bytes, तो यह आपको bytearrayनिम्न बिंदुओं की ओर इशारा करता है :

bytearray ([स्रोत [, एन्कोडिंग [, त्रुटियाँ]]])

बाइट्स की एक नई सरणी लौटें। बाइटरेयर प्रकार 0 <= x <256 सीमा में पूर्णांकों का एक परिवर्तनशील अनुक्रम है। इसमें उत्परिवर्ती अनुक्रमों के सामान्य तरीकों में से अधिकांश हैं, जो म्यूटेबल सीक्वेंस प्रकारों में वर्णित हैं, साथ ही अधिकांश विधियाँ जो बाइट्स प्रकार की हैं, देखें बाइट्स और बाइट ऐरे मेथड्स।

वैकल्पिक स्रोत पैरामीटर का उपयोग कुछ भिन्न तरीकों से सरणी को इनिशियलाइज़ करने के लिए किया जा सकता है:

यदि यह एक स्ट्रिंग है, तो आपको एन्कोडिंग (और वैकल्पिक रूप से, त्रुटियां) पैरामीटर भी देना होगा; bytearray () तब string को बाइट्स में कनवर्ट करके str.encode () का उपयोग करता है।

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

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

यदि यह एक चलने योग्य है, तो यह 0 <= x <256 सीमा में पूर्णांकों का एक पुनरावृत्ति होना चाहिए, जो कि सरणी की प्रारंभिक सामग्री के रूप में उपयोग किया जाता है।

एक तर्क के बिना, आकार 0 का एक सरणी बनाया जाता है।

तो bytesबस एक स्ट्रिंग को एन्कोड करने से बहुत कुछ हो सकता है। यह पाइथोनिक है कि यह आपको किसी भी प्रकार के स्रोत पैरामीटर के साथ कंस्ट्रक्टर को कॉल करने की अनुमति देगा जो समझ में आता है।

एक स्ट्रिंग को एन्कोडिंग के लिए, मुझे लगता है कि some_string.encode(encoding)कंस्ट्रक्टर का उपयोग करने की तुलना में अधिक पायथोनिक है, क्योंकि यह सबसे स्व-दस्तावेजीकरण है - "इस स्ट्रिंग को लें और इसे इस एन्कोडिंग के साथ एनकोड करें" की तुलना में स्पष्ट है bytes(some_string, encoding)- जब आप स्ट्रिंग का उपयोग करते हैं तो कोई स्पष्ट क्रिया नहीं होती है। निर्माता।

संपादित करें: मैंने पायथन स्रोत की जाँच की। यदि आप bytesCPython का उपयोग करने के लिए एक यूनिकोड स्ट्रिंग पास करते हैं, तो यह PyUnicode_AsEncodedString को कॉल करता है, जिसका कार्यान्वयन है encode; इसलिए यदि आप encodeस्वयं को कॉल करते हैं तो आप अप्रत्यक्ष स्तर को छोड़ रहे हैं ।

इसके अलावा, सर्दालिस की टिप्पणी देखें - unicode_string.encode(encoding)यह भी अधिक पायथोनिक है क्योंकि इसका उलटा है byte_string.decode(encoding)और समरूपता अच्छी है।


73
एक अच्छा तर्क और अजगर डॉक्स से उद्धरण के लिए +1। इसके अलावा unicode_string.encode(encoding)के साथ अच्छी तरह से मेल खाता है bytearray.decode(encoding), जब आप अपने स्ट्रिंग वापस चाहते हैं।
सेरडालिस

6
bytearrayका उपयोग तब किया जाता है जब आपको एक परिवर्तनशील वस्तु की आवश्यकता होती है। आप साधारण के लिए इसकी आवश्यकता नहीं है strbytesरूपांतरण।
हम्सटरजेन

8
@EugeneHomyakov इसका कोई लेना-देना नहीं है bytearrayसिवाय इसके कि डॉक्स bytesविवरण नहीं देते, वे बस कहते हैं "यह एक अपरिवर्तनीय संस्करण है bytearray" इसलिए मुझे वहां से उद्धृत करना होगा।
agf

1
संक्षेप में पायथन से एक सावधान नोट के बारे में bytes: एक पूर्णांक तर्क के साथ एक फ़ंक्शन के रूप में बाइट्स प्रकार का उपयोग करने से बचें। V2 में यह एक (बाइट) स्ट्रिंग में परिवर्तित पूर्णांक देता है क्योंकि बाइट्स str के लिए एक उपनाम है, जबकि v3 में यह एक बाइटस्ट्रिंग देता है जिसमें दिए गए शून्य वर्णों की संख्या होती है। इसलिए, उदाहरण के लिए, v3 अभिव्यक्ति बाइट्स (6) के बजाय, बराबर b '\ x00' * 6 का उपयोग करें, जो प्रत्येक संस्करण में समान रूप से काम करता है।
होल्डनवेब

2
बस एक ध्यान दें, कि यदि आप एक स्ट्रिंग के लिए बाइनरी डेटा कन्वर्ट करने के लिए कोशिश कर रहे हैं, तो आप के लिए कुछ प्रयोग संभवतः सबसे आवश्यक तरह हूँ byte_string.decode('latin-1')के रूप में utf-8संपूर्ण रेंज 0x00 0xFF के लिए (0-255), को कवर नहीं करता अजगर की जाँच डॉक्स के लिए और जानकारी।
iggy12345

346

यह जितना सोचा गया है उससे कहीं ज्यादा आसान है:

my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation

37
वह जानता है कि यह कैसे करना है, वह बस पूछ रहा है कि कौन सा तरीका बेहतर है। कृपया प्रश्न को पुनः पढ़ें।
एजीएफ

30
जानकारी के लिए: मेरे लिए str.decode (बाइट) नहीं किया काम (अजगर 3.3.3 कहा "प्रकार वस्तु 'str' कोई विशेषता 'डिकोड' है") के बजाय मैं इस्तेमाल किया bytes.decode ()
माइक

6
@ माइक: obj.method()सिंटैक्स के बजाय cls.method(obj)सिंटैक्स का उपयोग करें, का उपयोग करें bytestring = unicode_text.encode(encoding)और unicode_text = bytestring.decode(encoding)
JFS

2
... यानी आप अनावश्यक रूप से एक अनबाउंड विधि बना रहे हैं, और फिर इसे selfपहली दलील के रूप में पारित कर रहे हैं
एंटिटी हवाला

2
@KolobCanyon प्रश्न पहले से ही इसे करने का सही तरीका दिखाता है - encodeस्ट्रिंग पर एक बाध्य विधि के रूप में कॉल करता है। यह उत्तर बताता है कि आपको इसके बजाय अनबाउंड विधि को कॉल करना चाहिए और इसे स्ट्रिंग पास करना चाहिए। यह उत्तर में केवल नई जानकारी है, और यह गलत है।
abarnert

144

बिल्कुल सबसे अच्छा तरीका है 2 में से कोई भी है, लेकिन 3। पायथन 3.0 के बाद से कभी भी चूक करने वाला पहला पैरामीटर । इस प्रकार सबसे अच्छा तरीका हैencode 'utf-8'

b = mystring.encode()

यह तेजी से भी होगा, क्योंकि डिफ़ॉल्ट तर्क "utf-8"सी कोड में स्ट्रिंग में नहीं , लेकिन NULL, जो जांचने के लिए बहुत तेज है!

यहाँ कुछ समय हो:

In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop

In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop

चेतावनी के बावजूद बार-बार चलने के बाद समय बहुत स्थिर था - विचलन सिर्फ ~ 2 प्रतिशत था।


encode()एक तर्क के बिना उपयोग करना पायथन 2 संगत नहीं है, जैसा कि पायथन 2 में डिफ़ॉल्ट चरित्र एन्कोडिंग ASCII है

>>> 'äöä'.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

2
यहां केवल एक बड़ा अंतर है क्योंकि (ए) स्ट्रिंग शुद्ध ASCII है, जिसका अर्थ है कि आंतरिक भंडारण पहले से ही UTF-8 संस्करण है, इसलिए कोडेक को देखना लगभग एकमात्र लागत शामिल है, और (b) स्ट्रिंग छोटी है , इसलिए यदि आपको सांकेतिक शब्दों में बदलना है, तो भी इससे बहुत फर्क नहीं पड़ेगा। इसके साथ, कोशिश करो, कहते हैं '\u00012345'*10000। दोनों मेरे लैपटॉप पर 28.8; अतिरिक्त 50ns संभवतः राउंडिंग त्रुटि में खो गया है। बेशक यह एक बहुत ही चरम उदाहरण है — लेकिन 'abc'विपरीत दिशा में बस इतना ही चरम है।
गाली

@abarnert सच है, लेकिन फिर भी, कोई कारण नहीं है कि तर्क को एक स्ट्रिंग के रूप में पारित करें।
अंती हापला

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