मैं पायथन स्ट्रिंग की प्रतिलिपि कैसे बना सकता हूं?


92

मैं यह करता हूँ:

a = 'hello'

और अब मैं सिर्फ एक स्वतंत्र प्रति चाहता हूं a:

import copy

b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)

map( id, [ a,b,c,d,e ] )

आउट [3]:

[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]

उन सभी के पास एक ही मेमोरी एड्रेस क्यों है और मुझे इसकी एक प्रति कैसे मिल सकती है a?


3
Martijin से जवाब अलग प्राप्त करने के लिए (जो पूरी तरह से सही है, हालांकि जरूरी सवाल के रूप में कहा गया है उत्तर नहीं मिलता है) आप और अधिक विस्तार / उपयोग के मामले को दिखाने के लिए प्रदान करने के लिए चाहते हो सकता है क्यों आप चाहते हैं कॉपी।
एल्मो

4
जैसा कि @elemo का मतलब है, यह एक XY समस्या हो सकती है ।
मार्टिउ

2
मुझे प्रपत्र के एक नेस्टेड शब्दकोश की स्मृति उपयोग का अनुमान लगाने में रुचि थी d[ 'hello' ] = e, जहां e[ 'hi' ] = 'again'। इस तरह के नेस्टेड शब्दकोश को उत्पन्न करने के लिए, मैंने एक ही eशब्दकोश तैयार किया और इसे कई बार कॉपी किया। मैंने देखा कि मेमोरी की खपत बहुत कम थी, जिसके कारण यहां मेरा सवाल था। अब मैं समझता हूं कि कोई भी स्ट्रिंग प्रतियां नहीं बनाई गई थीं, इसलिए कम मेमोरी खपत।
आम तौर पर मुझे

1
यदि आप bसंशोधित aकिए बिना संशोधित संस्करण बनना चाहते हैं a, तो बस bजो भी हो, उसका परिणाम होने दें । जैसे b = a[2:-1]सेट bकरने के लिए 'll'और aअवशेष ' hello'
OJFord

ओली सही है। ऐसा इसलिए है क्योंकि str एक अपरिवर्तनीय प्रकार है। अजगर के सिंग्लेटों (और शायद अन्य आंतरिक अनुकूलन) के उपयोग के कारण, आप ई शब्दकोश की नकल करते समय आप की तरह स्मृति विस्तार नहीं देखेंगे।
FizxMike

जवाबों:


137

आपको पायथन स्ट्रिंग को कॉपी करने की आवश्यकता नहीं है । वे अपरिवर्तनीय हैं, और copyमॉड्यूल हमेशा ऐसे मामलों में मूल वापस करता है, जैसा कि करते हैं str(), पूरे स्ट्रिंग स्लाइस, और खाली स्ट्रिंग के साथ कंक्रीटिंग करते हैं।

इसके अलावा, आपका 'hello'तार नजरबंद है ( कुछ तार हैं )। पायथन जानबूझकर सिर्फ एक प्रति रखने की कोशिश करता है, क्योंकि इससे शब्दकोश देखने में तेजी आती है।

जिस तरह से आप इसके चारों ओर काम कर सकते हैं वह वास्तव में एक नई स्ट्रिंग बनाने के लिए है, फिर उस स्ट्रिंग को मूल सामग्री पर वापस करें:

>>> a = 'hello'
>>> b = (a + '.')[:-1]
>>> id(a), id(b)
(4435312528, 4435312432)

लेकिन अब आप जो कुछ भी कर रहे हैं वह बेकार की मेमोरी है। ऐसा नहीं है कि आप इन स्ट्रिंग ऑब्जेक्ट्स को किसी भी तरह से म्यूट कर सकते हैं, आखिरकार।

यदि आप सभी जानना चाहते हैं कि पायथन ऑब्जेक्ट को कितनी मेमोरी की आवश्यकता है, तो उपयोग करें sys.getsizeof(); यह आपको किसी भी पायथन ऑब्जेक्ट की मेमोरी फ़ुटप्रिंट देता है।

कंटेनरों के लिए इसमें सामग्री शामिल नहीं है ; कुल स्मृति आकार की गणना करने के लिए आपको प्रत्येक कंटेनर में फिर से भरना होगा:

>>> import sys
>>> a = 'hello'
>>> sys.getsizeof(a)
42
>>> b = {'foo': 'bar'}
>>> sys.getsizeof(b)
280
>>> sys.getsizeof(b) + sum(sys.getsizeof(k) + sys.getsizeof(v) for k, v in b.items())
360

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


4
नई स्ट्रिंग ऑब्जेक्ट बनाने के लिए केवल एक से अधिक तरीके हैं, जैसे कि b = ''.join(a)
14

@ स्मार्टिन्यू: निश्चित रूप से, मेरा वास्तव में 'एक ही रास्ता' कहने का था।
मार्टिन पीटर्स

10
"आपको पायथन स्ट्रिंग को कॉपी करने की आवश्यकता नहीं है" पर जोर दिया गया है। वहाँ एक कारण है कि उन आपरेशनों बस एक ही स्ट्रिंग लौटें।
14

1
इस मामले में, हालांकि, ओपी स्मृति को बर्बाद करने का प्रयास कर रहा है। चूँकि वह जानना चाहता है कि एक निश्चित मात्रा में तार कितनी मेमोरी का उपयोग करेगा, यही वास्तविक लक्ष्य है। जाहिर है कि वह अनोखे तार उत्पन्न कर सकता है, लेकिन यह सिर्फ एक बेकार काम है।
गाबे

8
एक उदाहरण का उपयोग करके "आकस्मिक रूप से" के लिए +1 जो 42 आउटपुट करेगा ।
बकुरीउ

11

आप स्ट्रिंग प्रारूपण के माध्यम से अजगर में एक स्ट्रिंग की नकल कर सकते हैं:

>>> a = 'foo'  
>>> b = '%s' % a  
>>> id(a), id(b)  
(140595444686784, 140595444726400)  

4
पाइथन 3.6.5 में सच नहीं है। आईडी (ए) और आईडी (बी) समान हैं। जब मैं प्रारूप के आधुनिक संस्करण का उपयोग करता हूं, तब भी परिणाम भिन्न नहीं होते हैं,b = '{:s}'.format(a)
शेषाद्री आर

7

मैं बस कुछ स्ट्रिंग जोड़तोड़ शुरू कर रहा हूं और इस सवाल को पाया। मैं शायद ओपी की तरह कुछ करने की कोशिश कर रहा था, "हमेशा की तरह"। पिछले जवाबों ने मेरा भ्रम दूर नहीं किया, लेकिन इसके बारे में थोड़ा सोचने के बाद आखिरकार मुझे "मिल गया"।

जब तक a, b, c, d, और eएक ही मूल्य है, वे एक ही जगह पर संदर्भित करें। स्मृति बच जाती है। जैसे ही चर के अलग-अलग मूल्य होने लगते हैं, उन्हें अलग-अलग संदर्भ मिलने लगते हैं। इस कोड से मेरा सीखने का अनुभव आया:

import copy
a = 'hello'
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)

print map( id, [ a,b,c,d,e ] )

print a, b, c, d, e

e = a + 'something'
a = 'goodbye'
print map( id, [ a,b,c,d,e ] )
print a, b, c, d, e

मुद्रित आउटपुट है:

[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]

hello hello hello hello hello

[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]

goodbye hello hello hello hello something

व्यवहार के लिए अधिक विवरण इस पोस्ट में वर्णित हैं stackoverflow.com/questions/2123925/…
dlasalle

3

एक स्ट्रिंग की नकल करना दो तरीकों से किया जा सकता है या तो स्थान को कॉपी करें a = "a" b = या आप क्लोन कर सकते हैं जिसका अर्थ है कि जब अभिप्रेत किया जाता है तो b अभ्यस्त प्रभावित हो जाता है जो a = 'a' b = [a] द्वारा किया जाता है


2

इसे अलग तरीके से रखने के लिए "आईडी ()" वह नहीं है जिसकी आपको परवाह है। आप जानना चाहते हैं कि क्या चर नाम को स्रोत चर नाम को नुकसान पहुंचाए बिना संशोधित किया जा सकता है।

>>> a = 'hello'                                                                                                                                                                                                                                                                                        
>>> b = a[:]                                                                                                                                                                                                                                                                                           
>>> c = a                                                                                                                                                                                                                                                                                              
>>> b += ' world'                                                                                                                                                                                                                                                                                      
>>> c += ', bye'                                                                                                                                                                                                                                                                                       
>>> a                                                                                                                                                                                                                                                                                                  
'hello'                                                                                                                                                                                                                                                                                                
>>> b                                                                                                                                                                                                                                                                                                  
'hello world'                                                                                                                                                                                                                                                                                          
>>> c                                                                                                                                                                                                                                                                                                  
'hello, bye'                                                                                                                                                                                                                                                                                           

यदि आप C के लिए उपयोग किए जाते हैं, तो ये पॉइंटर वैरिएबल की तरह होते हैं, सिवाय इसके कि आप उन्हें इंगित करने के लिए डी-रेफ़र नहीं कर सकते कि वे क्या इंगित करते हैं, लेकिन आईडी () आपको बताएंगे कि वे वर्तमान में कहाँ इंगित करते हैं।

अजगर प्रोग्रामर के लिए समस्या तब आती है जब आप सूची या डाइक जैसी गहरी संरचनाओं पर विचार करते हैं:

>>> o={'a': 10}                                                                                                                                                                                                                                                                                        
>>> x=o                                                                                                                                                                                                                                                                                                
>>> y=o.copy()                                                                                                                                                                                                                                                                                         
>>> x['a'] = 20                                                                                                                                                                                                                                                                                        
>>> y['a'] = 30                                                                                                                                                                                                                                                                                        
>>> o                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> x                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> y                                                                                                                                                                                                                                                                                                  
{'a': 30}                                                                                                                                                                                                                                                                                              

यहाँ o और x एक ही तानाशाह o ['a'] और x ['a'] को संदर्भित करते हैं, और यह ताना इस अर्थ में "परस्पर" है कि आप कुंजी 'a' के लिए मान बदल सकते हैं। इसीलिए "y" को कॉपी होने की आवश्यकता है और y ['a'] कुछ और को संदर्भित कर सकता है।

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