রেফারেন্স দিয়ে আমি কীভাবে একটি ভেরিয়েবল পাস করব?


2627

পাইথন ডকুমেন্টেশন প্যারামিটারগুলি রেফারেন্স বা মান দ্বারা পাস হয়েছে কিনা সে সম্পর্কে অস্পষ্ট বলে মনে হচ্ছে এবং নিম্নলিখিত কোডটি অপরিবর্তিত মান 'মূল' উত্পাদন করে

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

আসল রেফারেন্স দ্বারা ভেরিয়েবলটি পাস করার জন্য আমি কি কিছু করতে পারি?


23
সংক্ষিপ্ত ব্যাখ্যা / স্পষ্টতার জন্য এই স্ট্যাকওভারফ্লো প্রশ্নের প্রথম উত্তরটি দেখুন । স্ট্রিং যেমন অপরিবর্তনীয়, সেগুলি পরিবর্তন করা হবে না এবং একটি নতুন ভেরিয়েবল তৈরি হবে, সুতরাং "বহিরাগত" ভেরিয়েবলটির এখনও একই মান রয়েছে।
ফিলস

10
ব্লেয়ারকনরডের উত্তরের কোডটি ভাল তবে ডেভিডকর্নাপিউ এবং ড্যারেন থমাস প্রদত্ত ব্যাখ্যাটি সঠিক।
ইথান ফুরম্যান

70
নির্বাচিত উত্তরটি পড়ার আগে, দয়া করে এই সংক্ষিপ্ত পাঠটি পড়ার বিষয়টি বিবেচনা করুন অন্য ভাষায় "ভেরিয়েবল" রয়েছে, পাইথনের "নাম" রয়েছে । "ভেরিয়েবল" এবং "রেফারেন্স" এর পরিবর্তে "নাম" এবং "অবজেক্ট" সম্পর্কে চিন্তা করুন এবং আপনার অনেক অনুরূপ সমস্যা এড়ানো উচিত।
lqc

24
কেন এটি অযথা ক্লাস ব্যবহার করে? এটি জাভা নয়: পি
পিটার আর

2
আরেকটি কাজের ভিত্তিটি হ'ল এর মতো একটি র‌্যাপার 'রেফারেন্স' তৈরি করা: রেফ = টাইপ ('', ()), {'এন': 1}) স্ট্যাকওভারফ্লো.com/
রবার্ট

উত্তর:


2830

যুক্তি অ্যাসাইনমেন্ট দ্বারা পাস হয় । এর পিছনে যুক্তি দ্বিগুণ:

  1. পাস হওয়া প্যারামিটারটি আসলে কোনও জিনিসের রেফারেন্স (তবে রেফারেন্সটি মান দ্বারা পাস হয়)
  2. কিছু ডেটা ধরণের পরিবর্তনীয়, তবে অন্যগুলি তা নয়

তাই:

  • আপনি যদি কোনও ব্যবস্থায় কোনও পরিবর্তনীয় অবজেক্টটি পাস করেন , পদ্ধতিটি একই জিনিসটির একটি রেফারেন্স পেয়েছে এবং আপনি এটি আপনার হৃদয়ের আনন্দের সাথে রূপান্তর করতে পারেন, তবে আপনি যদি পদ্ধতিতে রেফারেন্সটি পুনরায় প্রত্যাবর্তন করেন তবে বাইরের সুযোগটি এ সম্পর্কে কিছুই জানতে পারবে না এবং পরে আপনি শেষ করেছেন, বাহ্যিক রেফারেন্সটি এখনও মূল অবজেক্টটিকে নির্দেশ করবে।

  • আপনি যদি কোনও পদ্ধতির ক্ষেত্রে অপরিবর্তনীয় বস্তুটি পাস করেন তবে আপনি এখনও বাহ্যিক রেফারেন্সটি পুনর্নির্মাণ করতে পারবেন না এবং আপনি এই বস্তুটিকে পরিবর্তন করতে পারবেন না।

এটিকে আরও স্পষ্ট করার জন্য আসুন কয়েকটি উদাহরণ দেওয়া যাক।

তালিকা - একটি পরিবর্তনীয় প্রকার

একটি পদ্ধতিতে পাস করা তালিকাটি পরিবর্তনের চেষ্টা করা যাক:

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)

আউটপুট:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

যেহেতু প্যারামিটারটি পাশ করা হয়েছে এটি একটি outer_listঅনুলিপি নয়, একটি রেফারেন্স , তাই আমরা এটিকে পরিবর্তন করতে পরিবর্তনীয় তালিকার পদ্ধতিগুলি ব্যবহার করতে পারি এবং বাইরের স্কোপগুলিতে পরিবর্তনগুলি প্রতিবিম্বিত করতে পারি।

এখন আসুন দেখুন আমরা যখন প্যারামিটার হিসাবে পাস করা রেফারেন্সটি পরিবর্তন করার চেষ্টা করি তখন কী হয়:

def try_to_change_list_reference(the_list):
    print('got', the_list)
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'English']

print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)

আউটপুট:

before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']

যেহেতু the_listপ্যারামিটারটি মান দ্বারা উত্তীর্ণ হয়েছিল, সুতরাং এটির জন্য একটি নতুন তালিকা নির্ধারণের কোনও প্রভাব নেই যে পদ্ধতির বাইরের কোডটি দেখতে পেত। এটি the_listছিল outer_listরেফারেন্সের একটি অনুলিপি , এবং আমাদের the_listএকটি নতুন তালিকার outer_listদিকে ইঙ্গিত করা হয়েছিল, তবে যেখানে নির্দেশিত সেখানে পরিবর্তন করার কোনও উপায় ছিল না ।

স্ট্রিং - একটি অপরিবর্তনীয় প্রকার

এটি পরিবর্তনযোগ্য, তাই স্ট্রিংয়ের বিষয়বস্তু পরিবর্তন করতে আমরা কিছুই করতে পারি না

এখন, রেফারেন্স পরিবর্তন করার চেষ্টা করা যাক

def try_to_change_string_reference(the_string):
    print('got', the_string)
    the_string = 'In a kingdom by the sea'
    print('set to', the_string)

outer_string = 'It was many and many a year ago'

print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)

আউটপুট:

before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago

আবার, যেহেতু the_stringপ্যারামিটারটি মান দ্বারা পাস হয়ে গেছে, এটিতে একটি নতুন স্ট্রিং নির্ধারণের ফলে কোনও প্রভাব নেই যে পদ্ধতির বাইরের কোডটি দেখতে পেত। এটি the_stringছিল outer_stringরেফারেন্সের একটি অনুলিপি , এবং আমাদের the_stringএকটি নতুন স্ট্রিংয়ের outer_stringদিকে ইঙ্গিত করা হয়েছিল, তবে যেখানে নির্দেশিত সেখানে পরিবর্তন করার কোনও উপায় ছিল না ।

আমি আশা করি এটি কিছুটা পরিষ্কার হয়ে যায়।

সম্পাদনা: এটি লক্ষ্য করা গেছে যে @ ডেভিড মূলত জিজ্ঞাসা করা এই প্রশ্নের উত্তর দেয় না, "প্রকৃত উল্লেখ দ্বারা ভেরিয়েবলটি পাস করার জন্য আমি কি কিছু করতে পারি?" এর উপর কাজ করা যাক।

আমরা কিভাবে এই কাছাকাছি পেতে পারি?

@ অ্যান্ড্রিয়ার উত্তরগুলি দেখায় আপনি নতুন মানটি ফিরিয়ে দিতে পারবেন। এটি জিনিসগুলিতে যেভাবে প্রেরণ করা হবে তা পরিবর্তন করে না, তবে আপনি কী চান তা তথ্য ফিরে পেতে দেয়:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

আপনি যদি সত্যিই কোনও রিটার্ন মান ব্যবহার করা এড়াতে চান, আপনি নিজের মান ধরে রাখতে এবং এটি ফাংশনে পাস করতে বা তালিকার মতো একটি বিদ্যমান শ্রেণি ব্যবহার করতে পারেন:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

যদিও এটি কিছুটা জটিল বলে মনে হচ্ছে।


165
তারপরেও এটি সি তে থাকে, যখন আপনি "রেফারেন্সের মাধ্যমে" পাস করেন আপনি আসলে রেফারেন্সটি মান দিয়ে যাচ্ছেন ... "রেফারেন্স দ্বারা" সংজ্ঞায়িত করুন: পি
আন্ড্রেআ আম্বু

104
আমি নিশ্চিত নই যে আমি আপনার শর্তাদি বুঝতে পেরেছি। আমি কিছুক্ষণের জন্য সি গেমের বাইরে ছিলাম, কিন্তু যখন আমি এটিতে ছিলাম তখন কোনও "রেফারেন্স দ্বারা পাস" হত না - আপনি জিনিসগুলি পাস করতে পারেন, এবং এটি সর্বদা মূল্য দ্বারা পাস করা হত, সুতরাং প্যারামিটার তালিকায় যা কিছু ছিল অনুলিপি করা হয়েছিল তবে কখনও কখনও জিনিসটি একটি পয়েন্টার ছিল, যা মেমরির টুকরো (আদিম, অ্যারে, কাঠামো, যাই হোক না কেন) অনুসরণ করতে পারে তবে আপনি বাহ্যিক ক্ষেত্র থেকে অনুলিপি করা পয়েন্টারটি পরিবর্তন করতে পারবেন না - যখন আপনি ফাংশনটি দিয়েছিলেন , মূল পয়েন্টারটি এখনও একই ঠিকানার দিকে নির্দেশ করে। সি ++ প্রবর্তিত রেফারেন্সগুলি, যা ভিন্ন আচরণ করে।
ব্লেয়ার কনরাড

34
@ জ্যাক বোলিং আপনি যা বলছেন তা এই উত্তরটির সাথে বাস্তবিক অর্থে কীভাবে প্রাসঙ্গিক তা আমি সত্যিই পাই না। যদি কোনও পাইথন আগত ব্যক্তি রেফ / ভ্যাল দিয়ে যাওয়ার বিষয়ে জানতে চান, তবে এই উত্তরটি গ্রহণ করা উচিত: 1- আপনি কোনও ফাংশনটি তার আর্গুমেন্ট হিসাবে প্রাপ্ত রেফারেন্সটি ব্যবহার করতে পারেন, যতক্ষণ না কোনও ভেরিয়েবলের 'বাইরের' মানটি সংশোধন করতে পারেন যেহেতু আপনি কোনও নতুন অবজেক্টের জন্য প্যারামিটারটিকে পুনরায় সাইন করবেন না। 2- অপরিবর্তনীয় ধরণের ক্ষেত্রে নিযুক্ত করা সর্বদা একটি নতুন অবজেক্ট তৈরি করবে , যা আপনার বাইরের ভেরিয়েবলের রেফারেন্সটি ভেঙে দেয়।
ক্যাম জ্যাকসন

11
@ ক্যামজ্যাকসন, আপনার আরও ভাল উদাহরণ দরকার - সংখ্যাগুলি পাইথনের অপরিবর্তনীয় বস্তুও। তদুপরি, এ কথা কি সত্য নয় যে সমান বাম দিকে সাবস্ক্রিপশন ছাড়াই যে কোনও অ্যাসাইনমেন্ট নামটি নতুন অবজেক্টের কাছে পুনরায় অর্পণ করবে তা পরিবর্তনযোগ্য কিনা? কলারের দৃষ্টিকোণ থেকে তালিকার বিষয়বস্তুগুলি পরিবর্তন def Foo(alist): alist = [1,2,3]করবে না
মার্ক রান্সম

59
-1। দেখানো কোডটি ভাল, সম্পূর্ণ ভুল কীভাবে তা ব্যাখ্যা। কেন তা সঠিক ব্যাখ্যা করার জন্য ডেভিডকর্নপেই বা ড্যারেন থমাসের উত্তরগুলি দেখুন।
ইথান ফুরম্যান

685

পাইথনে ভেরিয়েবলগুলি কী তা নিয়ে ভুল বোঝাবুঝি থেকেই সমস্যাটি আসে। আপনি যদি বেশিরভাগ traditionalতিহ্যবাহী ভাষাগুলিতে অভ্যস্ত হন তবে নিম্নলিখিত ক্রমে কী ঘটে তার একটি মানসিক মডেল আপনার কাছে রয়েছে:

a = 1
a = 2

আপনি বিশ্বাস করেন যে aএটি একটি মেমরির অবস্থান যা মূল্য সঞ্চয় করে 1, তারপরে মানটি সংরক্ষণ করার জন্য আপডেট করা হয় 2। পাইথনে জিনিসগুলি এমনভাবে কাজ করে না। পরিবর্তে, aমান দিয়ে কোনও বস্তুর রেফারেন্স হিসাবে শুরু হয় 1, তারপরে মান সহ কোনও বস্তুর রেফারেন্স হিসাবে পুনরায় নিয়োগ দেওয়া হয় 2। এই দুটি অবজেক্টের সহাবস্থান থাকতে পারে যদিও aপ্রথমটির সাথে আর উল্লেখ করা হয়নি; প্রকৃতপক্ষে এগুলি প্রোগ্রামের মধ্যে অন্যান্য যে কোনও রেফারেন্স দ্বারা ভাগ করা যেতে পারে।

আপনি যখন কোনও প্যারামিটার দিয়ে কোনও ফাংশন কল করেন, তখন একটি নতুন রেফারেন্স তৈরি করা হয় যা এতে পাস করা অবজেক্টটিকে বোঝায় This এটি ফাংশন কলে ব্যবহৃত রেফারেন্স থেকে পৃথক, সুতরাং সেই রেফারেন্সটি আপডেট করার এবং এটিকে রেফারেন্স করার কোনও উপায় নেই there's নতুন বস্তু আপনার উদাহরণে:

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

def Change(self, var):
    var = 'Changed'

self.variableস্ট্রিং অবজেক্টের একটি রেফারেন্স 'Original'। আপনি যখন কল করবেন তখন অবজেক্টের জন্য Changeদ্বিতীয় রেফারেন্স তৈরি করুন var। ফাংশনের অভ্যন্তরে আপনি রেফারেন্সটিকে varআলাদা স্ট্রিং অবজেক্টে পুনরায় নিয়োগ করুন 'Changed', তবে রেফারেন্সটি self.variableপৃথক এবং পরিবর্তন হয় না।

এর চারপাশের একমাত্র উপায় হ'ল একটি পরিবর্তনীয় বস্তুটি পাস করা। যেহেতু উভয়ই রেফারেন্স একই অবজেক্টকে বোঝায়, বস্তুর যে কোনও পরিবর্তন উভয় জায়গায় প্রতিফলিত হয়েছে।

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'

106
ভাল সংক্ষিপ্ত বিবরণ। আপনার অনুচ্ছেদ "যখন আপনি কোনও ফাংশন ডাকবেন ..." আমি তার পরিবর্তে ক্রিপ্টিক বাক্যাংশটি শুনেছি এমন একটি সেরা ব্যাখ্যা যা 'পাইথন ফাংশন পরামিতিগুলি হল রেফারেন্স, মান দ্বারা পাস করা' ' আমি মনে করি আপনি যদি এই অনুচ্ছেদটি একা বুঝতে পারেন তবে অন্য সমস্ত ধরণের জিনিসটি বোধগম্য হয় এবং সেখান থেকে একটি যৌক্তিক উপসংহার হিসাবে প্রবাহিত হয়। তারপরে আপনাকে সচেতন হতে হবে আপনি কখন একটি নতুন অবজেক্ট তৈরি করছেন এবং যখন আপনি কোনও বিদ্যমানটিকে সংশোধন করছেন।
ক্যাম জ্যাকসন

3
তবে আপনি কীভাবে রেফারেন্সকে পুনরায় সাইন করতে পারেন? আমি ভেবেছিলাম আপনি 'ভার' এর ঠিকানা পরিবর্তন করতে পারবেন না তবে আপনার স্ট্রিং "বদলে গেছে" এখন 'ভার' মেমরি ঠিকানায় সংরক্ষণ করা হবে। আপনার বিবরণটিকে মনে হচ্ছে "পরিবর্তিত" এবং "আসল" পরিবর্তে মেমরির বিভিন্ন জায়গার সাথে সম্পর্কিত এবং আপনি কেবল 'var' কে অন্য কোনও ঠিকানায় স্যুইচ করেছেন। এটা কি ঠিক?
গ্লাসজায়েড

8
@ গ্লাসজায়েদ, আমি মনে করি আপনি এটি পেয়েছেন। "পরিবর্তিত" এবং "আসল" হ'ল দুটি মেমরি ঠিকানার দুটি পৃথক স্ট্রিং অবজেক্ট এবং এক থেকে অন্যকে নির্দেশিত করার জন্য 'ভার' পরিবর্তন।
মার্ক রান্সম

আইডি () ফাংশনটি ব্যবহার করা বিষয়গুলিকে স্পষ্ট করতে সহায়তা করে, কারণ পাইথন একটি নতুন অবজেক্ট তৈরি করার সময় এটি স্পষ্ট হয় (সুতরাং আমি মনে করি, যাইহোক)।
টিম রিচার্ডসন

1
সহজ শব্দগুলিতে @ মিনতট্রান, একটি রেফারেন্স এমন একটি জিনিস যা কোনও বস্তুকে "রেফার" করে। এর দৈহিক উপস্থাপনা সম্ভবত পয়েন্টার তবে এটি কেবল বাস্তবায়নের বিশদ। এটা সত্যিই হৃদয় একটি বিমূর্ত ধারণা।
মার্ক রান্সম

329

আমি অন্য উত্তরগুলি বরং দীর্ঘ এবং জটিল পেয়েছি, তাই পাইথন যেভাবে ভেরিয়েবল এবং পরামিতিগুলির আচরণ করে তা বোঝাতে আমি এই সাধারণ চিত্রটি তৈরি করেছি। এখানে চিত্র বর্ণনা লিখুন


2
সুদৃশ্য, সূক্ষ্ম পার্থক্যের স্পষ্ট করে তোলা সহজ করে তোলে যে একটি মধ্যবর্তী কার্য রয়েছে, নৈমিত্তিক দর্শকের কাছে স্পষ্ট নয়। +1
ব্যবহারকারী 22866 15

9
ক এ পরিবর্তনযোগ্য কিনা তা বিবেচ্য নয়। আপনি বি কে আলাদা কিছু বরাদ্দ দিলে এ পরিবর্তিত হয় না । যদি কোনও বস্তু পরিবর্তনযোগ্য হয় তবে আপনি অবশ্যই এটি পরিবর্তন করতে পারবেন sure তবে সরাসরি কোনও নামের সাথে অ্যাসাইনমেন্টের সাথে এর কোনও
যোগসূত্র নেই

1
@ মার্তিজান আপনি ঠিক বলেছেন আমি উত্তরের যে অংশটি পরিবর্তনটির উল্লেখ করেছি সেই অংশটি সরিয়েছি। আমি মনে করি না এটি এখন আরও সহজতর হতে পারে।
জেনাডিক্স

4
আপডেটের জন্য ধন্যবাদ, আরও ভাল! যা বেশিরভাগ লোককে বিভ্রান্ত করে তা হ'ল একটি সাবস্ক্রিপশনের দায়িত্ব; যেমন B[0] = 2, বনাম সরাসরি অ্যাসাইনমেন্ট B = 2,।
মার্টিজন পিটারস

11
"এ বি কে অর্পণ করা হয়েছে।" এটা কি অস্পষ্ট নয়? আমি সাধারণ ইংরেজীতে মনে করি যার অর্থ হয় A=Bবা হয় B=A
হাটসেপসুট

240

এটি পাস-বাই-মান বা পাস-বাই-রেফারেন্স নয় - এটি কল-বাই-অবজেক্ট। ফ্রেডরিক লুন্ডের এটি দেখুন:

http://effbot.org/zone/call-by-object.htm

এখানে একটি উল্লেখযোগ্য উদ্ধৃতি:

"... ভেরিয়েবল [নাম] বস্তু নয় ; এগুলি অন্য ভেরিয়েবল দ্বারা চিহ্নিত করা যায় না বা বস্তুর দ্বারা উল্লেখ করা যায় না।"

আপনার উদাহরণে, যখন Changeপদ্ধতিটি বলা হয় - এর জন্য একটি নেমস্পেস তৈরি করা হয়; এবং varএকটি নাম, স্ট্রিং বস্তুর জন্য হয়ে, যে নামস্থান মধ্যে 'Original'। সেই বস্তুর তখন দুটি নেমস্পেসে একটি নাম রয়েছে। এর পরে, একটি নতুন স্ট্রিং অবজেক্টের var = 'Changed'সাথে আবদ্ধ varহয় এবং এইভাবে পদ্ধতির নাম স্থানটি ভুলে যায় 'Original'। অবশেষে, সেই নেমস্পেসটি ভুলে গেছে এবং তার সাথে স্ট্রিংটিও 'Changed'রয়েছে।


21
আমি এটি কিনতে কঠিন মনে করি। আমার কাছে ঠিক জাভা হিসাবে, পরামিতিগুলি মেমরির বস্তুগুলিতে পয়েন্টার হয় এবং সেই পয়েন্টারগুলি স্ট্যাক বা রেজিস্টারগুলির মধ্য দিয়ে যায়।
লুকিয়ানো

10
এটি জাভা এর মতো নয়। এটি একরকম নয় এমন ক্ষেত্রে হ'ল অপরিবর্তনীয় বস্তু। তুচ্ছ ফাংশন ল্যাম্বদা x: x সম্পর্কে ভাবেন। এটি x = [1, 2, 3] এবং x = (1, 2, 3) এর জন্য প্রয়োগ করুন। প্রথম ক্ষেত্রে, প্রত্যাবর্তিত মানটি ইনপুটটির অনুলিপি এবং দ্বিতীয় ক্ষেত্রে অভিন্ন হবে।
ডেভিড কর্নিপাউ

26
না, এটি হুবহু জাভাস্ত্রিটির জন্য শব্দার্থবিদ্যার মতো। আমি নিশ্চিত না যে আপনি কী বোঝাতে চেয়েছেন "প্রথম ক্ষেত্রে, প্রত্যাবর্তিত মানটি ইনপুটটির অনুলিপি এবং দ্বিতীয় ক্ষেত্রে অভিন্ন হবে।" তবে এই বিবৃতিটি স্পষ্টতই ভুল বলে মনে হচ্ছে।
মাইক গ্রাহাম

23
এটি ঠিক জাভার মতোই। অবজেক্টের রেফারেন্সগুলি মান দ্বারা পাস হয়। যে কেউ পৃথকভাবে ভাবেন তাকে পাইথন কোডটি swapএমন একটি ফাংশনের জন্য সংযুক্ত করা উচিত যা দুটি রেফারেন্স অদলবদল করতে পারে, এর মতো: a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42]
cayhorstmann

24
আপনি জাভাতে বস্তুগুলি পাস করার সময় এটি জাভার মতোই। তবে জাভাতেও আদিম রয়েছে, যা আদিমের মান অনুলিপি করে পাস হয় passed সুতরাং তারা এই ক্ষেত্রে পৃথক।
ক্লাদিউ

174

রেফারেন্স / মান দ্বারা পরিবর্তে অ্যাসাইনমেন্ট দিয়ে স্টাফগুলি পাস করার কথা ভাবুন । এইভাবে, এটি সর্বদা স্পষ্ট, সাধারণ অ্যাসাইনমেন্টের সময় কী ঘটে তা আপনি যতক্ষণ বুঝতে পারবেন ততক্ষণে কী ঘটছে।

সুতরাং, একটি ফাংশন / পদ্ধতিতে একটি তালিকা পাস করার সময়, তালিকাটি প্যারামিটার নামের সাথে বরাদ্দ করা হয়। তালিকায় যোগ করার ফলে তালিকাকে সংশোধন করা হবে। ফাংশনের অভ্যন্তরে তালিকাটি পুনর্নির্দিষ্ট করা মূল তালিকা পরিবর্তন করবে না, যেহেতু:

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print a, b      # prints [1, 2, 3, 4] ['a', 'b']

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


3
প্রথম নজরে এই উত্তরটি আসল প্রশ্নের দিক থেকে আলাদা হয়ে গেছে বলে মনে হচ্ছে। দ্বিতীয় পাঠের পরে আমি বুঝতে পেরেছি যে এটি বিষয়টি বেশ স্পষ্ট করে তোলে। এই "নাম অ্যাসাইনমেন্ট" ধারণাটির একটি ভাল অনুসরণ এখানে পাওয়া যেতে পারে: কোডটি পাইথনিস্টার মতো: আইডিয়োমেটিক পাইথন
ক্রিশ্চান গ্রোলাউ

65

এফবট (ওরফে ফ্রেডরিক লুন্ড) পাইথনের ভেরিয়েবল পাসিং স্টাইলকে কল-বাই-অবজেক্ট হিসাবে বর্ণনা করেছে: http://effbot.org/zone/call-by-object.htm

বস্তুগুলি গাদাতে বরাদ্দ করা হয় এবং সেগুলিতে পয়েন্টারগুলি যে কোনও জায়গায়।

  • আপনি যখন কোনও অ্যাসাইনমেন্ট তৈরি করেন যেমন x = 1000, একটি অভিধান এন্ট্রি তৈরি করা হয় যা বর্তমান নামস্থানে "x" স্ট্রিংয়ের মানচিত্র দেয় যেখানে এক হাজারের সংখ্যার পূর্ণসংখ্য অবজেক্টটির পয়েন্টার থাকে।

  • আপনি যখন "x" এর সাথে আপডেট করেন x = 2000, একটি নতুন পূর্ণসংখ্যার অবজেক্ট তৈরি হয় এবং অভিধানটি নতুন অবজেক্টের দিকে নির্দেশ করার জন্য আপডেট করা হয়। পুরানো এক হাজার অবজেক্ট অপরিবর্তিত (এবং অন্য কিছু বস্তুকে বোঝায় কিনা তার উপর নির্ভর করে জীবিত থাকতে পারে বা নাও হতে পারে)।

  • আপনি যখন একটি নতুন অ্যাসাইনমেন্ট করেন যেমন y = x, একটি নতুন অভিধান এন্ট্রি "y" তৈরি হয় যা "x" এর জন্য এন্ট্রি হিসাবে একই বস্তুটিকে নির্দেশ করে।

  • স্ট্রিং এবং পূর্ণসংখ্যার মতো অবজেক্টগুলি অপরিবর্তনীয় । এর সহজ অর্থ হ'ল এমন কোনও পদ্ধতি নেই যা বস্তুটি তৈরির পরে তা পরিবর্তন করতে পারে। উদাহরণস্বরূপ, একবার পূর্ণসংখ্যার বস্তু এক-হাজার তৈরি হয়ে গেলে, এটি কখনই পরিবর্তিত হবে না। নতুন পূর্ণসংখ্যক বস্তু তৈরি করে গণিত করা হয়।

  • তালিকার মতো বিষয়গুলি পরিবর্তনযোগ্য । এর অর্থ হ'ল বস্তুর বিষয়বস্তু অবজেক্টের দিকে নির্দেশ করে যে কোনও কিছু দ্বারা পরিবর্তন করা যেতে পারে। উদাহরণস্বরূপ, x = []; y = x; x.append(10); print yমুদ্রণ করবে [10]। খালি তালিকা তৈরি করা হয়েছিল। "X" এবং "y" উভয়ই একই তালিকার দিকে নির্দেশ করে। পরিশেষে যোগ পদ্ধতি mutates (আপডেট) তালিকা বস্তু (একটি ডাটাবেস থেকে একটি রেকর্ড যোগ করা) এবং ফলাফল উভয় "X" এবং "Y" দৃশ্যমান (ঠিক একটি ডাটাবেস আপডেট হিসাবে ডাটাবেসের সাথে যে সংযোগ কাছে দৃশ্যমান হতে হবে)।

আশা করি এটি আপনার জন্য বিষয়টি স্পষ্ট করে।


2
আমি একজন বিকাশকারী এর কাছ থেকে এটি সম্পর্কে শেখার সত্যই প্রশংসা করি। id()পিআরপির উত্তর অনুসারে ফাংশনটি পয়েন্টারের (অবজেক্ট রেফারেন্সের) মানটি ফেরত দেওয়ার বিষয়টি সত্য ?
সৎ আবে

4
@ স্নেস্টেবে হ্যাঁ, সিপথনে আইডি () ঠিকানাটি ফিরিয়ে দেয়। পাইপাই এবং জাইথনের মতো অন্যান্য অজগরগুলিতে, আইডি () কেবল একটি অনন্য বস্তু শনাক্তকারী।
রেমন্ড হেটেঙ্গার

59

প্রযুক্তিগতভাবে, পাইথন সর্বদা রেফারেন্স মান দ্বারা পাস ব্যবহার করে । আমি আমার বক্তব্য সমর্থন করার জন্য আমার অন্যান্য উত্তর পুনরাবৃত্তি করতে যাচ্ছি ।

পাইথন সর্বদা পাস-বাই-রেফারেন্স মানগুলি ব্যবহার করে। কোন ব্যতিক্রম নেই। যে কোনও ভেরিয়েবল অ্যাসাইনমেন্টের অর্থ রেফারেন্স মানটি অনুলিপি করা। এর ব্যতিক্রম. যেকোন ভেরিয়েবল হল রেফারেন্স মানের সাথে আবদ্ধ নাম। সর্বদা.

আপনি লক্ষ্য বস্তুর ঠিকানা হিসাবে একটি রেফারেন্স মান সম্পর্কে ভাবতে পারেন। ঠিকানাটি ব্যবহার করার পরে স্বয়ংক্রিয়ভাবে বিবেচিত হয়। এইভাবে, রেফারেন্স মানটির সাথে কাজ করে মনে হচ্ছে আপনি লক্ষ্য অবজেক্টের সাথে সরাসরি কাজ করছেন। তবে এর মধ্যে সবসময় একটি রেফারেন্স থাকে, লক্ষ্যটিতে যাওয়ার জন্য আরও এক ধাপ step

এখানে উদাহরণ রয়েছে যা প্রমাণ করে যে পাইথন রেফারেন্স দিয়ে পাসিং ব্যবহার করে:

তর্কটি পাস করার সচিত্র উদাহরণ

যদি আর্গুমেন্টটি মান দ্বারা পাস করা হয় তবে বাহ্যিকটি lstপরিবর্তন করা যায় না। সবুজ লক্ষ্য বস্তু (কালো হল ভিতরে সঞ্চিত মান, লাল বস্তুর ধরণ), হলুদ হল অভ্যন্তরের রেফারেন্স মান সহ স্মৃতি - তীর হিসাবে আঁকা। নীল কঠিন তীর হল সেই রেফারেন্স মান যা ফাংশনে (ড্যাশযুক্ত নীল তীর পথের মাধ্যমে) পাস হয়েছিল। কুরুচিপূর্ণ গা yellow় হলুদ হল অভ্যন্তরীণ অভিধান। (এটি আসলে সবুজ উপবৃত্ত হিসাবেও আঁকতে পারে The রঙ এবং আকৃতি কেবল এটি অভ্যন্তরীণ বলে)

id()রেফারেন্স মানটি কী তা শিখতে আপনি অন্তর্নির্মিত ফাংশনটি ব্যবহার করতে পারেন (এটি হ'ল লক্ষ্য সামগ্রীর ঠিকানা)।

সংকলিত ভাষায়, একটি চলক একটি মেমরি স্পেস যা ধরণের মান ক্যাপচার করতে সক্ষম। পাইথনে, একটি ভেরিয়েবল এমন একটি নাম (একটি স্ট্রিং হিসাবে অভ্যন্তরীণভাবে ক্যাপচার করা হয়) যা রেফারেন্স ভেরিয়েবলের সাথে আবদ্ধ থাকে যা লক্ষ্য বস্তুর রেফারেন্স মানকে ধরে রাখে। ভেরিয়েবলের নামটি অভ্যন্তরীণ অভিধানের মূল কী, সেই অভিধান আইটেমটির মান অংশটি লক্ষ্যকে রেফারেন্স মান সংরক্ষণ করে।

রেফারেন্স মানগুলি পাইথনে লুকানো আছে। রেফারেন্স মানটি সংরক্ষণ করার জন্য কোনও সুস্পষ্ট ব্যবহারকারীর ধরণ নেই। যাইহোক, আপনি একটি তালিকা উপাদান (বা অন্য কোনও উপযুক্ত ধারক প্রকারের উপাদান) রেফারেন্স ভেরিয়েবল হিসাবে ব্যবহার করতে পারেন, কারণ সমস্ত পাত্রে উপাদানগুলিকে লক্ষ্য বস্তুর উল্লেখ হিসাবেও সংরক্ষণ করে store অন্য কথায়, উপাদানগুলি ধারকটির ভিতরে আসলে থাকে না - কেবলমাত্র উপাদানের উল্লেখগুলি ferences


1
প্রকৃতপক্ষে এটি রেফারেন্স মান দ্বারা এটি পাস নিশ্চিত করা হয়। এই উত্তরের জন্য +1 যদিও উদাহরণটি ভাল ছিল না।
বাগশটজিজি

30
নতুন পরিভাষা উদ্ভাবন করা (যেমন "রেফারেন্স মান দ্বারা পাস" বা "অবজেক্ট দ্বারা কল" সহায়ক নয়)। "কল দ্বারা (মান | রেফারেন্স | নাম)" মানক পদ। "রেফারেন্স" একটি স্ট্যান্ডার্ড শব্দ। মান অনুসারে রেফারেন্সগুলি পাঠানো স্ট্যান্ডার্ড পরিভাষা ব্যবহার করে পাইথন, জাভা এবং অন্যান্য ভাষার একটি হোস্টের আচরণের সঠিকভাবে বর্ণনা করে।
cayhorstmann

4
@ কেহর্স্টম্যান: সমস্যাটি হ'ল পাইথন ভেরিয়েবলের অন্য ভাষার মতো শব্দটির অর্থ নেই। এইভাবে, রেফারেন্স দ্বারা কল এখানে ভাল মানায় না। এছাড়াও, আপনি সঠিকভাবে রেফারেন্সটি কীভাবে সংজ্ঞায়িত করবেন ? অনানুষ্ঠানিকভাবে পাইথন পথটিকে সহজেই অবজেক্টের ঠিকানাটি পাস করার মতো বর্ণনা করা যেতে পারে। তবে পাইথনের সম্ভাব্য বিতরণিত প্রয়োগের সাথে এটি খাপ খায় না।
পিআরপি

1
আমি এই উত্তরটি পছন্দ করি তবে আপনি যদি বিবেচনা করতে পারেন যে উদাহরণটি সত্যিই প্রবাহকে সহায়তা করছে বা আঘাত করছে। এছাড়াও, আপনি যদি 'অবজেক্ট রেফারেন্স' দিয়ে 'রেফারেন্স মান' প্রতিস্থাপন করেন তবে আপনি এখানে পরিভাষা হিসাবে 'অফিসিয়াল' বিবেচনা করতে পারতেন এমন শব্দের ব্যবহার করতে হবে: কার্যকারিতা সংজ্ঞায়িত করা
সর্বাধিক আবে

2
সেই উদ্ধৃতিটির শেষে একটি পাদটীকা নির্দেশিত রয়েছে, যা লেখা আছে: "আসলে, অবজেক্ট রেফারেন্সের মাধ্যমে কল করা আরও ভাল বিবরণ হতে পারে, যেহেতু কোনও পরিবর্তনীয় বস্তুটি পাস করা হয়, কলার দেখবে কলি এতে কোনও পরিবর্তন আনবে ... " আমি আপনার সাথে একমত যে অন্য ভাষার সাথে প্রতিষ্ঠিত টার্মিনোলজির মাপসই করার চেষ্টা করে বিভ্রান্তি ঘটে। শব্দার্থবিজ্ঞানের কথা বাদ দিয়ে, যে জিনিসগুলি বোঝার দরকার তা হ'ল: অভিধান / নামস্থান, নাম বাঁধাই ক্রিয়াকলাপ এবং নাম → পয়েন্টার → অবজেক্টের সম্পর্ক (যেমন আপনি ইতিমধ্যে জানেন)।
সৎ আবে

56

পাইথনে কোনও ভেরিয়েবল নেই

প্যারামিটার পাসিং বোঝার মূল চাবিকাঠি হল "ভেরিয়েবল" সম্পর্কে চিন্তাভাবনা বন্ধ করা। পাইথনে নাম এবং বস্তু রয়েছে এবং একসাথে এগুলি ভেরিয়েবলগুলির মতো প্রদর্শিত হয় তবে তিনটি পার্থক্য করা সর্বদা কার্যকর।

  1. পাইথনের নাম এবং বস্তু রয়েছে।
  2. অ্যাসাইনমেন্ট একটি বস্তুর সাথে একটি নাম আবদ্ধ করে।
  3. কোনও ফাংশনে আর্গুমেন্ট পাস করা কোনও বস্তুর সাথে একটি নাম (ফাংশনের প্যারামিটার নাম )ও আবদ্ধ করে।

এটাই তো আছে। মিউটিবিলিটি এই প্রশ্নের সাথে অপ্রাসঙ্গিক।

উদাহরণ:

a = 1

এটি নামটি aটাইপ পূর্ণসংখ্যার একটি বস্তুর সাথে বেঁধে রাখে যা মান 1 রাখে।

b = x

এটি নামটিকে bএকই বস্তুর সাথে আবদ্ধ করে যে নামটি xবর্তমানে আবদ্ধ। এরপরে নামটির bআর কোনও সম্পর্ক xনেই।

পাইথন 3 ভাষা রেফারেন্সে বিভাগ 3.1 এবং 4.2 দেখুন ।

প্রশ্নে উদাহরণটি কীভাবে পড়বেন

প্রশ্নে দেখানো কোডটি সালে বিবৃতি self.Change(self.variable)নাম binds var(ফাংশনের সুযোগ Change) বস্তু যে মান ঝুলিতে করার 'Original'এবং নিয়োগ var = 'Changed'(ফাংশনের শরীরে Changeকিছু অন্যান্য বস্তু (যে ঘটবে:) নির্ধারণ আবার একই নামের স্ট্রিং ধরে রাখার জন্য তবে সম্পূর্ণ অন্য কিছু হতে পারে)।

রেফারেন্স দিয়ে কীভাবে পাস করবেন

সুতরাং আপনি যে জিনিসটি পরিবর্তন করতে চান তা যদি কোনও মিউটেটেবল অবজেক্ট হয় তবে কোনও সমস্যা নেই, কারণ সবকিছু কার্যকরভাবে রেফারেন্সের মাধ্যমে পাস করা হয়েছে।

যদি এটি একটি অপরিবর্তনীয় অবজেক্ট (যেমন একটি বুল, সংখ্যা, স্ট্রিং) হয়, যাওয়ার উপায় হ'ল এটিকে কোনও পরিবর্তনীয় অবজেক্টে গুটিয়ে রাখা।
এর দ্রুত এবং নোংরা সমাধানটি হ'ল এক-উপাদানগুলির তালিকা (পরিবর্তে self.variable, পাস [self.variable]এবং ফাংশন সংশোধন করুন var[0])।
আরও অজগর দৃষ্টিভঙ্গি হবে একটি তুচ্ছ, এক-গুণযুক্ত শ্রেণি প্রবর্তন করা। ফাংশনটি ক্লাসের একটি উদাহরণ গ্রহণ করে এবং বৈশিষ্ট্যটি পরিচালনা করে।


20
"পাইথনের কোনও পরিবর্তনশীল নেই" একটি নির্বোধ এবং বিভ্রান্তিকর স্লোগান, এবং আমি সত্যিই আশা করি লোকেরা এটি বলা বন্ধ করে দেয় ... :( এই উত্তরটির বাকি অংশটি ভাল!
নেড ব্যাচেল্ডার

9
এটি মর্মান্তিক হতে পারে তবে এটি মূর্খ নয়। এবং আমি এটি বিভ্রান্তিকর বলে মনে করি না: এটি প্রত্যাশিত যে ব্যাখ্যাটি আসছে তার জন্য প্রাপকের মন উন্মুক্ত করে এবং তাকে একটি দরকারী "ভেরিয়েবলের পরিবর্তে তাদের কী আছে" ভেবে দেখি in (হ্যাঁ, আপনার মাইলেজটি পৃথক হতে পারে))
লুটজ প্রিচেল্ট

13
আপনি কি আরও বলবেন যে জাভাস্ক্রিপ্টের কোনও ভেরিয়েবল নেই? তারা পাইথনের মতোই কাজ করে। এছাড়াও, জাভা, রুবি, পিএইচপি, .... আমার মনে হয় আরও ভাল শিক্ষণ কৌশল হ'ল "পাইথনের ভেরিয়েবলগুলি সি এর চেয়ে আলাদাভাবে কাজ করে।"
নেড ব্যাচেল্ডার

9
হ্যাঁ, জাভাতে ভেরিয়েবল রয়েছে। পাইথন, এবং জাভাস্ক্রিপ্ট, রুবি, পিএইচপি ইত্যাদি। আপনি জাভাতে বলবেন না যা intভেরিয়েবল ঘোষণা করে, তবে Integerতা করে না। তারা উভয়ই ভেরিয়েবল ঘোষণা করে। Integerপরিবর্তনশীল, একটি অবজেক্ট intপরিবর্তনশীল একটি আদিম হয়। উদাহরণ হিসাবে, আপনি দেখিয়েছেন যে আপনার ভেরিয়েবলগুলি কীভাবে কাজ করে a = 1; b = a; a++ # doesn't modify b। পাইথনের ক্ষেত্রেও এটি সত্য ( += 1যেহেতু ++পাইথন নেই) ব্যবহার করে!
নেড ব্যাচেল্ডার

1
"ভেরিয়েবল" ধারণাটি জটিল এবং প্রায়শই অস্পষ্ট: একটি পরিবর্তনশীল একটি মানের জন্য একটি ধারক, নাম দ্বারা চিহ্নিত। পাইথনে, মানগুলি বস্তু, পাত্রে বস্তু হয় (সমস্যাটি দেখুন?) এবং নামগুলি আসলে পৃথক জিনিস things আমি বিশ্বাস করি যে এই পদ্ধতিতে ভেরিয়েবলগুলির সঠিক বোঝাপড়া পাওয়া আরও কঠিন । নাম-ও-অবজেক্টের ব্যাখ্যা আরও কঠিন বলে মনে হয়, তবে এটি আসলে সহজ।
লুটজ প্রেশেল্ট

43

একটি সাধারণ কৌশল যা আমি সাধারণত ব্যবহার করি তা হ'ল এটি কেবল একটি তালিকায় মোড়ানো:

def Change(self, var):
    var[0] = 'Changed'

variable = ['Original']
self.Change(variable)      
print variable[0]

(হ্যাঁ আমি জানি এটি অসুবিধেয় হতে পারে তবে কখনও কখনও এটি করা সহজ।


7
পাইথনকে পাস-বাই-রেফারেন্স না দেওয়ার সমস্যাটিকে সামান্য পরিমাণে পাঠ্য দেওয়ার জন্য +1। (এই পৃষ্ঠার যে কোনও স্থানে যেমন এখানে ও যথাযথভাবে মাপসই করা মন্তব্য / প্রশ্নের ফলো-অন হিসাবে: পাইথন কেন সি # এর মতো "রেফ" কীওয়ার্ডটি সরবরাহ করতে পারে না তা আমার কাছে স্পষ্ট নয়, যা কলারের যুক্তিটিকে কেবল একটি তালিকায় মোড় দেয়) এটি, এবং তালিকার 0 তম উপাদান হিসাবে ফাংশনটির মধ্যে যুক্তির রেফারেন্সগুলি বিবেচনা করুন))
এম ক্যাটজ

5
খুশী হলাম। রেফ দিয়ে যেতে, [] এর মধ্যে মোড়ানো।
জাস্টাস

38

(সম্পাদনা করুন - ব্লেয়ার তার প্রচুর জনপ্রিয় উত্তর আপডেট করেছেন যাতে এটি এখন সঠিক)

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

ডেভিড কর্নিপাউয়ের উত্তরটি আসল উত্তরের দিকে ইঙ্গিত করে এবং ব্যাখ্যা করে যে ব্লেয়ার কনরাডের পোস্টে আচরণগুলি সংজ্ঞা হিসাবে না হলেও কেন সঠিক বলে মনে হচ্ছে।

পাইথন যতটা মান দিয়ে পাস হয়, সমস্ত ভাষা মান অনুসারে পাস হয় যেহেতু কিছু অংশের ডেটা (এটি একটি "মান" বা "রেফারেন্স" হতে হবে) পাঠাতে হবে। যাইহোক, এর অর্থ এই নয় যে পাইথনটি কোনও সি প্রোগ্রামার দ্বারা এটি বিবেচনা করবে এমন অর্থে মান দ্বারা পাস হয়।

আপনি যদি আচরণটি চান, ব্লেয়ার কনরাদের উত্তরটি ভাল। তবে আপনি যদি পাইথনকে কেন মান দ্বারা পাস করেন না বা রেফারেন্সের মাধ্যমে পাস করেন না তার বাদ্যগুলি এবং বোল্টগুলি জানতে চাইলে ডেভিড কর্নিপউয়ের উত্তরটি পড়ুন।


4
এটি কেবল সত্য নয় যে সমস্ত ভাষা মান অনুসারে কল করে। সি ++ বা পাসকালে (এবং অবশ্যই আরও অনেকে যা আমি জানি না), আপনি রেফারেন্স দিয়ে কল করেছেন। উদাহরণস্বরূপ, সি ++ এ, void swap(int& x, int& y) { int temp = x; x = y; y = temp; }এতে ভেরিয়েবলগুলি অদলবদল করবে। পাস্কলে, আপনি এর varপরিবর্তে ব্যবহার করুন &
cayhorstmann

2
আমি ভেবেছিলাম আমি এর জবাব অনেক আগে দিয়েছি কিন্তু আমি এটি দেখতে পাচ্ছি না। সম্পূর্ণতার জন্য - cayhorstmann আমার উত্তর ভুল বুঝে। আমি বলছিলাম না যে সমস্ত কিছু প্রথমে সি / সি ++ সংক্রান্ত শিখতে হবে সেই শর্তে মান অনুসারে কল । এটি কেবলমাত্র কিছু মান পাস করা হয়েছিল (মান, নাম, পয়েন্টার, ইত্যাদি) এবং ব্লেয়ারের মূল উত্তরে ব্যবহৃত শর্তগুলি সঠিক ছিল না।
কোবেজহান

24

আপনি এখানে কিছু সত্যিই ভাল উত্তর পেয়েছি।

x = [ 2, 4, 4, 5, 5 ]
print x  # 2, 4, 4, 5, 5

def go( li ) :
  li = [ 5, 6, 7, 8 ]  # re-assigning what li POINTS TO, does not
  # change the value of the ORIGINAL variable x

go( x ) 
print x  # 2, 4, 4, 5, 5  [ STILL! ]


raw_input( 'press any key to continue' )

2
হ্যাঁ, তবে আপনি যদি x = [2, 4, 4, 5, 5], y = x, এক্স [0] = 1, প্রিন্ট এক্স # [1, 4, 4, 5, 5] y # [1 , 4, 4, 5, 5]
লেটকেট

19

varএক্ষেত্রে পদ্ধতিতে শিরোনামযুক্ত চলকটি Changeএকটি রেফারেন্স বরাদ্দ করা হয় self.variable, এবং আপনি তত্ক্ষণাত একটি স্ট্রিং নিযুক্ত করেন var। এটি আর ইশারা করে না self.variable। নিম্নলিখিত কোড স্নিপেট দেখায় যে আপনি যদি ডেটা কাঠামোটি নির্দেশ করে varএবং self.variableএই ক্ষেত্রে একটি তালিকা পরিবর্তন করেন তবে কী হবে would

>>> class PassByReference:
...     def __init__(self):
...         self.variable = ['Original']
...         self.change(self.variable)
...         print self.variable
...         
...     def change(self, var):
...         var.append('Changed')
... 
>>> q = PassByReference()
['Original', 'Changed']
>>> 

আমি নিশ্চিত যে অন্য কেউ এটি আরও পরিষ্কার করে বলতে পারে।


18

পাইথনের পাস-বাই-অ্যাসাইনমেন্ট স্কিমটি সি ++ এর রেফারেন্স প্যারামিটার বিকল্পগুলির মতো একদম একই নয় তবে বাস্তবে এটি সি ভাষার (এবং অন্যদের) যুক্তি-পাসিং মডেলের সাথে খুব মিল বলে প্রমাণিত হয়েছে:

  • অপরিবর্তনীয় যুক্তি কার্যকরভাবে " মান দ্বারা " পাস করা হয় । পূর্ণসংখ্যা এবং স্ট্রিংয়ের মতো অবজেক্টগুলি অনুলিপি করার পরিবর্তে অবজেক্ট রেফারেন্স দ্বারা পাস করা হয়, তবে আপনি কোনও স্থানে অপরিবর্তনীয় বস্তু পরিবর্তন করতে পারবেন না, ফলে প্রভাবটি অনুলিপি করার মতো is
  • পরিবর্তনীয় যুক্তি কার্যকরভাবে " পয়েন্টার দ্বারা " পাস করা হয় । তালিকাগুলি এবং অভিধানের মতো বস্তুগুলিও অবজেক্ট রেফারেন্স দ্বারা পাস হয়, যা সি পয়েন্টার হিসাবে অ্যারে পাস করার অনুরূপ — ফাংশনটিতে পরিবর্তিত বস্তু পরিবর্তিত হতে পারে অনেকটা সি অ্যারের মতো।

16

আপনি যেমনটি বলতে পারেন যে আপনাকে একটি পরিবর্তনীয় অবজেক্ট থাকা দরকার, তবে আমাকে আপনাকে বিশ্বব্যাপী ভেরিয়েবলগুলি পরীক্ষা করে দেখার পরামর্শ দিন কারণ তারা আপনাকে সহায়তা করতে পারে এমনকি এই ধরণের সমস্যা সমাধান করতে পারে!

http://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

উদাহরণ:

>>> def x(y):
...     global z
...     z = y
...

>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined

>>> x(2)
>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
2

5
আমি অনুরূপ প্রতিক্রিয়া পোস্ট করার জন্য প্রলুব্ধ হয়েছিলাম - মূল প্রশ্নকর্তা হয়ত জানেন না যে তিনি যা চেয়েছিলেন তা আসলে একটি বৈশ্বিক পরিবর্তনশীল, ফাংশনগুলির মধ্যে ভাগ করে নেওয়ার জন্য ছিল। এখানে লিংক আমি ভাগ যেত আছে: stackoverflow.com/questions/423379/... @Tim যেই সব উত্তর, স্ট্যাক ওভারফ্লো না শুধুমাত্র একটি প্রশ্ন ও উত্তর সাইট, এটা রেফারেন্স জ্ঞান যে শুধুমাত্র শক্তিশালী এবং আরো nuanced- অনেক পায় সুবিশাল সংগ্রহস্থলের হয় একটি সক্রিয় উইকির মতো- আরও ইনপুট সহ।
ম্যাক্স পি ম্যাজি

13

উত্তরের এখানে অন্তর্দৃষ্টি অনেক, তবে আমি মনে করি যে এখানে একটি অতিরিক্ত পয়েন্ট সুস্পষ্টভাবে উল্লেখ করা হয়নি। পাইথন ডকুমেন্টেশন থেকে উদ্ধৃতি https://docs.python.org/2/faq/programming.html# কি-are-the-rules-for-local-and-global-variables-in-python

"পাইথনে, কোনও ফাংশনের অভ্যন্তরে কেবলমাত্র উল্লেখযোগ্য ভেরিয়েবলগুলি স্পষ্টতই গ্লোবাল হয় function যদি কোনও ভেরিয়েবলটি ফাংশনের শরীরে যে কোনও জায়গায় নতুন মান নির্ধারিত হয় তবে এটি স্থানীয় হিসাবে ধরে নেওয়া হয় If যদি কোনও ভেরিয়েবলটি ফাংশনের অভ্যন্তরে কোনও নতুন মান বরাদ্দ করা হয়, ভেরিয়েবল সুস্পষ্টভাবে স্থানীয়, এবং আপনাকে এটি পরিষ্কারভাবে 'গ্লোবাল' হিসাবে ঘোষণা করতে হবে। প্রথমে কিছুটা আশ্চর্য হলেও এক মুহুর্তের বিবেচনা এটি ব্যাখ্যা করে one একদিকে, নির্ধারিত ভেরিয়েবলগুলির জন্য গ্লোবাল প্রয়োজনীয়তা অনিচ্ছাকৃত পার্শ্ব প্রতিক্রিয়াগুলির বিরুদ্ধে একটি বার সরবরাহ করে On অন্যদিকে, সমস্ত বৈশ্বিক রেফারেন্সের জন্য যদি বিশ্বব্যাপী প্রয়োজন হত, আপনি সর্বদা বিশ্বব্যাপী ব্যবহার করতেন You আপনাকে কোনও বিল্ট-ইন ফাংশন বা আমদানি করা মডিউলের কোনও উপাদানকে প্রতিটি রেফারেন্স হিসাবে বৈশ্বিক হিসাবে ঘোষণা করতে হবে This পার্শ্ব প্রতিক্রিয়া সনাক্তকরণের জন্য বিশ্বব্যাপী ঘোষণার কার্যকারিতাটিকে পরাস্ত করবে ""

এমনকি কোনও ফাংশনে কোনও পরিবর্তনীয় অবজেক্টটি পাস করার পরেও এটি প্রযোজ্য। এবং আমার কাছে ফাংশনটিতে অবজেক্টকে অর্পণ এবং অপারেটিংয়ের মধ্যে আচরণের পার্থক্যের কারণ স্পষ্টভাবে ব্যাখ্যা করে।

def test(l):
    print "Received", l , id(l)
    l = [0, 0, 0]
    print "Changed to", l, id(l)  # New local object created, breaking link to global l

l= [1,2,3]
print "Original", l, id(l)
test(l)
print "After", l, id(l)

দেয়:

Original [1, 2, 3] 4454645632
Received [1, 2, 3] 4454645632
Changed to [0, 0, 0] 4474591928
After [1, 2, 3] 4454645632

গ্লোবাল ভেরিয়েবলের অ্যাসাইনমেন্ট যা গ্লোবাল হিসাবে ঘোষিত হয় না তাই একটি নতুন স্থানীয় অবজেক্ট তৈরি করে এবং মূল বস্তুর লিঙ্কটি ভেঙে দেয়।


10

pass by objectপাইথনে ব্যবহৃত ধারণার সহজ (আমি আশা করি) ব্যাখ্যা এখানে ।
আপনি যখনই কোনও ফাংশনে কোনও বস্তুটি পাস করেন, তখন অবজেক্টটি নিজেই পাস হয়ে যায় (পাইথনের বস্তুটি আসলে আপনি অন্য প্রোগ্রামিং ভাষায় একটি মান বলতে চান) এই বস্তুর রেফারেন্স নয়। অন্য কথায়, আপনি যখন ফোন করবেন:

def change_me(list):
   list = [1, 2, 3]

my_list = [0, 1]
change_me(my_list)

আসল অবজেক্ট - [0, 1] (যা অন্যান্য প্রোগ্রামিং ভাষায় একটি মান হিসাবে পরিচিত হবে) পাস হচ্ছে। সুতরাং আসলে ফাংশনটি change_meএমন কিছু করার চেষ্টা করবে:

[0, 1] = [1, 2, 3]

যা স্পষ্টতই ফাংশনে পাস করা বস্তুটি পরিবর্তন করবে না। যদি ফাংশনটি দেখতে এমন হয়:

def change_me(list):
   list.append(2)

তারপরে কলটির ফলাফল হবে:

[0, 1].append(2)

যা স্পষ্টতই বিষয়টিকে পরিবর্তন করবে। এই উত্তরটি এটি ভালভাবে ব্যাখ্যা করে।


2
সমস্যাটি হ'ল অ্যাসাইনমেন্টটি আপনার প্রত্যাশা ব্যতীত অন্য কিছু করে। list = [1, 2, 3]কারণ পুনঃব্যবহার listঅন্য কিছু নাম এবং মূলত পাস বস্তুর forgeting। যাইহোক, আপনি চেষ্টা করে দেখতে পারেন list[:] = [1, 2, 3](প্রণালী দ্বারা listএকটি পরিবর্তনশীল জন্য ভুল নাম সম্পর্কে চিন্তা করছেন। [0, 1] = [1, 2, 3]সম্পূর্ণ অর্থহীন বিষয় যাই হোক, তুমি কি বুঝাইতে চাও মনে করি না। বস্তুর নিজেই পাস করা হয়েছে কি আপনার মতে ফাংশন অনুলিপি করা হয়েছে?
pepr

@ পেপার অবজেক্টগুলি আক্ষরিক নয়। তারা বস্তু। তাদের সম্পর্কে কথা বলার একমাত্র উপায় হ'ল তাদের কিছু নাম। এ কারণেই আপনি এটি উপলব্ধি করা এত সহজ, তবে ব্যাখ্যা করা অত্যন্ত জটিল। :-)
ভেকি

@ ভেকি: আমি সে সম্পর্কে অবহিত। যাইহোক, তালিকা আক্ষরিক তালিকা অবজেক্টে রূপান্তরিত হয়। প্রকৃতপক্ষে পাইথনের যে কোনও বস্তুর নাম ছাড়াই অস্তিত্ব থাকতে পারে এবং কোনও নাম না দেওয়া হলেও এটি ব্যবহার করা যেতে পারে। এবং আপনি তাদের বেনামে থাকা জিনিসগুলি সম্পর্কে ভাবতে পারেন। তালিকার উপাদান হিসাবে বস্তুগুলি সম্পর্কে ভাবুন। তাদের নাম দরকার নেই। আপনি তালিকাটি তালিকাবদ্ধ করে বা পুনরাবৃত্তির মাধ্যমে এগুলি অ্যাক্সেস করতে পারেন। যাইহোক, আমি জোর দিয়েছি [0, 1] = [1, 2, 3]কেবল একটি খারাপ উদাহরণ। পাইথনে তেমন কিছুই নেই।
পিআরপি

@ পেপার: আমি অগত্যা পাইথন-সংজ্ঞা নামগুলি না, কেবল সাধারণ নাম। অবশ্যই alist[2]তালিকার তৃতীয় উপাদানের একটি নাম হিসাবে গণনা করা হয়। তবে আমি মনে করি আপনার সমস্যাটি কী তা আমি ভুল বুঝেছি। :-)
ভিকি 12'14

আহা। আমার ইংরেজি স্পষ্টতই আমার পাইথনের চেয়ে অনেক খারাপ। :-) আমি আরও একবার চেষ্টা করব। আমি কেবল বলেছি তাদের সম্পর্কে কথা বলার জন্য আপনাকে কিছু নাম দিতে হবে। "নামগুলি" দ্বারা আমি "পাইথন দ্বারা সংজ্ঞায়িত নামগুলি" বোঝায় নি। আমি পাইথন প্রক্রিয়া জানি, চিন্তা করবেন না।
ভেকি

8

পাইথনে এই স্টাফগুলি কীভাবে কাজ করে সে সম্পর্কে সমস্ত দুর্দান্ত ব্যাখ্যা বাদ দিয়েও আমি সমস্যার সহজ সমাধান দেখতে পাচ্ছি না। আপনি যেমন অবজেক্ট এবং দৃষ্টান্ত তৈরি করেছেন বলে মনে হচ্ছে, ইনস্ট্যান্স ভেরিয়েবলগুলি পরিচালনা করার এবং এগুলি পরিবর্তন করার অজগর পদ্ধতিটি নিম্নলিখিত:

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.Change()
        print self.variable

    def Change(self):
        self.variable = 'Changed'

উদাহরণস্বরূপ পদ্ধতিগুলিতে, আপনি সাধারণত selfঅ্যাক্সেস দৃষ্টান্ত বৈশিষ্ট্যগুলিকে উল্লেখ করেন। উদাহরণ বৈশিষ্ট্যগুলিতে উদাহরণ বৈশিষ্ট্য সেট করা __init__এবং সেগুলি পড়তে বা পরিবর্তন করা স্বাভাবিক । এজন্যই আপনি selfপ্রথম যুক্তিকে প্রথমে পাস করেন def Change

আর একটি সমাধান হ'ল এটির মতো একটি স্থির পদ্ধতি তৈরি করা:

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.variable = PassByReference.Change(self.variable)
        print self.variable

    @staticmethod
    def Change(var):
        var = 'Changed'
        return var

6

ভাষাটি সম্ভব না করে সত্ত্বেও, রেফারেন্স দ্বারা কোনও বস্তু পাস করার জন্য একটি ছোট কৌশল আছে। এটি জাভাতেও কাজ করে, এটি একটি আইটেমের সাথে তালিকা। ;-)

class PassByReference:
    def __init__(self, name):
        self.name = name

def changeRef(ref):
    ref[0] = PassByReference('Michael')

obj = PassByReference('Peter')
print obj.name

p = [obj] # A pointer to obj! ;-)
changeRef(p)

print p[0].name # p->name

এটি একটি কুরুচিপূর্ণ হ্যাক, কিন্তু এটি কার্যকর হয়। ;-P


pএকটি পরিবর্তনীয় তালিকার অবজেক্টের রেফারেন্স যা বদলে বস্তুটি সঞ্চয় করে obj। রেফারেন্স 'পি', পাস করা হয় changeRef। ভিতরে changeRef, একটি নতুন রেফারেন্স তৈরি করা হয় (নতুন রেফারেন্স বলা হয় ref) যা একই তালিকার অবজেক্টের দিকে pনির্দেশ করে যা নির্দেশ করে। তবে তালিকাগুলি পরিবর্তনীয় হওয়ায় তালিকার পরিবর্তনগুলি উভয় উল্লেখেই দৃশ্যমান । এই ক্ষেত্রে, আপনি refসূচক 0 এ অবজেক্টটি পরিবর্তন করতে রেফারেন্সটি ব্যবহার করেছেন যাতে এটি পরবর্তীকালে PassByReference('Michael')বস্তুটি সঞ্চয় করে । তালিকা অবজেক্টে refপরিবর্তনটি ব্যবহার করেই করা হয়েছিল তবে এই পরিবর্তনটি দৃশ্যমান p
মিন ট্রান

সুতরাং এখন, উল্লেখ pএবং refএকটি তালিকা অবজেক্টে নির্দেশ করে যা একক বস্তু সংরক্ষণ করে PassByReference('Michael'),। সুতরাং এটি যে p[0].nameফিরে আসে Michael। অবশ্যই, refএখন সুযোগের বাইরে চলে গেছে এবং আবর্জনা সংগ্রহ করা হতে পারে তবে সমস্ত একই।
মিন ট্রান

আপনার আছে না ব্যক্তিগত উদাহরণস্বরূপ পরিবর্তনশীল পরিবর্তন name, মূল এর PassByReferenceরেফারেন্স সঙ্গে যুক্ত বস্তুর obj, যদিও। আসলে, obj.nameফিরে আসবে Peter। পূর্বোক্ত মন্তব্যগুলি সংজ্ঞাটি Mark Ransomদিয়েছে।
মিন ট্রান

পয়েন্ট হ'ল, আমি একমত নই যে এটি একটি হ্যাক (যার অর্থ আমি এমন কোনও কিছুকে বোঝায় যা কাজ করে তবে অজানা, অন্বেষণকৃত বা প্রয়োগকারী দ্বারা অজানা কারণে)। আপনি কেবল আপনার তালিকার একটি PassByReferenceবস্তুর সাথে অন্য একটি বস্তুর প্রতিস্থাপন করেছেন PassByReferenceএবং দুটি বস্তুর উত্তর উল্লেখ করেছেন।
মিন ট্রান

5

আমি কয়েকটি ফোর্টরান কোডগুলি দ্রুত পাইথনে রূপান্তর করতে নিম্নলিখিত পদ্ধতিটি ব্যবহার করেছি। সত্য, মূল প্রশ্নটি উত্থাপিত হওয়ায় এটি রেফারেন্স দ্বারা পাস করা হয়নি, তবে কিছু ক্ষেত্রে এটি একটি সাধারণ কাজ।

a=0
b=0
c=0
def myfunc(a,b,c):
    a=1
    b=2
    c=3
    return a,b,c

a,b,c = myfunc(a,b,c)
print a,b,c

হ্যাঁ, এটি আমার ব্যবহারের ক্ষেত্রেও 'পাস বাই রেফারেন্স' সমাধান করে। আমার একটি ফাংশন রয়েছে যা মূলত একটিতে মানগুলি পরিষ্কার করে dictএবং তারপরে ফিরে আসে dict। যাইহোক, পরিষ্কার করার সময় এটি সম্ভবত সিস্টেমের কোনও অংশের পুনর্নির্মাণের প্রয়োজন হতে পারে। অতএব, ফাংশনটি কেবল পরিষ্কার হওয়া ফিরিয়ে দিতে হবে না dictতবে পুনর্নির্মাণের সংকেত দিতে সক্ষম হবে। আমি boolরেফারেন্স দিয়ে একটি পাস করার চেষ্টা করেছি , তবে ofc এর কাজ করে না। এটি কীভাবে সমাধান করা যায় তা নির্ধারণ করে, আমি আপনার সমাধানটি (মূলত একটি টুপল ফিরিয়ে দিচ্ছি) হ্যাক / ওয়ার্কারআউন্ড মোটেও (আইএমএইচও) না হয়ে সেরা কাজ করার জন্য পেয়েছি।
কাসিমির

3

রেফারেন্স দ্বারা পাস অজগর মধ্যে ভাল ফিট করে এমন কিছু নয় এবং খুব কমই ব্যবহার করা উচিত যেখানে কিছু স্থানীয় কাজ রয়েছে যা বর্তমানে স্থানীয় ভেরিয়েবলের জন্য নির্ধারিত অবজেক্টটি পেতে বা এমনকি একটি কথিত ফাংশনের অভ্যন্তর থেকে স্থানীয় ভেরিয়েবলটিকে পুনরায় সাইন করতে কাজ করতে পারে।

মূল ধারণাটি এমন কোনও ফাংশন যা সেই অ্যাক্সেসটি করতে পারে এবং অন্য ফাংশনগুলিতে অবজেক্ট হিসাবে পাস করা যায় বা কোনও ক্লাসে সঞ্চিত হতে পারে।

একটি উপায় হ'ল global(গ্লোবাল ভেরিয়েবলের জন্য) বা nonlocal(কোনও ফাংশনে লোকাল ভেরিয়েবলের জন্য) একটি মোড়ক ফাংশনে ব্যবহার করা।

def change(wrapper):
    wrapper(7)

x = 5
def setter(val):
    global x
    x = val
print(x)

একই ধারণা পড়া এবং জন্য কাজ করে del ভেরিয়েবলটি নির্ধারণের ।

শুধু পড়ার জন্য এমনকি ব্যবহারের একটি আরও ছোট উপায় রয়েছে lambda: x যা কলযোগ্যকে ফিরে আসে যা যখন ডাকা হয় তখন এক্সের বর্তমান মান প্রদান করে। এটি কিছুটা দূর অতীতের ভাষায় ব্যবহৃত "নাম দ্বারা কল" এর মতো।

কোনও ভেরিয়েবল অ্যাক্সেস করতে 3 টি র্যাপারগুলি পাস করা কিছুটা অনাবশ্যক যাতে সেগুলি প্রক্সি বৈশিষ্ট্যযুক্ত একটি শ্রেণিতে আবৃত করা যায়:

class ByRef:
    def __init__(self, r, w, d):
        self._read = r
        self._write = w
        self._delete = d
    def set(self, val):
        self._write(val)
    def get(self):
        return self._read()
    def remove(self):
        self._delete()
    wrapped = property(get, set, remove)

# left as an exercise for the reader: define set, get, remove as local functions using global / nonlocal
r = ByRef(get, set, remove)
r.wrapped = 15

পাইথনসের "প্রতিবিম্ব" সমর্থনটি এমন একটি অবজেক্টকে পাওয়া সম্ভব করে যা সেই সুযোগে স্পষ্টভাবে ফাংশনগুলি সংজ্ঞায়িত না করে একটি প্রদত্ত সুযোগে একটি নাম / ভেরিয়েবল পুনরায় সাইন করতে সক্ষম:

class ByRef:
    def __init__(self, locs, name):
        self._locs = locs
        self._name = name
    def set(self, val):
        self._locs[self._name] = val
    def get(self):
        return self._locs[self._name]
    def remove(self):
        del self._locs[self._name]
    wrapped = property(get, set, remove)

def change(x):
    x.wrapped = 7

def test_me():
    x = 6
    print(x)
    change(ByRef(locals(), "x"))
    print(x)

এখানে ByRefশ্রেণি একটি অভিধান অ্যাক্সেস মোড়ানো। সুতরাং অ্যাট্রিবিউট অ্যাক্সেসটির wrappedপাস করা অভিধানে কোনও আইটেম অ্যাক্সেসে অনুবাদ করা হয়। বিল্টিনের ফলাফল localsএবং স্থানীয় ভেরিয়েবলের নামটি পাস করার পরে এটি একটি স্থানীয় ভেরিয়েবল অ্যাক্সেস করে। ৩.৫ হিসাবে পাইথন ডকুমেন্টেশন পরামর্শ দেয় যে ডিকশনারী পরিবর্তন করা কাজ নাও করতে পারে তবে এটি আমার পক্ষে কাজ করে বলে মনে হচ্ছে।


3

পাইথন যেভাবে মান এবং রেফারেন্সগুলিকে হ্যান্ডেল করে তা দেয়, কেবলমাত্র নাম অনুসারে একটি স্বেচ্ছাচারিত উদাহরণ বৈশিষ্ট্যটি উল্লেখ করতে পারেন:

class PassByReferenceIsh:
    def __init__(self):
        self.variable = 'Original'
        self.change('variable')
        print self.variable

    def change(self, var):
        self.__dict__[var] = 'Changed'

রিয়েল কোডে আপনি অবশ্যই ডিক লুকআপে ত্রুটি যুক্ত করে যুক্ত করবেন।


3

যেহেতু অভিধানগুলি রেফারেন্স দ্বারা পাস করা হয়, আপনি এর মধ্যে কোনও রেফারেন্সযুক্ত মান সংরক্ষণ করতে একটি ডিক ভেরিয়েবল ব্যবহার করতে পারেন।

# returns the result of adding numbers `a` and `b`
def AddNumbers(a, b, ref): # using a dict for reference
    result = a + b
    ref['multi'] = a * b # reference the multi. ref['multi'] is number
    ref['msg'] = "The result: " + str(result) + " was nice!" # reference any string (errors, e.t.c). ref['msg'] is string
    return result # return the sum

number1 = 5
number2 = 10
ref = {} # init a dict like that so it can save all the referenced values. this is because all dictionaries are passed by reference, while strings and numbers do not.

sum = AddNumbers(number1, number2, ref)
print("sum: ", sum)             # the return value
print("multi: ", ref['multi'])  # a referenced value
print("msg: ", ref['msg'])      # a referenced value

3

পাইথনে পাস-বাই-রেফারেন্স সি ++ / জাভাতে রেফারেন্স পাসের ধারণা থেকে একদম আলাদা।

  • জাভা এবং সি #: আদিম প্রকারগুলি (স্ট্রিং সহ) মান (কপি সহ) পাস করে, রেফারেন্স টাইপটি রেফারেন্সের মাধ্যমে পাস হয় (ঠিকানার অনুলিপি) সুতরাং ডাকা ফাংশনে পরামিতিগুলিতে করা সমস্ত পরিবর্তনগুলি কলারের কাছে দৃশ্যমান।
  • সি ++: পাস-বাই-রেফারেন্স বা পাস-বাই-মান উভয়ই অনুমোদিত। যদি কোনও পরামিতি রেফারেন্স দিয়ে পাস হয় তবে আপনি তা পরিবর্তন করতে পারেন বা প্যারামিটারটি কনস্ট হিসাবে পাস হয়েছে কিনা তার উপর নির্ভর করে। যাইহোক, কনস্টেট বা না, প্যারামিটারটি অবজেক্টের রেফারেন্স বজায় রাখে এবং রেফারেন্সকে ডাকা ফাংশনটির মধ্যে কোনও আলাদা অবজেক্টের দিকে নির্দেশ করার জন্য বরাদ্দ করা যায় না।
  • পাইথন: পাইথন হ'ল "পাস-বাই-অবজেক্ট-রেফারেন্স", যার মধ্যে প্রায়শই বলা হয়: "অবজেক্ট রেফারেন্সটি মান দ্বারা পাস হয়।" [এখানে পড়ুন]। কলার এবং ফাংশন উভয়ই একই অবজেক্টকে বোঝায় তবে ফাংশনের পরামিতিটি একটি নতুন ভেরিয়েবল যা কেবল কলারের মধ্যে অবজেক্টের অনুলিপি ধারণ করে। সি ++ এর মতো, একটি প্যারামিটার হয় পরিবর্তিত হতে পারে না ফাংশনে না - এটি পাস হওয়া অবজেক্টের ধরণের উপর নির্ভর করে। যেমন; অপরিবর্তনীয় বস্তুর প্রকারটিকে ডাকা ফাংশনটিতে সংশোধন করা যায় না যেখানে একটি পরিবর্তনীয় অবজেক্টটি হয় আপডেট বা পুনরায় আরম্ভ করা যেতে পারে। পরিবর্তনীয় পরিবর্তনশীলটিকে আপডেট করার বা পুনরায় নির্ধারণ / পুনরায় সূচনা করার মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য হ'ল পুনঃনির্দেশিত মানটি না হলেও আপডেট মান ডাকা ফাংশনে প্রতিফলিত হয়। একটি পরিবর্তনীয় ভেরিয়েবলের সাথে নতুন কোনও বস্তুর যে কোনও অ্যাসাইনমেন্টের ক্ষেত্রটি পাইথনের ফাংশনের স্থানীয়। @ ব্লেয়ার-কনরাড দ্বারা সরবরাহিত উদাহরণগুলি এটি বুঝতে দুর্দান্ত।

1
পুরাতন তবে আমি এটি সংশোধন করতে বাধ্য feel স্ট্রিংগুলি জাভা এবং সি # উভয় ক্ষেত্রেই রেফারেন্স দ্বারা পাস করা হয়, মান অনুসারে নয়
জন

2

যেহেতু আপনার উদাহরণটি বস্তু-কেন্দ্রিক বলে মনে হচ্ছে, আপনি অনুরূপ ফলাফল অর্জন করতে নিম্নলিখিত পরিবর্তন করতে পারেন:

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change('variable')
        print(self.variable)

    def change(self, var):
        setattr(self, var, 'Changed')

# o.variable will equal 'Changed'
o = PassByReference()
assert o.variable == 'Changed'

1
যদিও এটি কাজ করে। এটি রেফারেন্স দ্বারা পাস হয় না। এটি 'অবজেক্ট রেফারেন্স দ্বারা পাস'।
বিশ্ব মিশ্র

1

রেফারেন্স অবজেক্টগুলি সঞ্চয় করার জন্য আপনি কেবল খালি ক্লাসটি উদাহরণ হিসাবে ব্যবহার করতে পারেন কারণ অভ্যন্তরীণভাবে অবজেক্ট বৈশিষ্ট্য একটি উদাহরণ অভিধানে সঞ্চয় করা হয়। উদাহরণ দেখুন।

class RefsObj(object):
    "A class which helps to create references to variables."
    pass

...

# an example of usage
def change_ref_var(ref_obj):
    ref_obj.val = 24

ref_obj = RefsObj()
ref_obj.val = 1
print(ref_obj.val) # or print ref_obj.val for python2
change_ref_var(ref_obj)
print(ref_obj.val)

1

যেহেতু এটি কোথাও উল্লেখ করা যায় না যেমন রেফারেন্সগুলি যেমন: সি ++ থেকে পরিচিত হিসাবে সিমুলেট করা যায় তবে একটি "আপডেট" ফাংশন ব্যবহার করা হয় এবং এটি আসল ভেরিয়েবলের পরিবর্তে (বা পরিবর্তে "নাম") পাস করা হয়:

def need_to_modify(update):
    update(42) # set new value 42
    # other code

def call_it():
    value = 21
    def update_value(new_value):
        nonlocal value
        value = new_value
    need_to_modify(update_value)
    print(value) # prints 42

এটি বেশিরভাগ ক্ষেত্রে "কেবলমাত্র রেফারেন্স" বা একাধিক থ্রেড / প্রক্রিয়াগুলির সাথে আপডেট (আপডেট ফাংশন থ্রেড / মাল্টিপ্রসেসিং নিরাপদ করে) কার্যকর।

স্পষ্টতই উপরেরটি মানটি পড়তে দেয় না , কেবল এটি আপডেট করে।

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