পাইথন একাধিক ভেরিয়েবল একই মান নির্ধারণ করে? তালিকা আচরণ


131

আমি ভেরিয়েবলগুলি সূচনা করার জন্য নীচের শো হিসাবে একাধিক অ্যাসাইনমেন্ট ব্যবহার করার চেষ্টা করেছি, তবে আচরণের ফলে আমি বিভ্রান্ত হয়ে পড়েছি, আমি পৃথকভাবে মান তালিকাকে পুনরায় স্বাক্ষর করার প্রত্যাশা করব, আমি খ [0] এবং সি [0] সমান 0 টি আগের মতই করব।

a=b=c=[0,3,5]
a[0]=1
print(a)
print(b)
print(c)

ফলাফলটি: [1, 3, 5] [1, 3, 5] [1, 3, 5]

এটা কি ঠিক? একাধিক কার্যভারের জন্য আমার কী ব্যবহার করা উচিত? এর থেকে আলাদা কী?

d=e=f=3
e=4
print('f:',f)
print('e:',e)

ফলাফল: ('f:', 3) ('ই:', 4)


2
আপনি কি চান a, bএবং, c,একই মান সব পয়েন্ট (এই ক্ষেত্রে একটি তালিকা), অথবা চাও a=0, b=3এবং, c=5। সেক্ষেত্রে, আপনি চান a,b,c = [0,3,5]বা শুধু a,b,c = 0,3,5
চিপনার

উত্তর:


271

আপনি যদি সি / জাভা / ইত্যাদির কোনও ভাষা থেকে পাইথনে আসছেন। পরিবার, এটি আপনাকে a"ভেরিয়েবল" হিসাবে চিন্তাভাবনা বন্ধ করতে এবং এটি একটি "নাম" হিসাবে ভাবতে শুরু করতে সহায়তা করতে পারে ।

a, bএবং cসমান মান সহ বিভিন্ন ভেরিয়েবল নয়; তারা একই অভিন্ন মানের জন্য বিভিন্ন নাম। চলকগুলির মধ্যে প্রকার, পরিচয়, ঠিকানা এবং সমস্ত ধরণের স্টাফ রয়েছে।

নামগুলির মধ্যে একটিও নেই। মানগুলি অবশ্যই করে এবং আপনার একই মানের জন্য প্রচুর নাম থাকতে পারে।

আপনি যদি Notorious B.I.G.একটি গরম কুকুর দেন, * Biggie Smallsএবং Chris Wallaceএকটি গরম কুকুর আছে। আপনি প্রথম উপাদান পরিবর্তন করেন তাহলে a1 থেকে, প্রথম উপাদান bএবং c1 হয়।

যদি আপনি জানতে চান যে দুটি নাম একই জিনিসটির নামকরণ করছে কিনা, isঅপারেটরটি ব্যবহার করুন :

>>> a=b=c=[0,3,5]
>>> a is b
True

আপনি তারপর জিজ্ঞাসা:

এর থেকে আলাদা কী?

d=e=f=3
e=4
print('f:',f)
print('e:',e)

এখানে, আপনি নাম rebinding করছি eমান 4। এটি নামগুলিকে dএবং কোনওভাবে প্রভাবিত করে না f

আপনার পূর্ববর্তী সংস্করণে, আপনি বরাদ্দ করেছিলেন a[0], না a। সুতরাং, দৃষ্টিকোণ থেকে a[0], আপনি রিমন্ডিং করছি a[0], কিন্তু দৃষ্টিকোণ থেকে a, আপনি এটি জায়গায় জায়গায় পরিবর্তন করছেন।

আপনি কোনও idফাংশনটি ব্যবহার করতে পারেন , যা আপনাকে কোনও অবজেক্টের পরিচয় উপস্থাপনের জন্য কিছু অনন্য নম্বর দেয়, ঠিক কোন বস্তুটি কোনটি যা isসহায়তা করতে পারে না তা দেখার জন্য:

>>> a=b=c=[0,3,5]
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261120
>>> id(b[0])
4297261120

>>> a[0] = 1
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261216
>>> id(b[0])
4297261216

লক্ষ্য করুন যে a[0]4297261120 থেকে 4297261216 এ পরিবর্তিত হয়েছে - এটি এখন ভিন্ন মানের একটি নাম। এবং b[0]এখন একই নতুন মান জন্য একটি নাম। এটি কারণ aএবং bএখনও একই জিনিসটির নামকরণ করা হচ্ছে।


কভারগুলির নীচে, a[0]=1আসলে তালিকার অবজেক্টে একটি পদ্ধতি কল করে। (এটি এর সমতুল্য a.__setitem__(0, 1)।) সুতরাং, এটি আসলে কিছুতেই রিব্যান্ডিং নয়। এটি কল করার মতো my_object.set_something(1)। অবশ্যই, সম্ভবত এই পদ্ধতিটি বাস্তবায়নের জন্য বস্তুটি কোনও উদাহরণের বৈশিষ্ট্যটি রিমান্ড করছে, তবে এটি গুরুত্বপূর্ণ নয়; গুরুত্বপূর্ণটি হ'ল আপনি কোনও কিছু বরাদ্দ দিচ্ছেন না, আপনি কেবলমাত্র বস্তুকে পরিবর্তন করছেন। এবং এটি একই a[0]=1


user570826 জিজ্ঞাসা করেছে:

আমাদের যদি হয়, a = b = c = 10

ঠিক ঠিক একই অবস্থা a = b = c = [1, 2, 3]: আপনার একই মানের তিনটি নাম রয়েছে।

তবে এই ক্ষেত্রে মানটি একটি intএবং intঅপরিবর্তনীয়। উভয় ক্ষেত্রেই, আপনি aআলাদা মানটিতে (যেমন, a = "Now I'm a string!") ফেরত দিতে পারেন , তবে এটি মূল মানটিকে প্রভাবিত করবে না, যা এর জন্য bএবং cএখনও এর নাম থাকবে। পার্থক্য হচ্ছে একটি তালিকা সঙ্গে, আপনি মান পরিবর্তন করতে পারেন [1, 2, 3]মধ্যে [1, 2, 3, 4]করে, যেমন, a.append(4); যেহেতু যে আসলে মান পরিবর্তন bএবং cজন্য নাম হয়, bএখন b হবে [1, 2, 3, 4]10আর কোনও কিছুতে মান পরিবর্তন করার কোনও উপায় নেই। 10চিরদিনের জন্য 10, ক্লোদিয়ার মতো ভ্যাম্পায়ার চিরকাল 5 টি (অন্তত তিনি কিরস্টন ডানস্টের পরিবর্তে)।


* সতর্কতা: কুখ্যাত বিগকে কোনও গরম কুকুর দেবেন না। গ্যাংস্টা র‌্যাপ জম্বিগুলি কখনই মধ্যরাতের পরে খাওয়ানো উচিত নয়।


যদি আমরা have, a = b = c = 10;এবং যখন আমরা খ এর মান আপডেট করার চেষ্টা করি, তবে এটি অন্য কোনওটির উপর প্রভাব ফেলে? যদিও আমি চেক করেছি তাদের আইডিস একই ??
এজে

@ user570826: 10পরিবর্তনযোগ্য - এর অর্থ মানটি আপডেট করার কোনও উপায় নেই, সুতরাং আপনার প্রশ্নের অর্থটি বোঝায় না। আপনি bএকটি ভিন্ন মানের দিকে নির্দেশ করতে পারেন , তবে এটি করার ফলে কোনও প্রভাব নেই aএবং cযা এখনও মূল মানের দিকে নির্দেশ করছে। তালিকাগুলি যে পার্থক্যটি করে তা হ'ল তারা পারস্পরিক পরিবর্তনযোগ্য — যেমন, আপনি appendএকটি তালিকায় যেতে পারেন , বা lst[0] = 3, এবং এটি মানটি আপডেট করবে, যা সেই মানটির জন্য সমস্ত নামের মাধ্যমে দৃশ্যমান হবে।
17

72

কাশি কাশি

>>> a,b,c = (1,2,3)
>>> a
1
>>> b
2
>>> c
3
>>> a,b,c = ({'test':'a'},{'test':'b'},{'test':'c'})
>>> a
{'test': 'a'}
>>> b
{'test': 'b'}
>>> c
{'test': 'c'}
>>> 

10
আইএমএইচও, এটি আসলে একাধিক অ্যাসাইনমেন্টের জন্য আমার কী ব্যবহার করা উচিত তার প্রথম কপির প্রশ্নের উত্তর দেয়, যদিও উপরের উচ্চতর রেটযুক্ত এবং আরও সেরিব্রাল উত্তর দেয় না।
উইল ক্রক্সফোর্ড

2
বা a,b,c = 1,2,3বন্ধনী ব্যতীত পাইথন 2 বা 3 এ কাজ করে, যদি আপনি সত্যিই সেই অতিরিক্ত সেমি পঠনযোগ্যতা চান।
উইল ক্রক্সফোর্ড

14

হ্যাঁ, এটি প্রত্যাশিত আচরণ। a, b এবং c সবগুলি একই তালিকার জন্য লেবেল হিসাবে সেট করা আছে। আপনি যদি তিনটি পৃথক তালিকা চান, আপনার পৃথকভাবে তাদের নিয়োগ করা দরকার। আপনি হয় সুস্পষ্ট তালিকার পুনরাবৃত্তি করতে পারেন, বা একটি তালিকা অনুলিপি করতে বিভিন্ন উপায়ে একটি ব্যবহার করতে পারেন:

b = a[:] # this does a shallow copy, which is good enough for this case
import copy
c = copy.deepcopy(a) # this does a deep copy, which matters if the list contains mutable objects

পাইথনে অ্যাসাইনমেন্টের স্টেটমেন্টগুলিতে অবজেক্টগুলি অনুলিপি করা হয় না - তারা নামটিকে কোনও বস্তুর সাথে বেঁধে রাখে এবং কোনও আইটেমটি আপনার সেট করার মতো অনেকগুলি লেবেল থাকতে পারে। আপনার [সম্পাদনা] [0] পরিবর্তন করে আপনার প্রথম সম্পাদনায় আপনি ক, খ, এবং সি উল্লেখ করেছেন যে একক তালিকার একটি উপাদান আপডেট করছেন। আপনার সেকেন্ডে, ই পরিবর্তন করে আপনি ইটিকে আলাদা কোনও অবজেক্টের (3 এর পরিবর্তে 4) লেবেল হিসাবে স্যুইচ করছেন।


13

পাইথনে, সমস্ত কিছুই একটি বস্তু, এছাড়াও "সরল" ভেরিয়েবলের প্রকার (ইনট, ফ্লোট ইত্যাদি)।

আপনি যখন কোনও ভেরিয়েবলের মান পরিবর্তন করেন, আপনি আসলে এটির পয়েন্টার পরিবর্তন করেন এবং আপনি যদি দুটি ভেরিয়েবলের মধ্যে তুলনা করেন তবে এটি তাদের পয়েন্টারের সাথে তুলনা করে । (পরিষ্কার করার জন্য, পয়েন্টার হ'ল ফিজিক্যাল কম্পিউটার মেমরির ঠিকানা যেখানে একটি ভেরিয়েবল সঞ্চয় করা থাকে)।

ফলস্বরূপ, আপনি যখন একটি অভ্যন্তরীণ ভেরিয়েবল মান পরিবর্তন করেন, আপনি মেমরিতে এটির মান পরিবর্তন করেন এবং এটি এই ঠিকানায় নির্দেশিত সমস্ত ভেরিয়েবলকে প্রভাবিত করে।

উদাহরণস্বরূপ, আপনি যখন করবেন:

a = b =  5 

এর অর্থ হ'ল a এবং b একই ঠিকানায় মেমোরিতে ইঙ্গিত করে যার মধ্যে মান 5 রয়েছে তবে আপনি যখন করবেন:

a = 6

এটি খ কে প্রভাবিত করে না কারণ এ এখন another টি থাকা মেমরির অন্য অবস্থানের দিকে নির্দেশ করে এবং খ এখনও contains টি থাকা মেমরি ঠিকানার দিকে নির্দেশ করে।

তবে, আপনি যখন করবেন:

a = b = [1,2,3]

a এবং b, আবার একই অবস্থান নির্দেশ করে তবে পার্থক্য হ'ল আপনি যদি তালিকার মানগুলির মধ্যে একটি পরিবর্তন করেন:

a[0] = 2

এটি মেমরির মানকে পরিবর্তিত করে যা একটি পয়েন্ট করে, তবে একটি এখনও খ হিসাবে একই ঠিকানার দিকে নির্দেশ করে এবং ফলস্বরূপ, বি পরিবর্তন হয়।


6
এটি অত্যন্ত বিভ্রান্তিকর। পাইথনগুলি অবশ্যই পাইথন স্তরে দৃশ্যমান নয় এবং চারটি বড় বাস্তবায়নের মধ্যে কমপক্ষে দু'টি (পিপিপি এবং জাইথন) এগুলি প্রয়োগের অভ্যন্তরে ব্যবহার করে না।
২৩

1
আপনি পাইথন ইন্টার্নালগুলি পড়তে এবং অন্বেষণে স্বাগত জানাই এবং আপনি আবিষ্কার করতে পারবেন যে পাইথনের প্রতিটি পরিবর্তনশীল আসলে পয়েন্টার।
ওরি সেরি 23

4
নং সালে এক বাস্তবায়ন পাইথন (CPython) এর, যে পরিবর্তনশীল একটি একটি পয়েন্টার PyObject। পাইপি বা জাইথনের মতো অন্যান্য বাস্তবায়নে এটি সত্য নয়। (প্রকৃতপক্ষে, এটি কীভাবে সত্য হতে পারে তা এমনকি পরিষ্কারও নয়, কারণ যেগুলি যে ভাষাগুলি প্রয়োগ করা হয় তাতে যে ভাষাগুলি রচিত হয়
সেগুলির

আমি মনে করি একটি ধারণাগত অর্থে "পয়েন্টার" এর ব্যবহার ঠিক আছে (সম্ভবত একটি দাবি অস্বীকারের সাথে বাস্তবায়নগুলি পরিবর্তিত হতে পারে), esp যদি লক্ষ্যটি আচরণের প্রকাশ করা হয়।
লেভন

@ বার্নার্ট যখন পাইথন বলে তখন তাদের অর্থ সিপিথন, অন্য কদাচিৎ ব্যবহৃত বাস্তবায়ন নয়। ঠিক তেমনি লোকেরা যখন ক্লিনেক্স বলে তখন তাদের মুখের টিস্যু বোঝায়। এই মন্তব্যে শব্দার্থবিজ্ঞানের খেলা খেলা সত্যই অপ্রয়োজনীয়। তিনি যা লিখেছেন, সে কি ভুল বর্ণনা করেছে তার আচরণ?
swade

10

id(name)দুটি নাম একই জিনিসকে উপস্থাপন করে কিনা তা পরীক্ষা করতে আপনি ব্যবহার করতে পারেন :

>>> a = b = c = [0, 3, 5]
>>> print(id(a), id(b), id(c))
46268488 46268488 46268488

তালিকাগুলি পরিবর্তনযোগ্য; এর অর্থ আপনি কোনও নতুন অবজেক্ট তৈরি না করে জায়গায় মানটি পরিবর্তন করতে পারবেন। তবে আপনি কীভাবে মানটি পরিবর্তন করবেন তার উপর এটি নির্ভর করে:

>>> a[0] = 1
>>> print(id(a), id(b), id(c))
46268488 46268488 46268488
>>> print(a, b, c)
[1, 3, 5] [1, 3, 5] [1, 3, 5]

আপনি যদি একটি নতুন তালিকা অর্পণ করেন a, তবে এর আইডি পরিবর্তন হবে, সুতরাং এটি প্রভাবিত করবে না bএবং cএর মানগুলি:

>>> a = [1, 8, 5]
>>> print(id(a), id(b), id(c))
139423880 46268488 46268488
>>> print(a, b, c)
[1, 8, 5] [1, 3, 5] [1, 3, 5]

পূর্ণসংখ্যা পরিবর্তনযোগ্য, সুতরাং আপনি একটি নতুন অবজেক্ট তৈরি না করে মান পরিবর্তন করতে পারবেন না:

>>> x = y = z = 1
>>> print(id(x), id(y), id(z))
507081216 507081216 507081216
>>> x = 2
>>> print(id(x), id(y), id(z))
507081248 507081216 507081216
>>> print(x, y, z)
2 1 1

1
idঅগত্যা একটি মেমরি অবস্থান নয়। যেমন ডকস বলেছেন, এটি "পরিচয়… একটি পূর্ণসংখ্যা ফেরত দেয় ... যা তার জীবদ্দশায় এই বিষয়টির জন্য অনন্য এবং ধ্রুবক হওয়ার গ্যারান্টিযুক্ত"। সিপিথন মেমরি ঠিকানাটি হিসাবে হিসাবে ব্যবহার করে id, তবে অন্যান্য পাইথন বাস্তবায়ন নাও করতে পারে। পিপিপি, উদাহরণস্বরূপ, না। এবং "দুটি ভার্স একই মেমোরি অবস্থানের দিকে নির্দেশ করে" বললে যে কেউ এটিকে সি-স্টাইল বোঝে তাকে বিভ্রান্ত করছে। "একই বস্তুর দুটি নাম" উভয়ই আরও সঠিক এবং কম বিভ্রান্তিকর।
২৮:১৮

@ বার্নার্ট স্পষ্টির জন্য ধন্যবাদ, আমি উত্তর আপডেট করেছি।
জুরগেরেজা

7

আপনার প্রথম উদাহরণে a = b = c = [1, 2, 3]আপনি সত্যিই বলছেন:

 'a' is the same as 'b', is the same as 'c' and they are all [1, 2, 3]

আপনি যদি 'a' সমান 1, 'b' সমান '2' এবং 'সি' এর সমান 3 সেট করতে চান তবে এটি চেষ্টা করুন:

a, b, c = [1, 2, 3]

print(a)
--> 1
print(b)
--> 2
print(c)
--> 3

আশাকরি এটা সাহায্য করবে!


4

সহজ কথায়, প্রথম ক্ষেত্রে, আপনি একটিতে একাধিক নাম বরাদ্দ করছেন list। কেবলমাত্র তালিকার একটি অনুলিপি মেমরিতে তৈরি হয় এবং সমস্ত নাম সেই অবস্থানটি উল্লেখ করে। সুতরাং যে কোনও নাম ব্যবহার করে তালিকা পরিবর্তন করা আসলে মেমরিতে তালিকাকে সংশোধন করবে।

দ্বিতীয় ক্ষেত্রে, একই মানের একাধিক অনুলিপি মেমরিতে তৈরি হয়। সুতরাং প্রতিটি অনুলিপি একে অপরের থেকে স্বতন্ত্র।


3

আপনার যা প্রয়োজন তা হ'ল:

a, b, c = [0,3,5] # Unpack the list, now a, b, and c are ints
a = 1             # `a` did equal 0, not [0,3,5]
print(a)
print(b)
print(c)

3

কোডটি যা আমার প্রয়োজন তা হ'ল এটি হতে পারে:

# test

aux=[[0 for n in range(3)] for i in range(4)]
print('aux:',aux)

# initialization

a,b,c,d=[[0 for n in range(3)] for i in range(4)]

# changing values

a[0]=1
d[2]=5
print('a:',a)
print('b:',b)
print('c:',c)
print('d:',d)

ফলাফল:

('aux:', [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]])
('a:', [1, 0, 0])
('b:', [0, 0, 0])
('c:', [0, 0, 0])
('d:', [0, 0, 5])
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.