পাইথনে পয়েন্টার?


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সর্বদা একই মান পাই । এটি সম্পূর্ণ প্রয়োজনীয় নয়, তবে আমার মনে হয় এটি দুর্দান্ত হবে it


পিএইচপি-তে, উদাহরণস্বরূপ, আমি এটি করতে পারি:

<?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
এটি খুব কল্পনা লাগে না; আমি এটি করতে চাওয়ার কয়েক ডজন কারণ সম্পর্কে ভাবতে পারি। পাইথনের মতো পয়েন্টার-কম ভাষায় এটি কীভাবে হয় তা নয়; আপনার এটিকে এমন পাত্রে আবৃত করা দরকার যা ম্যাট এর উত্তরে দেওয়া হয় না inv
গ্লেন মেইনার্ড

14
আপনি পাইথনে কোনও অদলবদল লিখবেন না। আপনি লিখবেন a, b = b, a
dan04

3
-১: প্রশ্নের কাঠামোটি (ক) সংজ্ঞাহীন, এবং (খ) কেউ মনে করেন না যে এটি এমন কোনও উদাহরণ প্রদান করতে সক্ষম হবে যা এটি বোধগম্য করে তোলে। "ডজন ডজন কারণ" আছে বলা উদাহরণ পোস্ট করার মতো নয়।
এসলট

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
@ মার্ক, আপনার প্রশ্নে মন্তব্যগুলি দেখুন এবং আপনি দেখতে পাবেন যে "অবিশ্বাস" একটি বিস্তৃত প্রতিক্রিয়া - এবং শীর্ষ-ভোটপ্রাপ্ত এ আপনাকে "এটি করবেন না, এটি পেতে" বলছেন, তারপরে একটি "এটি ঠিক কেমন হয়" যায়। যদিও আপনি পাইথন-জ্ঞানী লোকগুলি আপনার মূল চশমাগুলিতে বিস্মিত হয়ে প্রতিক্রিয়া ব্যক্ত করেছেন তা "প্রশংসা" করতে পারেন না, তারা নিজের মধ্যে বেশ অবাক হয় ;-)।
অ্যালেক্স মার্টেলি

30
হ্যাঁ, তবে পাইথনের জ্ঞানের অভাব দেখে আপনি অবাক হয়েছেন ... যেন আমরা বিদেশী প্রজাতি: পি
এমপেন

51

কেবলমাত্র সেই লাইনটি পরিবর্তন করে আপনি এটি করার কোনও উপায় নেই। আপনি করতে পারেন:

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

এটি একটি তালিকা তৈরি করে, একটিকে রেফারেন্স বরাদ্দ করে, তারপর বিও, প্রথম উপাদানটিকে 2 এ সেট করার জন্য একটি রেফারেন্স ব্যবহার করে, তারপর বি রেফারেন্স ভেরিয়েবল ব্যবহার করে অ্যাক্সেস করে।


17
পাইথন এবং এই গতিশীল ভাষাগুলি সম্পর্কে আমি ঠিক এ জাতীয় অসঙ্গতি ঘৃণা করি। (হ্যাঁ হ্যাঁ, এটি আসলে "অসঙ্গত" নয় কারণ আপনি উল্লেখের পরিবর্তে কোনও বৈশিষ্ট্য পরিবর্তন করছেন তবে আমি এখনও এটি পছন্দ করি না)
এমপেন

10
@ মার্ক: সত্যই। আমি অগণিত (ভাল, কয়েক) লোককে জানি যারা তাদের কোডে "বাগ" অনুসন্ধান করতে এবং পরে এটি জানতে পেরেছিলেন যে এটি কোনও তালিকার হার্ড-অনুলিপি না পাওয়ার কারণে হয়েছে।
houbysoft

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

আমি এটি বেশ কয়েকবার ব্যবহার করেছি, বেশিরভাগ ক্ষেত্রে প্রায় 2.x এর "ননলোকাল" এর অভাব কাজ করে। এটি করা সবচেয়ে সুন্দর জিনিস নয়, তবে এটি একটি চিমটিতে দুর্দান্ত কাজ করে।
গ্লেন মেইনার্ড

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

34

এটি কোনও বাগ নয়, এটি একটি বৈশিষ্ট্য :-)

আপনি যখন পাইথনের '=' অপারেটরটির দিকে তাকান, অ্যাসাইনমেন্টের দিক থেকে ভাবেন না। আপনি জিনিস বরাদ্দ না, আপনি তাদের আবদ্ধ। = একটি বাধ্যতামূলক অপারেটর।

সুতরাং আপনার কোডে, আপনি মান 1 একটি নাম দিচ্ছেন: ক। তারপরে, আপনি 'a' তে একটি নাম দিয়ে যাচ্ছেন: খ। তারপরে আপনি 'a' নামের সাথে মানটি 2 বেঁধে দিচ্ছেন। খ এর সাথে আবদ্ধ মানটি এই ক্রিয়াকলাপে পরিবর্তন হয় না।

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

পাশাপাশি নোট করুন যে হাস্কেলের মতো কার্যকরী ভাষাও দৃ para়তার সাথে এই দৃষ্টান্তটি ব্যবহার করে great


39
আপনি জানেন, আমি কয়েক ডজন বার এর মতো উত্তরগুলি পড়েছি এবং আমি এটি কখনই বুঝতে পারি নি। a = 1; b = a; a = 2;পাইথন, সি এবং জাভাতে হ'ল আচরণটি হুবহু এক b
নেড ব্যাচেল্ডার

4
আপনি জিনিস বরাদ্দ না। এজন্য এটিকে একটি অ্যাসাইনমেন্ট স্টেটমেন্ট বলা হয় । আপনি যে পার্থক্যটি উল্লেখ করছেন তা বোঝা যায় না। এবং এটি সংকলিত ভি। ব্যাখ্যায়িত বা স্থিতিশীল বনাম গতিশীল সঙ্গে কিছুই করার নেই। জাভা হ'ল স্ট্যাটিক টাইপ-চেকিং সহ একটি সংকলিত ভাষা এবং এর কোনও পয়েন্টারও নেই।
ম্যাথু ফ্ল্যাশেন

3
সি ++ এর কী হবে? "খ" হতে পারে "ক" এর একটি উল্লেখ হতে পারে। অ্যাসাইনমেন্ট এবং বাইন্ডিংয়ের মধ্যে পার্থক্য বোঝার জন্য মার্ক কেন তিনি যা করতে চান তা করতে পারেন না এবং পাইথনের মতো ভাষা কীভাবে ডিজাইন করা হয়েছে তা পুরোপুরি বুঝতে গুরুত্বপূর্ণ critical ধারণাগতভাবে (বাস্তবায়নের ক্ষেত্রে অগত্যা নয়), "a = 1" "এ" নামক মেমরির ব্লকটিকে 1 দিয়ে ওভাররাইট করে না; এটি ইতিমধ্যে বিদ্যমান অবজেক্ট "1" কে "a" নাম দেয়, যা সি এর মধ্যে ঘটে তার চেয়ে মূলত আলাদা That's এজন্যই ধারণা হিসাবে পয়েন্টার পাইথনে অস্তিত্ব রাখতে পারে না - তারা পরের বারে বাসি হয়ে উঠবে d আসল ভেরিয়েবলটি "এসাইন ওভার" হয়েছিল।
গ্লেন মেইনার্ড

1
@ ডাব্লু: আমি এটি সম্পর্কে চিন্তা করার এই পদ্ধতিটি পছন্দ করি! "বাঁধাই" একটি ভাল শব্দ। @Ned: আউটপুট একই, হ্যাঁ, কিন্তু সি "1" এর মান উভয় অনুলিপি করা হয়েছে aএবং bপাইথন মধ্যে যেহেতু, তারা উভয় পড়ুন করার একই "1" (আমি মনে করি)। সুতরাং, আপনি যদি 1 (মান হিসাবে) এর মান পরিবর্তন করতে পারেন, এটি ভিন্ন হবে। যা শুনে কিছু অদ্ভুত বক্সিং / আনবক্সিংয়ের সমস্যার মুখোমুখি হয় I
এমপেন

4
পাইথন এবং সি এর মধ্যে পার্থক্য "অ্যাসাইনমেন্ট" বলতে বোঝায় না। এটি "ভেরিয়েবল" এর অর্থ কী।
dan04

28

হ্যাঁ! পাইথনে পয়েন্টার হিসাবে ভেরিয়েবল ব্যবহার করার উপায় আছে!

আমি দুঃখিত যে অনেক উত্তর আংশিক ভুল ছিল। নীতিগতভাবে প্রতিটি সমান (=) অ্যাসাইনমেন্ট মেমরি ঠিকানা ভাগ করে (আইডি (আপত্তি) ফাংশন পরীক্ষা করে দেখুন), তবে বাস্তবে এটি এমন নয়। এমন ভেরিয়েবল রয়েছে যার সমান ("=") আচরণ মেমরি স্পেসের অনুলিপি হিসাবে শেষ পর্বে কাজ করে, বেশিরভাগ সাধারণ বস্তুগুলিতে (যেমন "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

পয়েন্টার অ্যাসাইনমেন্ট অতিরিক্ত মেমোরির অপচয় না করে aliasing করার জন্য বেশ কার্যকর সরঞ্জাম, নির্দিষ্ট পরিস্থিতিতে কমফাই কোড সম্পাদনের জন্য,

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, ...) হয় এবং কিছুগুলির মধ্যে পয়েন্টার থাকে যখন তাদের মধ্যে নির্ধারিত হয় (যেমন ডিক্ট = = ডিক্ট 2)। কিভাবে তাদের চিনতে হবে? তাদের সাথে এই পরীক্ষার চেষ্টা করুন। ভেরিয়েবল এক্সপ্লোরার প্যানেল সহ আইডিইগুলিতে পয়েন্টার-মেকানিজম অবজেক্টগুলির সংজ্ঞাতে সাধারণত মেমরি ঠিকানা ("@axbbbbbb ...") বলে মনে হয়।

আমি বিষয়টিতে তদন্তের পরামর্শ দিচ্ছি। এমন অনেক লোক আছেন যারা নিশ্চিতভাবে এই বিষয়টি সম্পর্কে আরও অনেক কিছু জানেন। ("সিটিপস" মডিউলটি দেখুন)। আমি এটা সহায়ক আশা করি। বস্তুর ভাল ব্যবহার উপভোগ করুন! শুভেচ্ছা, জোসে ক্রেসপো


সুতরাং আমি একটি ফাংশন রেফারেন্স দ্বারা একটি ভেরিয়েবল পাস করার জন্য একটি অভিধান ব্যবহার করতে হবে, এবং আমি কোন int বা একটি স্ট্রিং ব্যবহার করে রেফারেন্স দিয়ে একটি ভেরিয়েবল পাস করতে পারি না?
সাম

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কেবল দুটি পৃথক নাম যা একই অপরিবর্তনীয় বস্তুর (ইন্ট) উল্লেখ করে 1। তাহলে তোমার সাথে পরে লিখতে a = 2, আপনি নাম reassign 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
আইডি ফাংশন প্রবর্তনের জন্য ধন্যবাদ। এটি আমার সন্দেহের অনেক সমাধান করে।

12

এক দৃষ্টিকোণ থেকে, পাইথন-এ সমস্ত কিছু পয়েন্টার। আপনার উদাহরণটি সি ++ কোডের মতো অনেক কাজ করে।

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

এটি পাইথন পয়েন্টার (সি / সি ++ এর থেকে আলাদা)

>>> 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 টি।

এইভাবে বিশ্বব্যাপী নেমস্পেসের সাথে জগাখিচুড়ি করা স্বচ্ছভাবে এক ভয়ঙ্কর ধারণা, তবে এটি দেখায় যে ওপি যা চেয়েছিল তা করা সম্ভব (যদি অপ্রয়োজনীয়) হয়।

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

যদিও এটি দেখতে অনেকটা সি বা সি ++ পয়েন্টারের মতো দেখাচ্ছে না, এটি এমন একটি সমস্যার সমাধান করছে যা আমি সি ++ এ লিখতে চাইলে পয়েন্টারগুলির সাথে সমাধান করতাম।


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

আমি মনে করি আপনি সবেমাত্র একটি অদ্ভুত উপায়ে মানগুলি বাক্স করেছেন।
এমপেন

আপনার অর্থ: একটি "চালাক উপায়" বা "চালাক নয়"?
মাইকটেক্স

আহ ... আমি একটি র্যান্ডম সংখ্যার দ্বারা সূচিত বিশ্বব্যাপী স্টোরেজটির জন্য একটি বৈধ ব্যবহারের কেসটি দেখতে লড়াই করছি।
এমপেন

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

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