সংক্ষিপ্ত উত্তরটি হল, পাইথন সর্বদা পাস-বাই-মান করে তবে প্রতিটি পাইথন ভেরিয়েবল আসলে কোনও কোনও বস্তুর পয়েন্টার হয়, তাই কখনও কখনও এটি পাস-বাই-রেফারেন্সের মতো দেখায়।
পাইথনে প্রতিটি বস্তু হয় হয় পরিবর্তনীয় বা অ-পরিবর্তনীয়। উদাহরণস্বরূপ, তালিকাগুলি, ডিক্টস, মডিউল এবং পান্ডাস ডেটা ফ্রেমগুলি পারস্পরিক পরিবর্তনযোগ্য এবং ইনটস, স্ট্রিং এবং টিপলগুলি অ-পরিবর্তনীয়। পরিবর্তনীয় অবজেক্টগুলি অভ্যন্তরীণভাবে পরিবর্তিত হতে পারে (উদাহরণস্বরূপ, তালিকায় একটি উপাদান যুক্ত করুন), তবে অ-পরিবর্তনীয় অবজেক্টগুলি পারে না।
আমি যেমন শুরুতে বলেছিলাম, আপনি প্রতিটি পাইথন ভেরিয়েবলকে কোনও বস্তুর পয়েন্টার হিসাবে ভাবতে পারেন। আপনি যখন কোনও ফাংশনে ভেরিয়েবলটি পাস করেন, ফাংশনের মধ্যে চলক (পয়েন্টার) হ'ল সর্বদা যে ভেরিয়েবলের (পয়েন্টার) পাশ করা হয়েছিল তার অনুলিপি থাকে So সুতরাং আপনি যদি অভ্যন্তরীণ ভেরিয়েবলকে নতুন কিছু নির্ধারণ করেন, আপনি যা করছেন তা সব পরিবর্তন করা হবে স্থানীয় ভেরিয়েবল একটি ভিন্ন বস্তুতে নির্দেশ করতে। এটি ভেরিয়েবলটি মূল বস্তুকে পরিবর্তিত করে (পরিবর্তিত করতে পারে না) বা এটি বাহ্যিক ভেরিয়েবলটিকে নতুন অবজেক্টে বিন্দু করে না। এই মুহুর্তে, বাহ্যিক ভেরিয়েবলটি এখনও মূল বস্তুকে নির্দেশ করে তবে অভ্যন্তরীণ ভেরিয়েবলটি একটি নতুন অবজেক্টের দিকে নির্দেশ করে points
যদি আপনি মূল অবজেক্টটি পরিবর্তন করতে চান (কেবলমাত্র পরিবর্তনযোগ্য ডেটা ধরণের সাহায্যে সম্ভব), আপনাকে এমন কিছু করতে হবে যা স্থানীয় ভেরিয়েবলকে সম্পূর্ণ নতুন মান নির্ধারণ না করেই বস্তুকে পরিবর্তন করে দেয়। এ কারণেই letgo()
এবং letgo3()
বাহ্যিক আইটেমটি আনল্যাটারড ছেড়ে দিন, তবে letgo2()
এটি পরিবর্তন করে।
যেমন @ উর্সান উল্লেখ করেছেন, letgo()
পরিবর্তে যদি এরকম কিছু ব্যবহার করা হয়, তবে এটি মূল অবজেক্টকে পরিবর্তিত করতে (পরিবর্তন করতে) df
বদলে দেবে যা বিশ্বব্যাপী a
ভেরিয়েবলের মাধ্যমে দেখা মানকে পরিবর্তিত করবে :
def letgo(df):
df.drop('b', axis=1, inplace=True)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo(a)
কিছু ক্ষেত্রে, আপনি আসল ভেরিয়েবলটি পুরোপুরি ফাঁকা করে সরাসরি নতুন অ্যাসাইনমেন্ট না করেই এটি নতুন ডেটা দিয়ে পুনরায় পূরণ করতে পারেন, উদাহরণস্বরূপ এটি সেই মূল বস্তুকে বদলে দেবে v
যা আপনি v
পরে ব্যবহার করার সময় দেখা ডাটা পরিবর্তন করবে :
def letgo3(x):
x[:] = np.array([[3,3],[3,3]])
v = np.empty((2, 2))
letgo3(v)
লক্ষ্য করুন যে আমি সরাসরি কিছু বরাদ্দ করছি না x
; আমি পুরো অভ্যন্তরীণ পরিসীমাতে কিছু বরাদ্দ করছি x
।
যদি আপনার অবশ্যই একেবারে নতুন একটি অবজেক্ট তৈরি করা উচিত এবং এটি বাহ্যিকভাবে দৃশ্যমান করা উচিত (যা কখনও কখনও প্যান্ডাসের ক্ষেত্রেও হয়) আপনার কাছে দুটি বিকল্প রয়েছে। 'ক্লিন' বিকল্পটি কেবলমাত্র নতুন অবজেক্টটি ফিরিয়ে আনতে হবে, যেমন,
def letgo(df):
df = df.drop('b',axis=1)
return df
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
a = letgo(a)
অন্য বিকল্পটি হ'ল আপনার ফাংশনের বাইরে পৌঁছানো এবং সরাসরি একটি বৈশ্বিক পরিবর্তনশীল পরিবর্তন করা। এটি a
একটি নতুন অবজেক্টের দিকে নির্দেশ করতে পরিবর্তিত হয় এবং যে কোনও ক্রিয়াকলাপ a
পরে উল্লেখ করা হয় সেই নতুন বস্তুটি দেখতে পাবে:
def letgo():
global a
a = a.drop('b',axis=1)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo()
সরাসরি গ্লোবাল ভেরিয়েবলগুলি পরিবর্তন করা সাধারণত একটি খারাপ ধারণা, কারণ যে কেউ আপনার কোডটি পড়ে তা কীভাবে a
পরিবর্তিত হয়েছে তা নির্ধারণ করতে বেশ সময় লাগবে । (আমি সাধারণত কোনও স্ক্রিপ্টে অনেকগুলি ফাংশন দ্বারা ব্যবহৃত ভাগ করা প্যারামিটারগুলির জন্য গ্লোবাল ভেরিয়েবলগুলি ব্যবহার করি, তবে আমি তাদের বিশ্বব্যাপী ভেরিয়েবলগুলি পরিবর্তন করতে দিই না))