পাইথনে দুটি ভেরিয়েবল অদলবদলের জন্য কি কোনও মানক পদ্ধতি আছে?


345

পাইথনে, আমি এই সিনট্যাক্সটি ব্যবহার করে দুটি পরিবর্তনশীল মান অদলবদল করতে দেখেছি:

left, right = right, left

এটি কি দুটি ভেরিয়েবলের মান অদলবদলের মানক উপায় হিসাবে বিবেচিত হয় বা দুটি অন্যান্য ভেরিয়েবল সাধারণত প্রচলিতভাবে কনভেনশন দ্বারা পরিবর্তিত হয় এমন কোনও অন্য উপায় রয়েছে?


1
@ এেকেম: এটি কেবলমাত্র নীচে আসে যে ক্রম-মূল্যায়নটি কোনও দ্বৈত / তালিকার অ্যাসাইনমেন্টের জন্য ভাষার দ্বারা নির্ধারিত হয়। পাইথন করে, বেশিরভাগ পুরানো ভাষা তা করে না।
smci

হার্মাম সি ++ এর অদলবদল রয়েছে (এ [আমি], একটি [কে]) পাইথনের জন্য আমাদের কেন এমন কিছু থাকতে পারে না।
নীল

উত্তর:


389

পাইথন বাম থেকে ডানে এক্সপ্রেশন মূল্যায়ণ করে। লক্ষ্য করুন যে কোনও অ্যাসাইনমেন্ট মূল্যায়ন করার সময়, ডান-হাতটি বাম-হাতের আগে মূল্যায়ন করা হয়।

http://docs.python.org/3/reference/expressions.html#evaluation-order

এর অর্থ এক্সপ্রেশনটির জন্য নিম্নলিখিত a,b = b,a:

  • ডান হাতের b,aমূল্যায়ন করা হয়, এর অর্থ স্মৃতিতে দুটি উপাদান তৈরি করা হয়। দুটি উপাদান হ'ল শনাক্তকারীদের দ্বারা নির্ধারিত অবজেক্টগুলি bএবং aযেগুলি প্রোগ্রামের সঞ্চালনের সময় নির্দেশটি হস্তান্তর করার আগে উপস্থিত ছিল
  • এই টিপল তৈরির ঠিক পরে, এই টিপল অবজেক্টটির কোনও অনুকরণ এখনও করা হয়নি, তবে এটি কোনও ব্যাপার নয়, পাইথন অভ্যন্তরীণভাবে এটি কোথায় আছে তা জানে
  • তারপরে, বাম-হাতের মূল্যায়ন করা হয়, অর্থাত্ ডুপালটি বাম-হাতের কাছে বরাদ্দ করা হয়
  • যেহেতু বাম-হাতটি দুটি শনাক্তকারীর সমন্বয়ে গঠিত, তাই টিপলটি আনপ্যাক করা হয়েছে যাতে প্রথম শনাক্তকারীটিকে aটিপলের প্রথম উপাদানটির জন্য বরাদ্দ করা হয় (যা সেই নাম যা স্ব্যাপের আগে ফর্মালি বি ছিল সেটির নাম ছিল b)
    এবং দ্বিতীয় আইডেন্টিফায়ার btuple দ্বিতীয় উপাদান নির্ধারিত হয় (যা বস্তু পূর্বে ছিল একটি swap 'র সামনে কারণ এটির শনাক্তকারী ছিল a)

এই প্রক্রিয়াটি কার্যকরভাবে শনাক্তকারীদের aএবং নিযুক্ত করা অবজেক্টগুলিকে সরিয়ে নিয়েছেb

সুতরাং, আপনার প্রশ্নের উত্তর দেওয়ার জন্য: হ্যাঁ, দুটি বস্তুর উপর দুটি শনাক্তকারীকে অদলবদল করার মানক উপায়।
যাইহোক, বস্তুগুলি ভেরিয়েবল নয়, তারা বস্তু।


1
আমি যতদূর বুঝতে পারি, এইভাবে দুটি ভেরিয়েবল অদল-বদল করা অতিরিক্ত মেমরি ব্যবহার করে না, কেবল 2 ভেরিয়েবলের জন্য কেবল মেমরি ব্যবহার করে, আমি ঠিক আছি?
ক্যাটবিল্টস

1
@ গেটবিল্টস টিউপলটি নির্মাণে কিছু অতিরিক্ত স্মৃতি গ্রহণ করা হবে (সম্ভবত সোয়াপটির 3-ভেরিয়েবল সংস্করণ বেশি লাগবে) তবে যেহেতু একমাত্র জিনিসগুলি অদলবদল করা হচ্ছে মেমরির ঠিকানা তাই এটি পরম্পরায় অতিরিক্ত মেমরির হবে না বোধ (সম্ভবত 24 অতিরিক্ত বাইট)।
ব্রিলিয়ান্ড

@ ব্রিলিয়ান্ড: কথা। আপনার কাছে এই বিষয়টির জন্য কোনও দলিল আছে? এটি বেশ আকর্ষণীয় এবং আমি আরও একটি পড়তে চাই। ধন্যবাদ।
ক্যাটবিল্টস

1
@ গুটিবিল্টস আমি নিশ্চিত নই, তবে সি ++ পয়েন্টার কীভাবে কাজ করে তা পড়তে সাহায্য করতে পারে। পাইথন আপনার জন্য স্বয়ংক্রিয়ভাবে জিনিসগুলি সর্বোত্তম উপায়ে করার চেষ্টা করে, সি ++ আসলে সমস্ত সম্ভাব্য সঠিক এবং ভুল উপায়ে কাজ করার জন্য সমস্ত অপশন দেয়, তাই পাইথন যে পদ্ধতির অসুবিধাগুলি গ্রহণ করে তার কী কী ত্রুটি রয়েছে তা শেখার জন্য এটি একটি ভাল সূচনা পয়েন্ট । এছাড়াও মনে রাখবেন যে একটি "-৪-বিট" অপারেটিং সিস্টেম থাকার অর্থ একটি মেমরি ঠিকানা সঞ্চয় করার জন্য b৪ বিট মেমরি লাগে - এটি আমার "24 বাইট" নম্বর পেয়েছে part
ব্রিল্যান্ড

দুর্দান্ত ব্যাখ্যা। কেবল যুক্ত করেই আপনি যে কোনও সংখ্যক "ভেরিয়েবল" পুনরায় সাজানোর জন্য এই পদ্ধতিটিও ব্যবহার করতে পারেন, যেমন a, b, c = c, a, b
alexlomba87


38

আমি ভেরিয়েবলগুলি অদলবদলের তিনটি উপায় জানি তবে a, b = b, aএটি সবচেয়ে সহজ। এখানে

এক্সওআর (পূর্ণসংখ্যার জন্য)

x = x ^ y
y = y ^ x
x = x ^ y

বা সংক্ষেপে,

x ^= y
y ^= x
x ^= y

অস্থায়ী পরিবর্তনশীল

w = x
x = y
y = w
del w

টুপল অদলবদল

x, y = y, x

1
সবচেয়ে সহজ এবং একমাত্র যা নিরবচ্ছিন্ন নয়।
জর্জি লিটাইও

17
এক্সওআর "ভেরিয়েবল" অদলবদল করে না। এটি পূর্ণসংখ্যার ভেরিয়েবলগুলি অদলবদল করে। (বা অন্য কয়েকটি ধরণের XOR অপারেটরকে যথাযথভাবে প্রয়োগ করছে) তদ্ব্যতীত, রোগালস্কির উত্তর অনুসারে, দ্বিপাক্ষিকের ক্ষেত্রে টুপল অদলবদল অনুকূলিত হয়েছে, এর বিরুদ্ধে আসলে কিছুই নেই। সংক্ষিপ্ত, পরিষ্কার এবং দ্রুত।
রোলার

এক্সওআর ইস্যুটি + - অপারেটরের ব্যবহার দ্বারা এড়ানো যেতে পারে তবে তবুও আমার কাছে সবচেয়ে ভাল লাগছে a, b = b, একটি codex = x + yy = xy x = xycode
অ্যাশিশ

22

আমি এটি বলব না যে এটি অদলবদলের একটি আদর্শ উপায় কারণ এটি কিছু অপ্রত্যাশিত ত্রুটি ঘটাবে।

nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]

nums[i]প্রথমে পরিবর্তন করা হবে এবং তারপরে দ্বিতীয় ভেরিয়েবলকে প্রভাবিত করবে nums[nums[i] - 1]


2
আপনার প্রায় কোনও প্রোগ্রামিং ল্যাঙ্গুয়েজে সমস্যা রয়েছে, এটি বি বা তদ্বিপরীত নির্ভর করে যদি অদলবদল (ক, খ) ব্যবহার করা নিরাপদ নয়। উদাহরণ হিসেবে বলা যায়, swap 'র (ক, খ) প্রসারিত হতে পারে: var c=a, a=b, b=c। এবং তারপরে, শেষ অ্যাসাইনমেন্ট aবি এর অ্যাড্রেস মূল্যায়নের জন্য নতুন মানটি ব্যবহার করবে ।
কাই পেটজকে

1
nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]। সমস্যা সমাধান করবে।
বিল চেং

1
এটি সমস্যার সমাধান করে, তবে কেন?
জ্যাকসন কেলি

2
@ জ্যাকসনকেলি ডান হাতের মূল্যায়ন নিরাপদ। ইন nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]: সমস্যাটি যখন পাইথন বাম-হাতের অ্যাসাইনমেন্টটি করে, nums[i]পরিবর্তিত হয়, যার ফলে nums[nums[i] - 1]অপ্রত্যাশিত পরিবর্তন ঘটে। আপনি প্রথমে কল্পনা করতে পারেন আপনি চান nums[1],nums[2] = nums[2],nums[1]তবে nums[1] = nums[2]রান করার পরে আপনি আর পাবেন না nums[2] = nums[1], পরিবর্তে আপনি পেয়েছেন nums[888] = nums[1]
গুও

5

বহুমাত্রিক অ্যারেগুলির জন্য কাজ করে না, কারণ এখানে উল্লেখগুলি ব্যবহৃত হয়।

import numpy as np

# swaps
data = np.random.random(2)
print(data)
data[0], data[1] = data[1], data[0]
print(data)

# does not swap
data = np.random.random((2, 2))
print(data)
data[0], data[1] = data[1], data[0]
print(data)

নম্পি অ্যারেগুলির স্ল্যাপগুলিও দেখুন


এটি প্রকৃতপক্ষে নাম্বার লাইব্রেরির একটি বিশেষ বৈশিষ্ট্য (বা বাগ)।
কাই পেটজকে

-1

আইকাম দ্বারা বর্ণিত সমস্যাগুলি ঘুরে দেখার জন্য , আপনি copyএকটি ফাংশনের মাধ্যমে মানগুলির একটি বিপরীতমুখী (বিপরীত) অনুলিপি ফিরিয়ে দিতে মডিউলটি ব্যবহার করতে পারেন :

from copy import copy

def swapper(x, y):
  return (copy(y), copy(x))

এক হিসাবে একই ফাংশন lambda:

swapper = lambda x, y: (copy(y), copy(x))

তারপরে, এগুলি পছন্দসই নামগুলিতে নিয়োগ করুন:

x, y = swapper(y, x)

দ্রষ্টব্য: আপনি চাইলে deepcopyপরিবর্তে আমদানি / ব্যবহার করতে পারতেন copy


আপনি অনুলিপি দ্বারা সমাধান করার চেষ্টা করছেন সমস্যা কি?
হানান শিটইনার্ট


1
তবে এটি কোনও সমস্যা বলে না, বাস্তবে তিনি বলেছেন "হ্যাঁ, এটি দুটি শনাক্তকারীকে অদলবদলের মানক উপায়"
হানান শ্টিংগার্ট

-2

আপনি টুপল এবং এক্সওআর সোয়াপগুলি একত্রিত করতে পারেন : x, y = x ^ x ^ y, x ^ y ^ y

x, y = 10, 20

print('Before swapping: x = %s, y = %s '%(x,y))

x, y = x ^ x ^ y, x ^ y ^ y

print('After swapping: x = %s, y = %s '%(x,y))

অথবা

x, y = 10, 20

print('Before swapping: x = %s, y = %s '%(x,y))

print('After swapping: x = %s, y = %s '%(x ^ x ^ y, x ^ y ^ y))

ল্যাম্বদা ব্যবহার :

x, y = 10, 20

print('Before swapping: x = %s, y = %s' % (x, y))

swapper = lambda x, y : ((x ^ x ^ y), (x ^ y ^ y))

print('After swapping: x = %s, y = %s ' % swapper(x, y))

আউটপুট:

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