একটি অজগর শ্রেণি যা ডিকের মতো কাজ করে


113

আমি এমন একটি কাস্টম ক্লাস লিখতে চাই যা এর মতো আচরণ করে dict- তাই, আমি উত্তরাধিকার সূত্রে পেয়েছি dict

যদিও আমার প্রশ্নটি হ'ল: dictআমার __init__()পদ্ধতিতে কি আমাকে কোনও ব্যক্তিগত সদস্য তৈরি করা দরকার ?. আমি এর বিন্দুটি দেখতে পাচ্ছি না, যেহেতু dictযদি আমি কেবল উত্তরাধিকার সূত্রে পাই তবে আমার ইতিমধ্যে আচরণ রয়েছে dict

যেহেতু বেশিরভাগ উত্তরাধিকার স্নিপেটগুলি নীচের অংশের মতো দেখাচ্ছে কেন কেউ চিহ্নিত করতে পারেন?

class CustomDictOne(dict):
   def __init__(self):
      self._mydict = {} 

   # other methods follow

সরল পরিবর্তে ...

class CustomDictTwo(dict):
   def __init__(self):
      # initialize my other stuff here ...

   # other methods follow

প্রকৃতপক্ষে, আমি মনে করি যে আমি প্রশ্নের উত্তরটি সন্দেহ করি যাতে ব্যবহারকারীরা সরাসরি আপনার অভিধানে অ্যাক্সেস করতে না পারে (যেমন তাদের দেওয়া অ্যাক্সেসের পদ্ধতিগুলি তাদের ব্যবহার করতে হবে)।

তবে অ্যারে অ্যাক্সেস অপারেটরের []কী হবে? কীভাবে কেউ এটি বাস্তবায়ন করবে? এখনও অবধি, আমি এমন একটি উদাহরণ দেখিনি যা দেখায় যে কীভাবে []অপারেটরকে ওভাররাইড করা যায় ।

সুতরাং যদি []কাস্টম ক্লাসে কোনও অ্যাক্সেস ফাংশন সরবরাহ না করা হয়, উত্তরাধিকারসূত্রে প্রাপ্ত বেস পদ্ধতিগুলি কোনও আলাদা অভিধানে কাজ করবে?

পাইথনের উত্তরাধিকার সম্পর্কে আমার উপলব্ধি পরীক্ষা করার জন্য আমি নিম্নলিখিত স্নিপেটটি চেষ্টা করেছি:

class myDict(dict):
    def __init__(self):
        self._dict = {}

    def add(self, id, val):
        self._dict[id] = val


md = myDict()
md.add('id', 123)
print md[id]

আমি নিম্নলিখিত ত্রুটি পেয়েছি:

কী-এরর: <অন্তর্নির্মিত ফাংশন আইডি>

উপরের কোডটিতে কী ভুল?

আমি ক্লাসটি কীভাবে সংশোধন করব myDictযাতে আমি এই জাতীয় কোড লিখতে পারি?

md = myDict()
md['id'] = 123

[সম্পাদনা]

আমি আমার ডেস্ক থেকে দূরে সরে যাওয়ার আগে তৈরি করা নিরীহ ত্রুটি থেকে মুক্তি পেতে উপরের কোডের নমুনাটি সম্পাদনা করেছি। এটি একটি টাইপো ছিল (আমার এটির ত্রুটি বার্তা থেকে স্পট করা উচিত ছিল)।

উত্তর:



105
class Mapping(dict):

    def __setitem__(self, key, item):
        self.__dict__[key] = item

    def __getitem__(self, key):
        return self.__dict__[key]

    def __repr__(self):
        return repr(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

    def __delitem__(self, key):
        del self.__dict__[key]

    def clear(self):
        return self.__dict__.clear()

    def copy(self):
        return self.__dict__.copy()

    def has_key(self, k):
        return k in self.__dict__

    def update(self, *args, **kwargs):
        return self.__dict__.update(*args, **kwargs)

    def keys(self):
        return self.__dict__.keys()

    def values(self):
        return self.__dict__.values()

    def items(self):
        return self.__dict__.items()

    def pop(self, *args):
        return self.__dict__.pop(*args)

    def __cmp__(self, dict_):
        return self.__cmp__(self.__dict__, dict_)

    def __contains__(self, item):
        return item in self.__dict__

    def __iter__(self):
        return iter(self.__dict__)

    def __unicode__(self):
        return unicode(repr(self.__dict__))


o = Mapping()
o.foo = "bar"
o['lumberjack'] = 'foo'
o.update({'a': 'b'}, c=44)
print 'lumberjack' in o
print o

In [187]: run mapping.py
True
{'a': 'b', 'lumberjack': 'foo', 'foo': 'bar', 'c': 44}

37
আপনি যদি সাবক্লাসে চলে যাচ্ছেন dict, তবে superকেবলমাত্র উদাহরণটির কাছে অর্পণ করার পরিবর্তে আপনাকে অবজেক্টটি নিজেই ব্যবহার করা উচিত ( __dict__যার অর্থ) - যার অর্থ হ'ল আপনি প্রতিটি উদাহরণের জন্য দুটি ডিক্ট তৈরি করছেন।
হারুন হলের

8
স্ব .__ dict__ হয় না প্রকৃত অভিধান সামগ্রী হিসাবে একই। প্রতিটি পাইথন অবজেক্ট, তার প্রকার নির্বিশেষে একটিতে _dict__রয়েছে যাতে সমস্ত অবজেক্ট বৈশিষ্ট্য (পদ্ধতি, ক্ষেত্র ইত্যাদি) রয়েছে। আপনাকে যা না এই সঙ্গে প্রায় জগাখিচুড়ি করতে চান, যদি না আপনি ... লেখার কোড চাই যে নিজেই পরিবর্তন হয়
Raik

85

এটার মত

class CustomDictOne(dict):
   def __init__(self,*arg,**kw):
      super(CustomDictOne, self).__init__(*arg, **kw)

এখন আপনি dict.get()যেমন বিল্ট-ইন ফাংশনগুলি ব্যবহার করতে পারেন self.get()

আপনার কোনও লুকানো জড়ানোর দরকার নেই self._dict। আপনার বর্গ ইতিমধ্যে হয় একটি অভি।


3
এই. dictপ্রথমে এর কনস্ট্রাক্টরকে কল না করে উত্তরাধিকার সূত্রে কোনও লাভ নেই ।
সিকোড়া

1
মনে রাখবেন যে আপনার উত্তরাধিকারসূত্রে dictআসলে ২ টি ডিক্ট-উদাহরণ রয়েছে: 1 ম হ'ল উত্তরাধিকার সূত্রে প্রাপ্ত ধারক এবং দ্বিতীয়টি হ'ল শ্রেণি-বৈশিষ্ট্যযুক্ত হ'ল - আপনি স্লট ব্যবহার করে এড়াতে পারেন ।
ankostis

1
এটি কেবল __dict__তখনই তৈরি করা হয় যখন এটি প্রথম অ্যাক্সেস করা হয়, তাই যতক্ষণ না ব্যবহারকারীরা এটি ব্যবহার করার চেষ্টা না করেন, ঠিক আছে। __slots__যদিও ভাল হবে।
অ্যারন হল

9
আপনি ক্ষয়ক্ষতি কমা পরে স্পেস ব্যবহার করুন! ;-)
জেমস বার্ক

10

সম্পূর্ণতার স্বার্থে, সর্বশেষ পাইথন ২.x (লেখার সময় অনুযায়ী ২.7..7) এর জন্য @ বিজন-পোলেক্স দ্বারা উল্লিখিত ডকুমেন্টেশনের লিঙ্কটি এখানে রয়েছে:

অনুকরণকারী ধারক প্রকারের

(মন্তব্য ফাংশনটি ব্যবহার না করার জন্য দুঃখিত, স্ট্যাকওভারফ্লো দ্বারা আমাকে কেবল এটি করার অনুমতি দেওয়া হচ্ছে না))


3

কোডটির এই অংশটি নিয়ে সমস্যা:

class myDict(dict):
    def __init__(self):
        self._dict = {}

    def add(id, val):
        self._dict[id] = val


md = myDict()
md.add('id', 123)

... এটি হ'ল আপনার 'অ্যাড' পদ্ধতিটি (... এবং যে কোনও পদ্ধতিতে আপনি কোনও শ্রেণীর সদস্য হতে চান) এর একটি স্পষ্ট 'স্ব' তার প্রথম যুক্তি হিসাবে ঘোষণা করা দরকার যেমন:

def add(self, 'id', 23):

কী দ্বারা আইটেমগুলি অ্যাক্সেস করতে অপারেটরকে ওভারলোডিং বাস্তবায়নের জন্য, যাদু পদ্ধতিগুলির জন্য ডক্সে__getitem__ এবং দেখুন __setitem__

নোট করুন যেহেতু পাইথন হাঁসের টাইপিং ব্যবহার করে, তাই আপনার কাস্টম ডিক শ্রেণীটি ভাষার ডিক ক্লাস থেকে প্রাপ্ত করার কোনও কারণ থাকতে পারে না - আপনি কী করার চেষ্টা করছেন সে সম্পর্কে আরও অজানা (উদাহরণস্বরূপ, যদি আপনাকে এটির কোনও উদাহরণ পাস করতে হয় তবে) এমন কোনও কোডে ক্লাস করা হবে যা ভেঙে যাবে না isinstance(MyDict(), dict) == True), আপনি কেবলমাত্র এমন API টি প্রয়োগ করতে পারেন যা আপনার ক্লাসকে পর্যাপ্ত ডিকের মতো করে তোলে এবং সেখানে থামিয়ে দেয়।


3

এখানে একটি বিকল্প সমাধান:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__dict__ = self

a = AttrDict()
a.a = 1
a.b = 2

এটি খারাপ কারণ আপনি কোনও কাস্টম পদ্ধতি সংজ্ঞায়িত করেন না এবং অন্যান্য উত্তর যেমন বলেছে তেমন অন্যান্য সমস্যাও রয়েছে।
শীতল শাহ

এই আমার প্রয়োজন ঠিক কি। ধন্যবাদ!
জ্যাকব্রিংকম্যান

2

আমি সত্যিই এর সঠিক উত্তর কোথাও দেখতে পাচ্ছি না

class MyClass(dict):
    
    def __init__(self, a_property):
        self[a_property] = a_property

আপনার সত্যিকারের যা করা দরকার তা হ'ল আপনার নিজের সংজ্ঞাটি __init__- এটি যা যা আছে তা আসলে এটি।

আরেকটি উদাহরণ (আরও জটিল):

class MyClass(dict):

    def __init__(self, planet):
        self[planet] = planet
        info = self.do_something_that_returns_a_dict()
        if info:
            for k, v in info.items():
                self[k] = v

    def do_something_that_returns_a_dict(self):
        return {"mercury": "venus", "mars": "jupiter"}

আপনি যখন কোনও ধরণের যুক্তি এম্বেড করতে চান তবে এই শেষ উদাহরণটি কার্যকর।

যাইহোক ... সংক্ষেপে class GiveYourClassAName(dict)আপনার শ্রেণি অভিনয়কে ডিকের মতো করার জন্য যথেষ্ট। আপনি যে কোনও ডিক অপারেশন করেন selfতা ঠিক নিয়মিত ডিকের মতোই হবে।


1

এটি আমার সেরা সমাধান। আমি এটি বহুবার ব্যবহার করেছি।

class DictLikeClass:
    ...
    def __getitem__(self, key):
        return getattr(self, key)

    def __setitem__(self, key, value):
        setattr(self, key, value)
    ...

আপনি যেমন ব্যবহার করতে পারেন:

>>> d = DictLikeClass()
>>> d["key"] = "value"
>>> print(d["key"])

0

পাইথন অন্তর্নির্মিত ডিক থেকে উত্তরাধিকারী হন না, কখনও! উদাহরণস্বরূপ updateপদ্ধতিটি ব্যবহার করে না __setitem__, তারা অপ্টিমাইজেশনের জন্য অনেক কিছু করে। ইউজারডিক্ট ব্যবহার করুন।

from collections import UserDict

class MyDict(UserDict):
    def __delitem__(self, key):
        pass
    def __setitem__(self, key, value):
        pass

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

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