पायथन में संकेत?


124

मुझे पता है कि पायथन में संकेत नहीं हैं, लेकिन क्या 2इसके बजाय इस उपज का एक तरीका है

>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1

?


यहाँ एक उदाहरण है: मैं चाहता हूँ form.data['field']और form.field.valueहमेशा एक ही मूल्य है। यह पूरी तरह से आवश्यक नहीं है, लेकिन मुझे लगता है कि यह अच्छा होगा।


उदाहरण के लिए, PHP में, मैं यह कर सकता हूं:

<?php

class Form {
    public $data = [];
    public $fields;

    function __construct($fields) {
        $this->fields = $fields;
        foreach($this->fields as &$field) {
            $this->data[$field['id']] = &$field['value'];
        }
    }
}

$f = new Form([
    [
        'id' => 'fname',
        'value' => 'George'
    ],
    [
        'id' => 'lname',
        'value' => 'Lucas'
    ]
]);

echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph

आउटपुट:

GeorgeGeorgeRalphRalph

ideone


या सी ++ में ऐसा लगता है (मुझे लगता है कि यह सही है, लेकिन मेरा सी ++ रस्टी है):

#include <iostream>
using namespace std;

int main() {
    int* a;
    int* b = a;
    *a = 1;
    cout << *a << endl << *b << endl; # 1 1

    return 0;
}

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

8
यह बहुत कल्पना नहीं करता है; मैं ऐसा करने के लिए दर्जनों कारणों के बारे में सोच सकता हूं। यह सिर्फ यह नहीं है कि यह अजगर की तरह सूचक-कम भाषाओं में कैसे किया जाता है; आपको इसे एक कंटेनर में लपेटने की आवश्यकता है जो कि अपरिवर्तनीय नहीं है, जैसा कि मैट के उत्तर में है।
ग्लेन मेनार्ड

14
आप पायथन में एक स्वैप समारोह नहीं लिखेंगे। आप लिखेंगे a, b = b, a
dan04

3
-1: प्रश्न में निर्माण एक (समझदार) है, और (बी) कोई भी ऐसा उदाहरण देने में सक्षम नहीं लगता जो उसे समझदार बनाता हो। यह कहना कि "दर्जनों कारण" उदाहरण पोस्ट करने के समान नहीं हैं।
एस.लूट

1
@ मर्क: इसके अलावा, मैं "असहमत" नहीं हूं। मैं उलझन में हूं। मैं एक प्रश्न पूछ रहा हूं, यह समझने का तरीका खोज रहा हूं कि यह क्या है और आपको क्यों लगता है कि यह इतना महत्वपूर्ण है।
एस.लॉट

जवाबों:


48

मैं चाहता हूँ form.data['field']और form.field.valueहमेशा एक ही मूल्य है

यह संभव है, क्योंकि इसमें सजाए गए नाम और अनुक्रमण शामिल हैं - यानी, बारनेम से पूरी तरह से अलग निर्माण और जो आप के बारे में पूछ रहे हैं, और आपके अनुरोध के लिए पूरी तरह से असंभव है। क्यों आप (वास्तव में) वास्तव में चाहते हैं (संभव) बात से कुछ असंभव और पूरी तरह से अलग है ! ab

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

अब, आपका "वास्तविक डिसाइडेराटा" उदाहरण रहस्यमय है क्योंकि प्रत्येक मामले में अनुक्रमण या विशेषता-प्राप्ति के दो स्तर शामिल हैं, इसलिए आपके द्वारा दी गई सूक्ष्मता को कई तरीकों से पेश किया जा सकता है। form.fieldउदाहरण के लिए, इसके अलावा और कौन सी विशेषताएँ हैं value? कि आगे की .valueसंगणना के बिना , संभावनाओं में शामिल होंगे:

class Form(object):
   ...
   def __getattr__(self, name):
       return self.data[name]

तथा

class Form(object):
   ...
   @property
   def data(self):
       return self.__dict__

.valueपहले फॉर्म को चुनने का सुझाव दिया गया, साथ ही एक तरह का बेकार आवरण:

class KouWrap(object):
   def __init__(self, value):
       self.value = value

class Form(object):
   ...
   def __getattr__(self, name):
       return KouWrap(self.data[name])

यदि कार्य ऐसे form.field.value = 23भी प्रविष्टि सेट करने के लिए माना जाता है form.data, तो आवरण और अधिक जटिल वास्तव में बन जाना चाहिए, और बेकार है कि सभी नहीं:

class MciWrap(object):
   def __init__(self, data, k):
       self._data = data
       self._k = k
   @property
   def value(self):
       return self._data[self._k]
   @value.setter
   def value(self, v)
       self._data[self._k] = v

class Form(object):
   ...
   def __getattr__(self, name):
       return MciWrap(self.data, name)

बाद का उदाहरण लगभग उतना ही करीब है जितना कि पायथन में, "पॉइंटर" के अर्थ में, जैसा कि आप चाहते हैं - लेकिन यह समझना महत्वपूर्ण है कि इस तरह की सूक्ष्मता कभी भी केवल अनुक्रमण और / या सजाए गए नामों के साथ काम कर सकती है , कभी नहीं जैसा कि आपने मूल रूप से बारनामेस के साथ पूछा था!


23
मैंने इसे वैसे ही पूछा जैसे मैं कर रहा था क्योंकि मैं एक सामान्य समाधान प्राप्त करने की उम्मीद कर रहा था जो "बार्नेम्स" के लिए सब कुछ ठीक काम करेगा और मेरे पास उस समय कोई विशेष मामला नहीं था - बस मैं इसमें भाग गया था इस परियोजना के पिछले पुनरावृत्ति के साथ समस्या और मैं फिर से नहीं चलना चाहता था। वैसे भी, यह एक महान जवाब है! अविश्वसनीयता, हालांकि, कम सराहना की जाती है।
एमपीएन

2
@ मर्क, अपने क्यू पर टिप्पणियों को देखें और आप देखेंगे कि "अविश्वास" एक व्यापक प्रतिक्रिया है - और शीर्ष-मतदान ए आपको बता रहा है "ऐसा मत करो, इसे खत्म करो", उसके बाद एक जाता है "यह सिर्फ यह कैसे है"। हालांकि आप पायथन-जानकार लोगों को आपके मूल चश्मे के बारे में विस्मय के साथ प्रतिक्रिया नहीं दे सकते हैं , वे अपने आप में काफी हैरान हैं;;
एलेक्स मार्टेली 14

30
हां, लेकिन आप पायथन ज्ञान की कमी के कारण चकित हैं ... जैसे कि हम एक विदेशी प्रजाति हैं: पी
एमपीएन

51

कोई तरीका नहीं है कि आप केवल उस लाइन को बदल सकते हैं। तुम कर सकते हो:

a = [1]
b = a
a[0] = 2
b[0]

यह एक सूची बनाता है, एक संदर्भ संदर्भित करता है, फिर बी भी, पहले तत्व को 2 पर सेट करने के लिए एक संदर्भ का उपयोग करता है, फिर बी संदर्भ चर का उपयोग करके पहुंचता है।


17
यह ठीक उसी तरह की असंगतता है जिससे मैं पायथन और इन गतिशील भाषाओं के बारे में नफरत करता हूं। (हाँ, यह वास्तव में "असंगत" नहीं है क्योंकि आप संदर्भ के बजाय एक विशेषता बदल रहे हैं लेकिन मुझे अभी भी यह पसंद नहीं है)
एमपीएन

10
@ मर्क: वास्तव में। मैं अनगिनत (अच्छी तरह से, कुछ) लोगों को जानता हूं, जिन्होंने संभवतः अपने कोड में "बग" की खोज करने में घंटों बिताए और फिर पाया कि यह एक सूची के कारण हार्ड-कॉपी न मिलने के कारण हुआ।
houbysoft

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

मैंने इसे कई बार उपयोग किया है, आमतौर पर लगभग 2.x की कमी के लिए काम करने के लिए "नॉनक्लोकल"। यह करने के लिए सबसे सुंदर बात नहीं है, लेकिन यह एक चुटकी में ठीक काम करता है।
ग्लेन मेनार्ड

1
यह बिल्कुल भी असंगत नहीं है क्योंकि आप जिस ऑब्जेक्ट को असाइन कर रहे हैं aऔर bवह सूची है, सूची में मान नहीं है। चर असाइनमेंट नहीं बदल रहे हैं, ऑब्जेक्ट समान ऑब्जेक्ट है। यदि यह बदल गया, जैसा कि पूर्णांक (जिनमें से प्रत्येक अलग-अलग ऑब्जेक्ट हैं) को बदलने के मामले में, aअब किसी अन्य ऑब्जेक्ट को सौंपा जाएगा और bसूट का पालन करने के लिए कुछ भी नहीं है । यहां, aफिर से असाइन नहीं किया जा रहा है, बल्कि जिस वस्तु को सौंपा गया है उसके अंदर एक मूल्य बदल रहा है। चूँकि bवह अभी भी उस वस्तु से बंधा हुआ है, यह उस वस्तु और उसके भीतर के मूल्यों में परिवर्तन को प्रतिबिंबित करेगा।
अर्किगोस

34

यह एक बग नहीं है, यह एक सुविधा है :-)

जब आप पायथन में '=' ​​ऑपरेटर को देखते हैं, असाइनमेंट के संदर्भ में नहीं सोचते हैं। आप चीजों को असाइन नहीं करते हैं, आप उन्हें बांधते हैं। = एक बाध्यकारी ऑपरेटर है।

तो आपके कोड में, आप मान 1 को एक नाम दे रहे हैं: a। फिर, आप 'a' a name: b में मान दे रहे हैं। फिर आप मान 2 को 'a' नाम से बांध रहे हैं। इस ऑपरेशन में b के लिए बाध्य मान नहीं बदलता है।

सी-लाइक भाषाओं से आ रहा है, यह भ्रामक हो सकता है, लेकिन एक बार जब आप इसके आदी हो जाते हैं, तो आप पाते हैं कि यह आपको पढ़ने और अपने कोड के बारे में अधिक स्पष्ट रूप से तर्क करने में मदद करता है: 'बी' नाम का मान तब तक नहीं बदलेगा जब तक आप बदल नहीं जाते। इसे स्पष्ट रूप से बदलें। और यदि आप एक 'इम्पोर्ट इस' करते हैं, तो आप पाएंगे कि पायथन का ज़ेन बताता है कि स्पष्ट रूप से निहितार्थ से बेहतर है।

ध्यान दें कि हास्केल जैसी कार्यात्मक भाषाएं भी इस प्रतिमान का उपयोग करती हैं, जिसमें मजबूती के मामले में बहुत महत्व है।


39
आप जानते हैं, मैंने इस तरह के उत्तर दर्जनों बार पढ़े हैं, और मैंने इसे कभी नहीं समझा। a = 1; b = a; a = 2;पायथन, सी और जावा में व्यवहार बिलकुल एक जैसा है: 1. यह "इस काम पर ध्यान क्यों नहीं दिया गया, यह बाध्यकारी है"?
नेड बैचेल्ड

4
आप चीजें असाइन करते हैं। इसलिए इसे असाइनमेंट स्टेटमेंट कहा जाता है । जो अंतर आप बता रहे हैं, उसका कोई मतलब नहीं है। और इसका संकलित v। व्याख्या या स्थैतिक v। गतिशील से कोई लेना-देना नहीं है। जावा स्टैटिक टाइप-चेकिंग के साथ संकलित भाषा है, और इसमें पॉइंटर्स भी नहीं हैं।
मैथ्यू फ्लेशेन

3
C ++ के बारे में क्या? "b" "a" का संदर्भ हो सकता है। असाइनमेंट और बाइंडिंग के बीच के अंतर को समझना पूरी तरह से समझना महत्वपूर्ण है कि मार्क वह क्यों नहीं कर सकता है जो वह करना चाहता है, और पायथन जैसी भाषाओं को कैसे डिज़ाइन किया गया है। वैचारिक रूप से (आवश्यक रूप से कार्यान्वयन में नहीं), "a = 1" 1 के साथ "a" नामक मेमोरी के ब्लॉक को अधिलेखित नहीं करता है; यह पहले से मौजूद ऑब्जेक्ट "1" के लिए एक नाम "ए" प्रदान करता है, जो कि सी में क्या होता है की तुलना में मौलिक रूप से अलग है। यही कारण है कि एक अवधारणा के रूप में संकेत पायथन में मौजूद नहीं हो सकते हैं - वे अगली बार बासी हो जाएंगे। मूल चर "असाइन किया गया" था।
ग्लेन मेयार्ड

1
@dw: मुझे इस बारे में सोचने का यह तरीका पसंद है! "बाइंडिंग" एक अच्छा शब्द है। @ नीड: आउटपुट समान है, हाँ, लेकिन C में "1" के मान को दोनों में कॉपी किया जाता है aऔर bजबकि पायथन में, वे दोनों समान "1" (मुझे लगता है) को संदर्भित करते हैं । इस प्रकार, यदि आप 1 (वस्तुओं के साथ) के मूल्य को बदल सकते हैं, तो यह अलग होगा। जो कुछ अजीब बॉक्सिंग / अनबॉक्सिंग मुद्दों की ओर जाता है, मैं सुनता हूं।
एमपीएन

4
पायथन और सी के बीच का अंतर "असाइनमेंट" का मतलब नहीं है। यह "चर" का मतलब है।
dan04

28

हाँ! अजगर में एक सूचक के रूप में एक चर का उपयोग करने का एक तरीका है!

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

यहाँ सूचक असाइनमेंट का एक उदाहरण है

dict1 = {'first':'hello', 'second':'world'}
dict2 = dict1 # pointer assignation mechanism
dict2['first'] = 'bye'
dict1
>>> {'first':'bye', 'second':'world'}

यहाँ कॉपी असाइनमेंट का एक उदाहरण है

a = 1
b = a # copy of memory mechanism. up to here id(a) == id(b)
b = 2 # new address generation. therefore without pointer behaviour
a
>>> 1

पॉइंटर असाइनमेंट, कम्फर्ट कोड करने के लिए कुछ स्थितियों में, अतिरिक्त मेमोरी की बर्बादी के बिना एलियासिंग के लिए एक बहुत उपयोगी उपकरण है,

class cls_X():
   ...
   def method_1():
      pd1 = self.obj_clsY.dict_vars_for_clsX['meth1'] # pointer dict 1: aliasing
      pd1['var4'] = self.method2(pd1['var1'], pd1['var2'], pd1['var3'])
   #enddef method_1
   ...
#endclass cls_X

लेकिन किसी को कोड की गलतियों को रोकने के लिए इस उपयोग के बारे में पता होना चाहिए।

निष्कर्ष निकालने के लिए, डिफ़ॉल्ट रूप से कुछ चर नामे (सरल वस्तु जैसे int, float, str, ...) होते हैं, और कुछ उनके बीच असाइन किए जाने पर संकेत होते हैं (उदाहरण के लिए dict1 = dict2)। उन्हें कैसे पहचानें? बस उनके साथ इस प्रयोग को आजमाएँ। चर एक्सप्लोरर पैनल वाले आईडीई में आमतौर पर पॉइंटर-मैकेनिज्म ऑब्जेक्ट की परिभाषा में मेमोरी एड्रेस ("@axbbbbb ...") प्रतीत होता है।

मैं विषय में जांच का सुझाव देता हूं। ऐसे कई लोग हैं जो इस विषय के बारे में अधिक जानते हैं। ("ctypes" मॉड्यूल देखें)। मुझे आशा है कि यह उपयोगी है। वस्तुओं के अच्छे उपयोग का आनंद लें! सादर, जोस क्रेस्पो


इसलिए मुझे किसी फ़ंक्शन के संदर्भ में एक चर को पास करने के लिए एक शब्दकोश का उपयोग करना होगा, और मैं एक इंट या स्ट्रिंग का उपयोग करके संदर्भ द्वारा एक चर नहीं पारित कर सकता हूं?
सैम

13
>> id(1)
1923344848  # identity of the location in memory where 1 is stored
>> id(1)
1923344848  # always the same
>> a = 1
>> b = a  # or equivalently b = 1, because 1 is immutable
>> id(a)
1923344848
>> id(b)  # equal to id(a)
1923344848

जैसा कि आप देख सकते हैं aऔर bकेवल दो अलग-अलग नाम हैं जो एक ही अपरिवर्तनीय वस्तु (int) के संदर्भ में हैं 1। यदि आप बाद में लिखते हैं a = 2, तो आप aएक अलग ऑब्जेक्ट (int) में नाम को फिर से असाइन करते हैं 2, लेकिन bजारी रखने के लिए संदर्भित करता है 1:

>> id(2)
1923344880
>> a = 2
>> id(a)
1923344880  # equal to id(2)
>> b
1           # b hasn't changed
>> id(b)
1923344848  # equal to id(1)

यदि आपके पास एक उत्परिवर्तित वस्तु होती, जैसे कि एक सूची, तो क्या होगा [1]?

>> id([1])
328817608
>> id([1])
328664968  # different from the previous id, because each time a new list is created
>> a = [1]
>> id(a)
328817800
>> id(a)
328817800 # now same as before
>> b = a
>> id(b)
328817800  # same as id(a)

फिर, हम एक ही वस्तु (सूची) [1]को दो अलग-अलग नामों से संदर्भित कर रहे हैं aऔर b। हालाँकि अब हम इस सूची को बदल सकते हैं जबकि यह एक ही वस्तु है, और a, bक्या दोनों इसका संदर्भ देते रहेंगे

>> a[0] = 2
>> a
[2]
>> b
[2]
>> id(a)
328817800  # same as before
>> id(b)
328817800  # same as before

1
आईडी फंक्शन शुरू करने के लिए धन्यवाद। यह मेरी कई शंकाओं का समाधान करता है।
haudoing

12

एक दृष्टिकोण से, सब कुछ पायथन में एक संकेतक है। आपका उदाहरण C ++ कोड की तरह काम करता है।

int* a = new int(1);
int* b = a;
a = new int(2);
cout << *b << endl;   // prints 1

(एक समतुल्य समकक्ष shared_ptr<Object>इसके बजाय किसी प्रकार का उपयोग करेगा int*।)

यहाँ एक उदाहरण है: मैं चाहता हूं कि form.data ['फ़ील्ड'] और form.field.value का हमेशा समान मान हो। यह पूरी तरह से आवश्यक नहीं है, लेकिन मुझे लगता है कि यह अच्छा होगा।

आप इसे कक्षा __getitem__में ओवरलोड करके कर सकते हैं form.data


form.dataक्लास नहीं है क्या इसे एक बनाना आवश्यक है, या क्या मैं इसे मक्खी पर ओवरराइड कर सकता हूं? (यह सिर्फ एक अजब-गजब तानाशाही है) इसके अलावा, डेटा को formखेतों तक पहुंचने के लिए एक संदर्भ वापस होना होगा ... जो इस बदसूरत को लागू करता है।
एमपीएन

1

यह एक अजगर सूचक है (c / c ++ का अलग)

>>> a = lambda : print('Hello')
>>> a
<function <lambda> at 0x0000018D192B9DC0>
>>> id(a) == int(0x0000018D192B9DC0)
True
>>> from ctypes import cast, py_object
>>> cast(id(a), py_object).value == cast(int(0x0000018D192B9DC0), py_object).value
True
>>> cast(id(a), py_object).value
<function <lambda> at 0x0000018D192B9DC0>
>>> cast(id(a), py_object).value()
Hello

0

मैंने निम्न साधारण वर्ग को, प्रभावी रूप से, अजगर में एक पॉइंटर का अनुकरण करने का तरीका लिखा:

class Parameter:
    """Syntactic sugar for getter/setter pair
    Usage:

    p = Parameter(getter, setter)

    Set parameter value:
    p(value)
    p.val = value
    p.set(value)

    Retrieve parameter value:
    p()
    p.val
    p.get()
    """
    def __init__(self, getter, setter):
        """Create parameter

        Required positional parameters:
        getter: called with no arguments, retrieves the parameter value.
        setter: called with value, sets the parameter.
        """
        self._get = getter
        self._set = setter

    def __call__(self, val=None):
        if val is not None:
            self._set(val)
        return self._get()

    def get(self):
        return self._get()

    def set(self, val):
        self._set(val)

    @property
    def val(self):
        return self._get()

    @val.setter
    def val(self, val):
        self._set(val)

यहाँ उपयोग का एक उदाहरण है (ज्यूपिटर नोटबुक पृष्ठ से):

l1 = list(range(10))
def l1_5_getter(lst=l1, number=5):
    return lst[number]

def l1_5_setter(val, lst=l1, number=5):
    lst[number] = val

[
    l1_5_getter(),
    l1_5_setter(12),
    l1,
    l1_5_getter()
]

Out = [5, None, [0, 1, 2, 3, 4, 12, 6, 7, 8, 9], 12]

p = Parameter(l1_5_getter, l1_5_setter)

print([
    p(),
    p.get(),
    p.val,
    p(13),
    p(),
    p.set(14),
    p.get()
])
p.val = 15
print(p.val, l1)

[12, 12, 12, 13, 13, None, 14]
15 [0, 1, 2, 3, 4, 15, 6, 7, 8, 9]

बेशक, यह काम किसी वस्तु के तानाशाह सामान या विशेषताओं के लिए करना आसान है। यहां तक ​​कि ओपी ने ग्लोबल्स () का उपयोग करते हुए क्या करने के लिए कहा है:

def setter(val, dict=globals(), key='a'):
    dict[key] = val

def getter(dict=globals(), key='a'):
    return dict[key]

pa = Parameter(getter, setter)
pa(2)
print(a)
pa(3)
print(a)

यह 2 का प्रिंट आउट लेगा, उसके बाद 3 होगा।

इस तरह से वैश्विक नामस्थान के साथ खिलवाड़ करना पारदर्शी तरीके से एक भयानक विचार है, लेकिन यह दर्शाता है कि ओपी ने जो पूछा है, वह करना संभव है (यदि असावधान है)।

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

हालाँकि यह एक C या C ++ पॉइंटर की तरह नहीं दिखता है, लेकिन यह एक समस्या को हल कर रहा है जो कि मैं C ++ में लिख रहा था तो मुझे पॉइंटर्स से हल करना होगा।


0

निम्नलिखित कोड सी में संकेत के व्यवहार का अनुकरण करता है:

from collections import deque # more efficient than list for appending things
pointer_storage = deque()
pointer_address = 0

class new:    
    def __init__(self):
        global pointer_storage    
        global pointer_address

        self.address = pointer_address
        self.val = None        
        pointer_storage.append(self)
        pointer_address += 1


def get_pointer(address):
    return pointer_storage[address]

def get_address(p):
    return p.address

null = new() # create a null pointer, whose address is 0    

यहाँ उपयोग के उदाहरण हैं:

p = new()
p.val = 'hello'
q = new()
q.val = p
r = new()
r.val = 33

p = get_pointer(3)
print(p.val, flush = True)
p.val = 43
print(get_pointer(3).val, flush = True)

लेकिन अब एक और अधिक पेशेवर कोड देने का समय आ गया है, जिसमें पॉइंटर्स को हटाने का विकल्प भी शामिल है, जो मैंने अभी अपनी निजी लाइब्रेरी में पाया है:

# C pointer emulation:

from collections import deque # more efficient than list for appending things
from sortedcontainers import SortedList #perform add and discard in log(n) times


class new:      
    # C pointer emulation:
    # use as : p = new()
    #          p.val             
    #          p.val = something
    #          p.address
    #          get_address(p) 
    #          del_pointer(p) 
    #          null (a null pointer)

    __pointer_storage__ = SortedList(key = lambda p: p.address)
    __to_delete_pointers__ = deque()
    __pointer_address__ = 0 

    def __init__(self):      

        self.val = None 

        if new.__to_delete_pointers__:
            p = new.__to_delete_pointers__.pop()
            self.address = p.address
            new.__pointer_storage__.discard(p) # performed in log(n) time thanks to sortedcontainers
            new.__pointer_storage__.add(self)  # idem

        else:
            self.address = new.__pointer_address__
            new.__pointer_storage__.add(self)
            new.__pointer_address__ += 1


def get_pointer(address):
    return new.__pointer_storage__[address]


def get_address(p):
    return p.address


def del_pointer(p):
    new.__to_delete_pointers__.append(p)

null = new() # create a null pointer, whose address is 0

मुझे लगता है कि आपने सिर्फ एक अजीब तरीके से मूल्यों को बॉक्सिंग किया है।
18

आपका मतलब है: एक "चतुर तरीका" या "एक चतुर तरीका नहीं"?
माइकटेक्स

उह ... मैं एक यादृच्छिक संख्या द्वारा अनुक्रमित वैश्विक भंडारण के लिए एक वैध उपयोग-मामला देखने के लिए संघर्ष कर रहा हूं।
मप्र

उपयोग का उदाहरण: मैं एक एल्गोरिथ्म इंजीनियर हूं और मुझे प्रोग्रामर के साथ काम करना है। मैं पायथन के साथ काम करता हूं और वे C ++ के साथ काम करते हैं। कभी-कभी, वे मुझे उनके लिए एक एल्गोरिथ्म लिखने के लिए कहते हैं, और मैं इसे अपनी सुविधा के लिए C ++ के करीब लिखता हूं। बाइनरी पेड़ों आदि के लिए पॉइंटर्स उपयोगी होते हैं
माइकटेक्स

नोट: यदि वैश्विक भंडारण परेशान करता है, तो आप इसे कक्षा के स्तर पर एक वैश्विक चर के रूप में शामिल कर सकते हैं, जो संभवतः अधिक सुरुचिपूर्ण है।
माइक टीएक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.