पायथन फ़ंक्शन संदर्भ द्वारा कॉल करता है


84

कुछ भाषाओं में आप रेफरी या वैल जैसे विशेष आरक्षित शब्द का उपयोग करके संदर्भ या मान द्वारा एक पैरामीटर पास कर सकते हैं । जब आप पायथन फ़ंक्शन के लिए एक पैरामीटर पास करते हैं, तो यह फ़ंक्शन को छोड़ने पर पैरामीटर के मूल्य को कभी भी बदल नहीं देता है। ऐसा करने का एकमात्र तरीका वैश्विक आरक्षित शब्द का उपयोग करके है (या जैसा कि मैं वर्तमान में इसे समझता हूं)।

उदाहरण 1:

k = 2

def foo (n):
     n = n * n     #clarity regarding comment below
     square = n
     return square

j = foo(k)
print j
print k

दिखाएगा

>>4
>>2

दिखा रहा है कि अपरिवर्तित होना

इस उदाहरण में चर n कभी नहीं बदला जाता है

उदाहरण 2:

n = 0
def foo():
    global n
    n = n * n
    return n

इस उदाहरण में चर n को बदल दिया गया है

वहाँ पायथन में किसी भी तरह से एक समारोह फोन और अजगर बताते हैं कि करने के लिए है पैरामीटर या तो है एक मूल्य या संदर्भ पैरामीटर के बजाय वैश्विक का उपयोग कर?

दूसरे, एक स्तर के कैम्ब्रिज परीक्षा में वे कहते हैं कि एक फ़ंक्शन एक एकल मान लौटाता है जबकि एक प्रक्रिया एक से अधिक मान लौटाती है । मुझे सिखाया गया था कि 80 के दशक के दौरान एक फ़ंक्शन का रिटर्न स्टेटमेंट है और प्रक्रिया नहीं है। अब यह गलत क्यों है?


5
पायथन के कॉलिंग मॉडल को समझने के लिए मैंने जो सबसे अच्छा संसाधन पाया है वह है यह आलेख effbot पर: effbot.org/zone/call-by-object.htm
Wilduck

1
आपको पायथन चरों, उत्परिवर्तनीय और अकुशल वस्तुओं के बारे में पढ़ना चाहिए। आपके पहले उदाहरण में भी क्यों nबदला जाएगा, आप squareअपनी गणना के परिणाम को संग्रहीत करने के लिए एक नए चर का उपयोग कर रहे हैं ।
फैकंडो Casco

6
कृपया एक में दो असंबंधित प्रश्न पोस्ट न करें। फ़ंक्शन बनाम प्रक्रिया की परिभाषा परिभाषा की बात है, और ऐसा लगता है कि आपकी परिभाषा पास्कल की ओर पक्षपाती है। पायथन शब्दजाल में एक प्रक्रिया के रूप में ऐसी कोई बात नहीं है।
फ्रेड फू

2
इसके अलावा, इस पिछले StackOverflow जवाब पर एक नज़र है। stackoverflow.com/a/10262945/173292 यह ऑब्जेक्ट रेफरेंस मॉडल द्वारा कॉल को काफी सहज रूप से समझाता है।
Wilduck

1
बहुत उपयोगी स्पष्टीकरण के लिए यह एसओ प्रश्न भी देखें: मैं संदर्भ से एक चर कैसे पार करूं
माइकल ओह्लोगेगे ने

जवाबों:


79

आप की तरह एक अपरिवर्तनीय वस्तु नहीं बदल सकता, strया tuple, पायथन में एक समारोह के अंदर है, लेकिन आप की तरह कर सकते हैं:

def foo(y):
  y[0] = y[0]**2

x = [5]
foo(x)
print x[0]  # prints 25

हालांकि, इसके बारे में जाने के लिए एक अजीब तरीका है, जब तक कि आपको कुछ तत्वों को हमेशा एक सरणी में वर्ग करने की आवश्यकता न हो।

ध्यान दें कि पायथन में, आप एक से अधिक मान भी लौटा सकते हैं, जिससे संदर्भ के लिए उपयोग के कुछ मामले कम महत्वपूर्ण हो जाते हैं:

def foo(x, y):
   return x**2, y**2

a = 2
b = 3
a, b = foo(a, b)  # a == 4; b == 9

जब आप इस तरह से मान लौटाते हैं, तो उन्हें एक टुपल के रूप में लौटाया जाता है जो बदले में अनपैक होता है।

संपादित करें: इसके बारे में सोचने का एक और तरीका यह है कि, जबकि आप स्पष्ट रूप से पाइथन में संदर्भ द्वारा चर पास नहीं कर सकते हैं, आप उन वस्तुओं के गुणों को संशोधित कर सकते हैं, जो मेरे द्वारा पारित किए गए थे। मेरे उदाहरण में (और अन्य) आप सूची के सदस्यों को संशोधित कर सकते हैं। यह पारित किया गया था। हालांकि, आप पूरी तरह से चर में पारित करने के लिए आश्वस्त करने में सक्षम नहीं होंगे। उदाहरण के लिए, कोड के निम्नलिखित दो टुकड़े देखें जैसे वे कुछ समान कर सकते हैं, लेकिन विभिन्न परिणामों के साथ समाप्त होते हैं:

def clear_a(x):
  x = []

def clear_b(x):
  while x: x.pop()

z = [1,2,3]
clear_a(z) # z will not be changed
clear_b(z) # z will be emptied

2
कार्यक्रमों के परिणामों को देखना उपयोगी होगा। उदाहरण के लिए 'प्रिंट x [0]' 25 लौटाता है? (हाँ यह करता है, लेकिन यह दिखाया जाना चाहिए।)
रे सलेमई

11
@alexey clear_aको एक संदर्भ दिया जाता है zऔर उस संदर्भ को संग्रहीत करता है x। यह फिर xएक अलग सरणी को संदर्भित करने के लिए तुरंत बदल जाता है। zके दायरे में मूल सरणी को भुला clear_aदिया जाता है, लेकिन वास्तव में नहीं बदला जाता है। वैश्विक दायरे में लौटते समय यह अपरिवर्तित रहता है। इसके विपरीत, clear_bजिसके साथ एक संदर्भ लेता है zऔर फिर सीधे उस पर काम करता है, बिना किसी नए सरणी या अन्यथा इंगित किए xऔर कुछ अलग किए बिना ।
मैनकॉफ़

धन्यवाद डाव! मैंने Clear_b में "एक नई सरणी बनाने" की कोशिश की y = x, y: y.pop()और फिर फोन किया clear_b(z), z अभी भी खाली हो गया ... इसलिए हमें y = list(x)x की एक प्रति बनाने के लिए कुछ ऐसा चाहिए (सूची (x) यहाँ समझाया गया है )
alexey

run_thread = [True] t= threading.Thread(target=module2.some_method, \ args=(11,1,run_thread)) --do something - and when you want to sop run_thread[0] =False
एलेक्स पुन्नेन

जावा के विपरीत, पायथन में कोई आदिम प्रकार नहीं है। सभी प्रकार की वस्तुएं।
मार्को सुल

184

अनिवार्य रूप से 'फ़ंक्शन कॉल' तीन प्रकार के होते हैं:

  • मूल्य से गुजारें
  • संदर्भ से गुजारें
  • ऑब्जेक्ट संदर्भ द्वारा पास

पायथन एक PASS-BY-OBJECT-REFERENCE प्रोग्रामिंग भाषा है।

सबसे पहले, यह समझना महत्वपूर्ण है कि एक चर, और चर (वस्तु) का मूल्य दो अलग चीजें हैं। चर 'वस्तु' को इंगित करता है। चर वस्तु नहीं है। फिर:

वार्बल ओब्जेक्ट नहीं है

उदाहरण: कोड की निम्नलिखित पंक्ति में:

>>> x = []

[]खाली सूची है, xएक चर है जो खाली सूची को इंगित xकरता है , लेकिन खुद खाली सूची नहीं है।

xएक बॉक्स के रूप में चर ( और उपरोक्त मामले में) पर विचार करें , और []बॉक्स के अंदर वस्तु के रूप में चर (') के मूल्य' ।

OBJECT REFERENCE द्वारा मामला (अजगर में मामला):

यहां, "वस्तु संदर्भों को मूल्य द्वारा पारित किया जाता है।"

def append_one(li):
    li.append(1)
x = [0]
append_one(x)
print x

यहाँ, स्टेटमेंट x = [0]एक चर x(बॉक्स) बनाता है जो ऑब्जेक्ट की ओर इंगित करता है [0]

फंक्शन कहे जाने पर, एक नया बॉक्स liबनाया जाता है। की सामग्री को liबॉक्स की सामग्री के रूप में ही कर रहे हैं xदोनों बक्सों में एक ही वस्तु है। यही है, दोनों चर स्मृति में एक ही वस्तु को इंगित करते हैं। इसलिए, द्वारा इंगित की गई वस्तु में किसी भी परिवर्तन को liभी इंगित की गई वस्तु द्वारा परिलक्षित किया जाएगा x

निष्कर्ष में, उपरोक्त कार्यक्रम का आउटपुट होगा:

[0, 1]

ध्यान दें:

यदि liफ़ंक्शन में चर को फिर से असाइन किया गया है, तो liमेमोरी में एक अलग ऑब्जेक्ट को इंगित करेगा। xहालाँकि, यह उसी ऑब्जेक्ट की ओर इशारा करता रहेगा जो स्मृति में पहले इंगित कर रहा था।

उदाहरण:

def append_one(li):
    li = [0, 1]
x = [0]
append_one(x)
print x

कार्यक्रम का आउटपुट होगा:

[0]

संदर्भ द्वारा पास:

कॉलिंग फ़ंक्शन से बॉक्स को कॉल किया जाता है जिसे फ़ंक्शन कहा जाता है। कथित तौर पर, बॉक्स की सामग्री (चर का मूल्य) को कहा जाता है। इसलिए, कॉलिंग फ़ंक्शन में बॉक्स की सामग्री में कोई भी परिवर्तन कॉलिंग फ़ंक्शन में दिखाई देगा।

मूल्य द्वारा पास:

नए फ़ंक्शन में एक नया बॉक्स बनाया जाता है, और कॉलिंग फ़ंक्शन से बॉक्स की सामग्री की प्रतियां नए बक्से में संग्रहीत की जाती हैं।

उम्मीद है की यह मदद करेगा।


4
क्या आप "संदर्भ द्वारा पास" और "पास बाय वैल्यू" जैसे उदाहरण दे सकते हैं, जैसे आपने "ऑब्जेक्ट संदर्भ द्वारा पास" के लिए किया था।
तजैन

@TJain संदर्भ द्वारा पास और मान से पास C ++ में देखा जा सकता है। यह उत्तर एक अच्छी व्याख्या देता है: stackoverflow.com/a/430958/5076583
शोभित वर्मा

3
मुझे अभी भी समझ में नहीं आया कि यह पास-दर-संदर्भ कैसे अलग है। इस उत्तर की सख्त जरूरत है कि कैसे समान छद्मकोड सभी 3 प्रतिमानों के लिए अलग-अलग आउटपुट का उत्पादन करेगा। एक अलग उत्तर से जोड़ना जो केवल पास-बाय-रेफरेंस और पास-बाय-वैल्यू के बीच के अंतर को बताता है, मदद नहीं करता है।
जेस रिडेल

क्या यह कहना अधिक सरल नहीं है कि "पायथन में सभी वेरिएबल्स पॉइंटर्स हैं " और "फंक्शन कॉल में पैरामीटर्स को दिए गए सभी वेरिएबल्स नए पॉइंटर्स को असाइन किए जाते हैं?"। यदि आपको यह एहसास है, तो आप देखेंगे कि पायथन जावा की तरह है: यह हमेशा मूल्य से संकेत देता है । देखें किर्क स्ट्रैसर का जवाब
मार्को

27

ठीक है, मैं इस पर एक छुरा लूंगा। पायथन ऑब्जेक्ट संदर्भ से गुजरता है, जो कि आप "संदर्भ द्वारा" या "मूल्य से" के रूप में सामान्य रूप से जो सोचते हैं, उससे अलग है। इस उदाहरण को लें:

def foo(x):
    print x

bar = 'some value'
foo(bar)

तो आप 'कुछ मान' और "बाइंडिंग" मान के साथ एक स्ट्रिंग ऑब्जेक्ट बना रहे हैं, जिसे नाम दिया गया है bar। C में, यह bar'कुछ मान' के सूचक के समान होगा ।

जब आप फोन करते हैं foo(bar), तो आप अपने आप में नहीं गुजर रहे barहैं। आप bar'मान' में जा रहे हैं : 'कुछ मान' के लिए एक सूचक। उस बिंदु पर, एक ही स्ट्रिंग ऑब्जेक्ट में दो "पॉइंटर्स" होते हैं।

अब इसकी तुलना करें:

def foo(x):
    x = 'another value'
    print x

bar = 'some value'
foo(bar)

यहाँ जहाँ अंतर निहित है। कतार में:

x = 'another value'

आप वास्तव में की सामग्री को बदल नहीं रहे हैं x। वास्तव में, यह भी संभव नहीं है। इसके बजाय, आप 'एक और मान' मान के साथ एक नया स्ट्रिंग ऑब्जेक्ट बना रहे हैं। वह असाइनमेंट ऑपरेटर? यह नहीं कह रहा है "इस बात xको अधिलेखित करें नए मूल्य के साथ इशारा कर रहा है"। यह कह रहा है "अद्यतन के xबजाय नई वस्तु पर इंगित करें"। उस पंक्ति के बाद, दो स्ट्रिंग ऑब्जेक्ट हैं: 'कुछ मान' (इस पर barइंगित करने के साथ ) और 'एक और मान' (इसके साथ xइंगित करने के साथ )।

यह अनाड़ी नहीं है। जब आप समझते हैं कि यह कैसे काम करता है, तो यह एक सुंदर, कुशल प्रणाली है।


3
लेकिन क्या होगा अगर मैं अपने चर की सामग्री को बदलना चाहता हूं? मैं इसे लेता हूं कि ऐसा करने का कोई तरीका नहीं है?
जलसेतु

1
आप उस ऑब्जेक्ट को बदल सकते हैं, जिस पर नाम इंगित कर रहा है, उदाहरण के लिए किसी सूची में जोड़कर, यदि वह वस्तु परिवर्तनशील है। यह कहने के लिए कोई पाइथन शब्दार्थ नहीं हैं कि "उस स्कोप के नाम स्थान को बदल दें जो मुझे बुलाता है ताकि मेरी तर्क सूची में नाम अब उस समय की तुलना में कुछ अलग हो जाए जब वह मुझे कहा जाता है"।
कर्क स्ट्रूसर

2
प्रभावी रूप से मैं जो पूछ रहा हूं वह यह है कि अजगर को प्राप्त करने का एक सरल तरीका एक ही ऑब्जेक्ट के लिए एक नया पॉइंटर नहीं बनाना है, बल्कि मूल पॉइंटर का उपयोग करना है। मैं इसे लेता हूं कि ऐसा करने का कोई तरीका नहीं है। मैं इसे अन्य उत्तरों से लेता हूं कि सामान्य कार्य-के आसपास जो संदर्भ से गुजरता है उसे प्राप्त करने के लिए बस अधिक मापदंडों को वापस करना है। अगर ऐसा है, तो मुझे इस तर्क में कुछ वैधता दिखाई देती है कि a, b, c, d, e = foo (a, b, c, d, e) सिर्फ foo (a, b, c, c) की तुलना में थोड़ा अधिक क्लंकी है। डे)।
जलीय जीव

2
@aquirdturtle इस तथ्य से कोई लेना देना नहीं है कि एक नया पॉइंटर बनाया गया है। आपको एक नई वस्तु लौटानी होगी क्योंकि strings, tuples और अन्य वस्तुएँ अपरिवर्तनीय हैं । यदि आप एक उत्परिवर्तित वस्तु को पास करते हैं, जैसे list, आप इसे वापस करने की आवश्यकता के बिना फ़ंक्शन के अंदर बदल सकते हैं, क्योंकि सभी फ़ंक्शन पैरामीटर उसी ऑब्जेक्ट के लिए संकेत हैं जो आपने पास किए थे।
मार्को सुल

24

आशा है कि निम्नलिखित विवरण इसे अच्छी तरह प्रस्तुत करते हैं:

यहां पर विचार करने के लिए दो चीजें हैं - चर और वस्तुएं।

  1. यदि आप एक चर पारित कर रहे हैं, तो यह मूल्य से गुजरता है, जिसका अर्थ है कि फ़ंक्शन के भीतर चर में किए गए परिवर्तन उस फ़ंक्शन के लिए स्थानीय हैं और इसलिए यह विश्व स्तर पर प्रतिबिंबित नहीं होगा। यह व्यवहार की तरह एक 'सी' का अधिक है।

उदाहरण:

def changeval( myvar ):
   myvar = 20; 
   print "values inside the function: ", myvar
   return

myvar = 10;
changeval( myvar );
print "values outside the function: ", myvar

ओ / पी:

values inside the function:  20 
values outside the function:  10
  1. यदि आप एक सूची की तरह, एक परिवर्तनशील वस्तु के अंदर पैक किए गए चर पास कर रहे हैं, तो ऑब्जेक्ट में किए गए परिवर्तन तब तक वैश्विक रूप से परिलक्षित होते हैं, जब तक कि ऑब्जेक्ट फिर से असाइन नहीं किया जाता है।

उदाहरण:

def changelist( mylist ):
   mylist2=['a'];
   mylist.append(mylist2);
   print "values inside the function: ", mylist
   return

mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist

ओ / पी:

values inside the function:  [1, 2, 3, ['a']]
values outside the function:  [1, 2, 3, ['a']]
  1. अब उस मामले पर विचार करें जहां ऑब्जेक्ट को फिर से सौंपा गया है। इस स्थिति में, ऑब्जेक्ट एक नई मेमोरी लोकेशन को संदर्भित करता है जो उस फ़ंक्शन के लिए स्थानीय है जिसमें ऐसा होता है और इसलिए यह विश्व स्तर पर प्रतिबिंबित नहीं होता है।

उदाहरण:

def changelist( mylist ):
   mylist=['a'];
   print "values inside the function: ", mylist
   return

mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist

ओ / पी:

values inside the function:  ['a']
values outside the function:  [1, 2, 3]

2
यह सबसे अच्छा सारांश है! ^^ ^ सबसे अच्छा सारांश यहाँ ^ ^ ^ हर कोई इस जवाब को पढ़ें! 1. पास सरल चर 2. पास ऑब्जेक्ट संदर्भ जो संशोधित किया गया है। 3. पास ऑब्जेक्ट संदर्भ जो फ़ंक्शन में पुन: असाइन किया गया है
gaoithe

4
यह उत्तर बहुत उलझा हुआ है। पायथन अलग-अलग प्रकार के मानों को अलग-अलग पारित नहीं करता है: पायथन में सभी फ़ंक्शन तर्क असाइनमेंट द्वारा अपने मान प्राप्त करते हैं, और ठीक उसी तरह व्यवहार करते हैं जैसे असाइनमेंट भाषा में कहीं और व्यवहार करता है। ("हालांकि यह तरीका तब तक स्पष्ट नहीं हो सकता जब तक कि आप डच न हों।")
डैनियल प्राइडेन

9

पायथन न तो पास-बाय-वैल्यू है और न ही पास-बाय-रेफरेंस। यहाँ वर्णित के अनुसार यह "वस्तु संदर्भों को मूल्य द्वारा पारित किया जाता है" अधिक है :

  1. यहां बताया गया है कि यह पास-बाय-वैल्यू क्यों नहीं है। चूंकि

    def append(list):
        list.append(1)
    
    list = [0]
    reassign(list)
    append(list)
    

रिटर्न [0,1] यह दर्शाता है कि किसी प्रकार का संदर्भ स्पष्ट रूप से पारित किया गया था क्योंकि पास-बाय-वैल्यू फ़ंक्शन को पैरेंट स्कोप को बदलने की अनुमति नहीं देता है

पास-पास संदर्भ की तरह लग रहा है, फिर हु? नहीं।

  1. यहाँ क्यों यह पास-बाय-रेफरेंस नहीं है।चूंकि

    def reassign(list):
      list = [0, 1]
    
    list = [0]
    reassign(list)
    print list
    

रिटर्न [0] दिखा रहा है कि सूची को पुन: असाइन किए जाने पर मूल संदर्भ नष्ट हो गया था। पास-दर-संदर्भ वापस आ गया होगा [0,1]

अधिक जानकारी के लिए यहां देखें :

यदि आप चाहते हैं कि आपका कार्य बाहर के दायरे में हेरफेर न करे, तो आपको एक नया ऑब्जेक्ट बनाने वाले इनपुट मापदंडों की प्रतिलिपि बनाने की आवश्यकता है।

from copy import copy

def append(list):
  list2 = copy(list)
  list2.append(1)
  print list2

list = [0]
append(list)
print list

4

तकनीकी रूप से अजगर मूल्य से तर्क पारित नहीं करते हैं: सभी संदर्भ द्वारा। लेकिन ... चूँकि अजगर के पास दो प्रकार की वस्तुएँ होती हैं: अपरिवर्तनीय और परिवर्तनशील, यहाँ वही होता है:

  • अपरिवर्तनीय तर्क प्रभावी रूप से मूल्य द्वारा पारित किए जाते हैं : स्ट्रिंग, पूर्णांक, ट्यूपल सभी अपरिवर्तनीय वस्तु प्रकार हैं। हालांकि वे तकनीकी रूप से "संदर्भ द्वारा पारित" (सभी मापदंडों की तरह) हैं, क्योंकि आप उन्हें फ़ंक्शन के अंदर इन-प्लेस में नहीं बदल सकते हैं जो ऐसा दिखता है / व्यवहार करता है जैसे कि यह मूल्य द्वारा पारित किया गया है।

  • परस्पर तर्क प्रभावी ढंग से संदर्भ द्वारा पारित किए जाते हैं : सूची या शब्दकोश इसके संकेत द्वारा पारित किए जाते हैं। फ़ंक्शन (परिशिष्ट या डेल) के अंदर कोई भी जगह परिवर्तन मूल वस्तु को प्रभावित करेगा।

यह कैसे पायथन को डिज़ाइन किया गया है: कोई प्रतियां नहीं और सभी संदर्भ द्वारा पारित की जाती हैं। आप स्पष्ट रूप से एक प्रति पारित कर सकते हैं।

def sort(array):
    # do sort
    return array

data = [1, 2, 3]
sort(data[:]) # here you passed a copy

अंतिम बिंदु मैं यह उल्लेख करना चाहूंगा कि एक फ़ंक्शन का अपना क्षेत्र है।

def do_any_stuff_to_these_objects(a, b): 
    a = a * 2 
    del b['last_name']

number = 1 # immutable
hashmap = {'first_name' : 'john', 'last_name': 'legend'} # mutable
do_any_stuff_to_these_objects(number, hashmap) 
print(number) # 1 , oh  it should be 2 ! no a is changed inisde the function scope
print(hashmap) # {'first_name': 'john'}

1
"अपरिवर्तनीय तर्क प्रभावी रूप से मूल्य द्वारा पारित किए जाते हैं: स्ट्रिंग, पूर्णांक, ट्यूपल सभी संदर्भ द्वारा पारित किए जाते हैं" इस वाक्य में आत्म-विरोधाभास है
eral

@ अंतिम, यदि आप पूरा संदर्भ समझते हैं, तो यह स्वयं विरोधाभासी नहीं है। मैंने इसे और अधिक स्पष्ट करने के लिए इसे संपादित किया।
वातकी 02

2

तो यह एक सूक्ष्म बिंदु का एक छोटा सा है, क्योंकि जबकि पायथन केवल चर को मान से पारित करता है, पायथन में प्रत्येक चर एक संदर्भ है। यदि आप एक फ़ंक्शन कॉल के साथ अपने मूल्यों को बदलने में सक्षम होना चाहते हैं, तो आपको एक पारस्परिक वस्तु की आवश्यकता है। उदाहरण के लिए:

l = [0]

def set_3(x):
    x[0] = 3

set_3(l)
print(l[0])

उपरोक्त कोड में, फ़ंक्शन एक सूची ऑब्जेक्ट (जो कि परिवर्तन योग्य है) की सामग्री को संशोधित करता है, और इसलिए आउटपुट 0 के बजाय 3 है।

मैं यह उत्तर केवल यह बताने के लिए लिखता हूं कि पायथन में 'मूल्य द्वारा' का क्या अर्थ है। उपरोक्त कोड खराब शैली है, और यदि आप वास्तव में अपने मूल्यों को म्यूट करना चाहते हैं, तो आपको उस वर्ग के भीतर एक वर्ग और कॉल के तरीके लिखना चाहिए, जैसा कि 5X का सुझाव है।


यह आधा प्रश्न का उत्तर देता है तो मैं एक ही set_3 (x) फ़ंक्शन को कैसे लिखूंगा ताकि यह l का मान न बदले लेकिन एक नई सूची लौटाता है जिसे बदल दिया गया है?
टिमोथी लॉमैन

बस एक नई सूची बनाएं और इसे संशोधित करें:y = [a for a in x]; y[0] = 3; return y
इसहाक

पूरी बात में सूचियों और प्रतिलिपि सूचियों को शामिल किया गया है जो उत्तर देने के लिए कुछ तरीकों से जाता है, लेकिन मैं इसे किसी सूची में एक इंट को बदलने के लिए कैसे कर सकता हूं या क्या यह हमारे पास सबसे अच्छा है?
टिमोथी लॉमैन

आप एक int की तरह एक आदिम तर्क को संशोधित नहीं कर सकते। आपको इसे किसी प्रकार के कंटेनर में डालना होगा। मेरे उदाहरण ने इसे एक सूची में रखा। आप इसे कक्षा या शब्दकोश में भी डाल सकते हैं। हालांकि वास्तव में, आपको इसे किसी फ़ंक्शन के साथ पुन: असाइन करना चाहिए जैसे कुछ x = foo(x)
इसहाक

0

जवाब दिया गया है

def set_4(x):
   y = []
   for i in x:
       y.append(i)
   y[0] = 4
   return y

तथा

l = [0]

def set_3(x):
     x[0] = 3

set_3(l)
print(l[0])

जो अब तक का सबसे अच्छा जवाब है क्योंकि यह वही करता है जो वह सवाल में कहता है। हालाँकि, यह VB या पास्कल की तुलना में बहुत ही भद्दा तरीका लगता है। क्या यह हमारे पास सबसे अच्छा तरीका है?

न केवल यह अनाड़ी है, इसमें मूल पैरामीटर को किसी तरह से परिवर्तित करना शामिल है से मैन्युअल रूप से परिवर्तित करना शामिल है जैसे कि मूल पैरामीटर को किसी सूची में बदलना: या इसे केवल कहने के बजाय किसी अन्य सूची में कॉपी करना: "इस पैरामीटर को मान के रूप में उपयोग करें" या "इस का उपयोग करें" संदर्भ के रूप में"। क्या इसका सरल उत्तर हो सकता है कि इसके लिए कोई आरक्षित शब्द नहीं है , लेकिन ये बड़े काम हैं?


0

विचार करें कि चर एक बॉक्स है और यह जिस मूल्य को इंगित करता है वह बॉक्स के अंदर "बात" है:

1. संदर्भ से गुजरें: फ़ंक्शन एक ही बॉक्स साझा करता है और इस तरह से अंदर की चीज भी।

2. मान से गुजारें: फ़ंक्शन एक नया बॉक्स बनाता है, पुराने की प्रतिकृति, जो भी चीज उसके अंदर है उसकी एक प्रति सहित। उदाहरण के लिए। जावा - फ़ंक्शन बॉक्स की एक प्रति और उसके अंदर की चीज़ बनाते हैं जो हो सकता है: एक वस्तु के लिए एक आदिम / एक संदर्भ। (ध्यान दें कि नए बॉक्स में कॉपी किए गए संदर्भ और मूल दोनों अभी भी एक ही ऑब्जेक्ट को इंगित करते हैं, यहां संदर्भ बॉक्स के अंदर की चीज है, न कि उस ऑब्जेक्ट की ओर इशारा करता है)

3. ऑब्जेक्ट-रेफरेंस से गुजरें : फ़ंक्शन एक बॉक्स बनाता है, लेकिन यह एक ही चीज़ को संलग्न करता है प्रारंभिक बॉक्स संलग्न था। तो पायथन में :

a) यदि उक्त बॉक्स के अंदर की चीज परस्पर परिवर्तन योग्य है , तो किए गए परिवर्तन मूल बॉक्स में वापस दिखाई देंगे (उदाहरण के लिए। सूचियाँ)।

b) यदि बात अपरिवर्तनीय है (जैसे अजगर स्ट्रिंग्स और न्यूमेरिक प्रकार), तो फ़ंक्शन के अंदर बॉक्स उसी चीज़ को रखेगा, जिस पर UNTIL आपके मूल्य को बदलने का प्रयास करता है। एक बार बदल जाने के बाद, फंक्शन के बॉक्स में चीज़ मूल की तुलना में एक बिल्कुल नई चीज़ है। इसलिए उस बॉक्स के लिए आईडी () अब उस नई चीज़ की पहचान देगा जो उसे संलग्न करती है


0
class demoClass:
    x = 4
    y = 3
foo1 = demoClass()
foo1.x = 2
foo2 = demoClass()
foo2.y = 5
def mySquare(myObj):
    myObj.x = myObj.x**2
    myObj.y = myObj.y**2
print('foo1.x =', foo1.x)
print('foo1.y =', foo1.y)
print('foo2.x =', foo2.x)
print('foo2.y =', foo2.y)
mySquare(foo1)
mySquare(foo2)
print('After square:')
print('foo1.x =', foo1.x)
print('foo1.y =', foo1.y)
print('foo2.x =', foo2.x)
print('foo2.y =', foo2.y)

-2

पायथन में संदर्भ के माध्यम से या मान के साथ गुजरना पड़ता है कि आप वास्तविक वस्तुओं को क्या कर रहे हैं। यदि आप उदाहरण के लिए एक सूची से गुजर रहे हैं, तो आप वास्तव में संदर्भ द्वारा इस पास को बनाते हैं, क्योंकि सूची एक परिवर्तनशील वस्तु है। इस प्रकार, आप फ़ंक्शन को एक पॉइंटर पास कर रहे हैं और आप फ़ंक्शन बॉडी में ऑब्जेक्ट (सूची) को संशोधित कर सकते हैं।

जब आप एक स्ट्रिंग पास कर रहे होते हैं, तो यह पासिंग वैल्यू द्वारा किया जाता है, इसलिए एक नया स्ट्रिंग ऑब्जेक्ट बनाया जा रहा है और जब फ़ंक्शन समाप्त हो जाता है तो यह नष्ट हो जाता है। तो यह सब परस्पर और अपरिवर्तनीय वस्तुओं के साथ करना है।


1
यह पूरी तरह से गलत है। पायथन हमेशा "ऑब्जेक्ट संदर्भ" से गुजरता है (जो चर संदर्भ से अलग है)।
किर्क स्ट्रैसर

मैं सादृश्य परिवर्तनशील वस्तुओं का मतलब - संदर्भ और अपरिवर्तनीय वस्तुओं से गुजरती हैं - value.It द्वारा पास सही मान्य है saying.You शायद समझ नहीं आया क्या मैं कर रहा हूँ मैं क्या कह रहा था
jkalivas

1
मैंने इसे पकड़ लिया और यह गलत है। इसका इस बात से कोई लेना-देना नहीं है कि कोई वस्तु परस्पर है या अपरिवर्तनीय; यह हमेशा उसी तरह से किया जाता है।
बजे कर्क स्ट्रेसर

-2

अजगर पहले से ही रेफरी द्वारा कॉल ..

आइए उदाहरण लेते हैं:

  def foo(var):
      print(hex(id(var)))


  x = 1 # any value
  print(hex(id(x))) # I think the id() give the ref... 
  foo(x)

उत्पादन

  0x50d43700 #with you might give another hex number deppend on your memory 
  0x50d43700

नहीं, यह सच नहीं हैdef foo(var): print(id(var)) var = 1234 print(id(var)) x = 123 print(id(x)) # I think the id() give the ref... foo(x) print(id(x))
ज़ोहैब इज़ाज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.