আমি কীভাবে পাইথন স্ট্রিংটি অনুলিপি করতে পারি?


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?


4
মার্তিজিনের থেকে পৃথক উত্তর পেতে (যা সম্পূর্ণরূপে সঠিক, যদিও বলা হয়েছে যেভাবে প্রশ্নের উত্তর দেয় না) আপনি কেন এটি অনুলিপি করতে চান তা আরও বিশদ / ব্যবহারের ক্ষেত্রে সরবরাহ করতে চাইতে পারেন।
এলমো

4
@ ইলেমো সূচিত হিসাবে, এটি একটি এক্সওয়াই সমস্যা হতে পারে ।
মার্টিনো

4
আমি ফর্মটির নেস্টেড অভিধানের মেমরির ব্যবহারের অনুমান করতে আগ্রহী ছিলাম d[ 'hello' ] = e, কোথায় e[ 'hi' ] = 'again'। এ জাতীয় নেস্টেড ডিকশনারি তৈরি করতে, আমি একটি একক eঅভিধান তৈরি করেছি এবং একাধিকবার এটি অনুলিপি করেছি। আমি লক্ষ্য করেছি যে মেমরির খরচ খুব কম, যার ফলে এখানে আমার প্রশ্ন উঠেছে। এখন আমি বুঝতে পারি যে কোনও স্ট্রিং অনুলিপি তৈরি করা হয়নি, সুতরাং কম স্মৃতিশক্তি গ্রহণ।
যথারীতি আমাকে

4
আপনি যদি কোনও পরিবর্তন না করেই bএকটি পরিবর্তিত সংস্করণ হতে চান তবে যে কোনও ক্রিয়াকলাপের ফলাফল হোক। যেমন সেট করতে এবং দেহাবশেষ ' । aabb = a[2:-1]b'll'ahello'
ওজেফোর্ড 17'14

অলি ঠিক আছে। এটি কারণ str একটি অপরিবর্তনীয় প্রকার। পাইথনের সিঙ্গলটনের ব্যবহারের কারণে (এবং সম্ভবত অন্যান্য অভ্যন্তরীণ অপ্টিমাইজেশান), ই অভিধানটি অনুলিপি করার সময় আপনি যেভাবে প্রত্যাশা করেছিলেন তা স্মৃতিশক্তিটি প্রসারণ করতে পারবেন না।
ফিজক্সমাইক

উত্তর:


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)
মার্টিনো

@ মার্টিনো: অবশ্যই, আমি আসলে 'ওয়ান ওয়ে' বলতে চাইছিলাম।
মার্টিজন পিটারস

10
"আপনাকে পাইথন স্ট্রিংটি অনুলিপি করার দরকার নেই" উপর জোর দিন। এই ক্রিয়াকলাপগুলি কেবল একই স্ট্রিংটি ফিরে আসার একটি কারণ রয়েছে।
tcooc

4
এই ক্ষেত্রে, যদিও ওপি মেমরি নষ্ট করার চেষ্টা করছে। যেহেতু তিনি জানতে চান যে নির্দিষ্ট পরিমাণের স্ট্রিং দ্বারা কত স্মৃতি ব্যবহৃত হবে, এটিই আসল লক্ষ্য। স্পষ্টতই তিনি অনন্য স্ট্রিং তৈরি করতে পেরেছিলেন, তবে এটি কেবলমাত্র কাজের অকারণ হিসাবে কাজ নয়।
গাবে

8
42 "আউটপুট হবে এমন একটি উদাহরণ ব্যবহার করে" কেসুল্যালি "জন্য +1 ।
বাকুরিউ

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 = a কে অনুলিপি করুন বা আপনি ক্লোন করতে পারবেন যার অর্থ b পরিবর্তন হবে যখন a = 'a' b = a [:]


2

এটিকে অন্যভাবে রাখার জন্য "আইডি ()" আপনার পছন্দের বিষয় নয়। উত্স পরিবর্তনশীল নামটি ক্ষতি না করে পরিবর্তনশীল নামটি সংশোধন করা যায় কিনা তা আপনি জানতে চান।

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

আপনি যদি সি ব্যবহার করেন তবে এগুলি পয়েন্টার ভেরিয়েবলের মতো তবে আপনি কী নির্দেশ করেছেন সেগুলি পরিবর্তন করতে আপনি তাদের ডি-রেফারেন্স করতে পারবেন না তবে id () আপনাকে বর্তমানে তারা কোথায় নির্দেশ করবে তা আপনাকে জানিয়ে দেবে।

পাইথন প্রোগ্রামারদের সমস্যাটি তখন আসে যখন আপনি গভীর কাঠামোগত তালিকা বা ডিক্টের মতো বিবেচনা করেন:

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

এখানে ও ও এক্স একই ডিক ও ['' এ '] এবং এক্স [' এ '] উল্লেখ করে এবং সেই ডিকটি "পরিবর্তিত" এই অর্থে যে আপনি কী' এ 'এর মান পরিবর্তন করতে পারেন। এজন্য "y" এর একটি অনুলিপি হওয়া দরকার এবং y ['a'] অন্য কোনও কিছু উল্লেখ করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.