पायथन में संदर्भ द्वारा पूर्णांक पास करना


96

मैं पायथन में संदर्भ द्वारा एक पूर्णांक कैसे पास कर सकता हूं?

मैं एक चर के मान को संशोधित करना चाहता हूं जिसे मैं फ़ंक्शन में पास कर रहा हूं। मैंने पढ़ा है कि पायथन में सब कुछ मूल्य से पास है, लेकिन एक आसान चाल है। उदाहरण के लिए, जावा में आप के संदर्भ प्रकार गुजर सकता है Integer, Longआदि

  1. मैं संदर्भ द्वारा फ़ंक्शन में पूर्णांक कैसे पास कर सकता हूं?
  2. सर्वोत्तम अभ्यास क्या हैं?

इसे एक अच्छे के लिए देखें, अगर आप अपने इनटस को अनाम कक्षा में लपेटने के लिए थोड़ा जटिल तरीका (जो कि परस्पर है) जो एक 'संदर्भ' की तरह व्यवहार करेगा: stackoverflow.com/a/1123054/409638 अर्थात ref = type ('') () , {'एन': 1})
रॉबट

जवाबों:


106

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

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

x = [1]
change(x)
print x

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

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

आमतौर पर वर्कअराउंड केवल उस ऑब्जेक्ट को वापस करना है जिसे आप चाहते हैं:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

* ऊपर के पहले उदाहरण के मामले में, 3वास्तव में पास हो जाता है x.__setitem__


11
"अजगर वस्तुओं को पास करता है।" नहीं। पाइथन संदर्भों (वस्तुओं की ओर इशारा करता है) से गुजरता है।
user102008

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

यह निश्चित रूप से अजगर के संदर्भ क्या हैं, इसका वर्णन है , लेकिन यह उन लोगों के लिए सफलतापूर्वक वर्णन करने का तरीका खोजना आसान नहीं है जो शब्दावली से परिचित नहीं हैं।
mgilson

2
यह कोई आश्चर्य नहीं है कि हम शब्दावली से भ्रमित हो जाते हैं। यहां हमने इसे कॉल-बाय-ऑब्जेक्ट के रूप में वर्णित किया है और यहां इसे पास-बाय-वैल्यू के रूप में वर्णित किया गया है । कहीं और इसे "पास-बाय-रेफरेंस" कहा जाता है, जो वास्तव में इसका मतलब है, पर एक तारांकन चिह्न के साथ ... मूल रूप से, समस्या यह है कि समुदाय ने इसे कॉल करने के लिए क्या
mgilson

1
पायथन संदर्भ जावा संदर्भों के समान सटीक हैं। और जावा संदर्भ वस्तुओं के लिए जेएलएस संकेत के अनुसार हैं। और मूल रूप से जावा / पाइथन संदर्भों और C ++ पॉइंटर्स के बीच शब्दार्थ में वस्तुओं के लिए एक पूर्ण आक्षेप है, और कुछ भी इस शब्दार्थ का वर्णन नहीं करता है। "उन्हें नहीं होना चाहिए" ठीक है, .ऑपरेटर बस बाईं ओर dereferences है। विभिन्न भाषाओं में ऑपरेटर अलग-अलग हो सकते हैं।
user102008

31

अधिकांश मामले जहां आपको संदर्भ से गुजरने की आवश्यकता होती है, जहां आपको कॉल करने वाले को एक से अधिक मूल्य वापस करने की आवश्यकता होती है। एक "सर्वोत्तम अभ्यास" कई वापसी मूल्यों का उपयोग करना है, जो कि जावा जैसी भाषाओं की तुलना में पायथन में करना बहुत आसान है।

यहाँ एक सरल उदाहरण है:

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

9

सीधे एक मान को पारित नहीं करना, लेकिन इसका उपयोग करना जैसे कि इसे पारित किया गया था।

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

चेतावनियां:

  • nonlocal अजगर 3 में पेश किया गया था
  • यदि एन्कोडिंग स्कोप वैश्विक है, तो globalइसके बजाय उपयोग करें nonlocal

7

वास्तव में, सबसे अच्छा अभ्यास वापस कदम रखना है और पूछना है कि क्या आपको वास्तव में ऐसा करने की आवश्यकता है। क्योंआप उस चर के मान को संशोधित करना चाहते हैं जिसे आप फ़ंक्शन में पास कर रहे हैं?

यदि आपको इसे एक त्वरित हैक के लिए करने की आवश्यकता है, तो सबसे तेज़ तरीका एक listपूर्णांक को पास करना है , और एक छड़ी करना है[0] हर उपयोग के चारों ओर करना, जैसा कि mgilson का उत्तर दर्शाता है।

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

अधिक आम तौर पर, यदि आप कुछ जावा मुहावरों को सीधे पायथन में पोर्ट करने की कोशिश कर रहे हैं, तो आप इसे गलत कर रहे हैं। यहां तक ​​कि जब वहाँ कुछ सीधे इसी (के साथ static/ के रूप में @staticmethod) है, आप अभी भी इसे सबसे पायथन कार्यक्रमों में उपयोग नहीं करना चाहते हैं क्योंकि आप इसे जावा में उपयोग करेंगे।


JAVA पूर्णांकों को संदर्भ (पूर्णांक या किसी भी वस्तु) से पारित नहीं करता है। बॉक्स वाली वस्तुओं को असाइनमेंट पर प्रतिस्थापित किया जाता है)।
लुइस मूसली 3

@LuisMasuelli खैर, बॉक्सिंग प्राइमिटव्स को वस्तुओं की तरह ही व्यवहार किया जाता है, केवल ओपी चाहता है के रूप में उनके उपयोग को रोकने वाली बात यह है कि बक्से अपरिवर्तनीय हैं (और चूंकि आदिम स्वयं भी अपरिवर्तनीय हैं, पूरी चीज अपरिवर्तनीय है और केवल इसे बदला जा सकता है चर स्तर)
क्रॉल्टन

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

4

पायथन में, हर मूल्य एक संदर्भ (किसी वस्तु के लिए एक संकेतक) है, जावा में गैर-आदिम की तरह। इसके अलावा, जावा की तरह, पायथन केवल मूल्य से गुज़रा है। इसलिए, शब्दार्थ, वे बहुत अधिक समान हैं।

चूंकि आप अपने प्रश्न में जावा का उल्लेख करते हैं, इसलिए मैं यह देखना चाहूंगा कि आप जावा में क्या चाहते हैं। यदि आप इसे जावा में दिखा सकते हैं, तो मैं आपको यह दिखा सकता हूं कि इसे पायथन में बिलकुल समकक्ष कैसे किया जाए।


4

एक संख्यात्मक एकल-तत्व सरणी परिवर्तनशील है और अभी तक अधिकांश प्रयोजनों के लिए, इसका मूल्यांकन किया जा सकता है जैसे कि यह एक संख्यात्मक अजगर संस्करण था। इसलिए, यह एकल तत्व सूची की तुलना में अधिक सुविधाजनक उप-संदर्भ संख्या कंटेनर है।

    import numpy as np
    def triple_var_by_ref(x):
        x[0]=x[0]*3
    a=np.array([2])
    triple_var_by_ref(a)
    print(a+1)

उत्पादन:

3


3

शायद यह पाइथोनिक तरीका नहीं है, लेकिन आप ऐसा कर सकते हैं

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

यार वो स्मार्ट है।
xilpex

2

हो सकता है कि लिस्ट-ऑफ-लेंथ -1 ट्रिक की तुलना में थोड़ा अधिक स्व-दस्तावेजीकरण पुराना खाली टाइप ट्रिक है:

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)

या एक वर्ग में संख्या को लपेटें: github.com/markrages/python_mutable_number
अंकन

0

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


3
मुझे लगता है, क्योंकि everything is passed by valueवास्तव में सच नहीं है। भाव डॉक्स:arguments are passed using call by value (where the value is always an object reference, not the value of the object)
एस्ट्री

1
सूचियां, वस्तुएं और शब्दकोश संदर्भ द्वारा पारित किए जाते हैं
AN88

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

0

सही उत्तर, कक्षा का उपयोग करना और मूल्य को कक्षा के अंदर रखना है, इससे आप अपनी इच्छानुसार संदर्भ से गुजर सकते हैं।

class Thing:
  def __init__(self,a):
    self.a = a
def dosomething(ref)
  ref.a += 1

t = Thing(3)
dosomething(t)
print("T is now",t.a)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.