পাইথন-এ, আমি কীভাবে কোনও ডিকের জন্য কোনও শ্রেণীর বস্তু নিক্ষেপ করব


89

ধরা যাক আমি পাইথনে একটি সাধারণ ক্লাস পেয়েছি

class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __what_goes_here__(self):
        return {'a': self.a, 'b': self.b, 'c': self.c}

আমি এটি খুব সহজেই একটি পূর্ণসংখ্যার কাছে কাস্ট করতে পারি

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> int(w)
9006

যা মহান! তবে, এখন আমি এটি একই ধরণের একটি ডিকের কাছে কাস্ট করতে চাই

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}

এটি কাজ করার জন্য আমার কী সংজ্ঞা দেওয়া দরকার? আমি উভয় __dict__এবং dictজন্য উভয় প্রতিস্থাপন চেষ্টা __what_goes_here__, কিন্তু উভয় ক্ষেত্রে dict(w)একটি ফলাফল TypeError: Wharrgarbl object is not iterable। আমি মনে করি না কেবল ক্লাসটিকে পুনরাবৃত্ত করার ফলে সমস্যার সমাধান হবে। আমি "পাইথন কাস্ট অবজেক্ট টু ডিক" এর বিচিত্র শব্দের সাথে অনেকগুলি গুগলের চেষ্টা করেছি তবে প্রাসঙ্গিক কিছু খুঁজে পাইনি: {

এছাড়াও! কল করুন কীভাবে কলিং w.__dict__আমি যা চাই তা করতে পারে না কারণ এটি ধারণ করে w.versionএবং w.sum। আমি কাস্টটিকে dictএকইভাবে কাস্টমাইজ করতে চাই যেভাবে আমি কাস্টটি intব্যবহার করে কাস্টমাইজ করতে পারি def int(self)

আমি জানি যে আমি এই জাতীয় কিছু করতে পারি

>>> w.__what_goes_here__()
{'a': 'one', 'c': 'three', 'b': 'two'}

তবে আমি ধরে নিচ্ছি যে dict(w)কাজটি করার এক অজগর উপায় আছে কারণ এটি একই ধরণের জিনিস int(w)বা হিসাবে str(w)। যদি আরও অজগর উপায় না হয়, এটি খুব ভাল, স্রেফ মনে হয়েছে আমি জিজ্ঞাসা করব। উহু! আমি অনুমান করি যেহেতু এটি গুরুত্বপূর্ণ, এটি অজগর ২.7 এর জন্য, তবে একটি সুপারিশ বোনাস পয়েন্ট ২.৪ পুরানো এবং ব্যস্টযুক্ত সমাধানের জন্যও।

পাইথন ক্লাসে ওভারলোডিং __ডিক্ট __ () রয়েছে যা এটির অনুরূপ তবে এটি সদৃশ না হওয়ার জন্য ওয়ারেন্ট দেওয়ার পক্ষে যথেষ্ট আলাদা হতে পারে। আমি বিশ্বাস করি যে ওপি কীভাবে তার শ্রেণীর অবজেক্টগুলিতে সমস্ত ডেটা অভিধান হিসাবে ফেলতে চাইছে। আমি আরও কাস্টমাইজড পদ্ধতির সন্ধান করছি __dict__যাতে অভিধানে অন্তর্ভুক্ত থাকা সমস্ত কিছুই আমি ফিরিয়ে দিতে চাই না dict()। সরকারী বনাম ব্যক্তিগত ভেরিয়েবলগুলির মতো কিছুতে আমি যা খুঁজছি তা ব্যাখ্যা করতে যথেষ্ট হতে পারে। অবজেক্টগুলি গণনাতে ব্যবহৃত কিছু মানগুলি সংরক্ষণ করবে এবং এরূপ যে ফলাফলের অভিধানগুলিতে আমার প্রয়োজন / দেখাতে চাই না।

আপডেট: আমি asdictপ্রস্তাবিত রুটটির সাথে যেতে বেছে নিয়েছি তবে আমি প্রশ্নের উত্তর কী হতে চাই তা নির্বাচন করা একটি কঠিন পছন্দ ছিল। @ রিকটিচি এবং @ জেএমপিসি 26 উভয়ই উত্তর দিয়েছিল যে আমি রোল করতে যাচ্ছি তবে প্রাক্তনটির আরও তথ্য এবং বিকল্প ছিল এবং একই ফলাফলে অবতীর্ণ হয়েছিল এবং আরও উত্সাহিত হয়েছিল তাই আমি এটির সাথে গিয়েছিলাম। যদিও চারদিকে উজ্জ্বল হন এবং সহায়তার জন্য ধন্যবাদ। আমি স্ট্যাকওভারফ্লোতে দীর্ঘ এবং কঠোরভাবে লুকিয়েছি এবং আমি আমার পায়ের আঙ্গুলগুলি আরও পানিতে পাওয়ার চেষ্টা করছি।


4
আপনি কি এটি ইতিমধ্যে দেখেছেন? docs.python.org/3/references/…
গ্যারেট আর

@ গ্যারেটআর এটি সহায়ক, তবে এটি এই বিশেষ সমস্যাটিতে সত্যিকার অর্থে প্রচুর অন্তর্দৃষ্টি প্রকাশ করে না।
Zizouz212


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

আপনার প্রশ্নটি বিভ্রান্তিকরভাবে বর্ণিত হয়েছে, আপনি নিজের বিষয়টিকে ডিকে উপস্থাপনার জন্য রূপান্তর করতে বা কাস্ট করতে চান না (যেমন আপনি যদি আবার রূপান্তর করেন তবে আপনি বস্তুটি পুরোপুরি পুনরুদ্ধার করতে পারেন)। আপনি কেবলমাত্র (যেমন) জনসাধারণের উদাহরণের ভেরিয়েবলগুলির জন্য একটি ডিক উপস্থাপনা ভিউ তৈরি করতে চান।
smci

উত্তর:


124

কমপক্ষে পাঁচটি ছয়টি উপায় রয়েছে। পছন্দসই উপায়টি আপনার ব্যবহারের ক্ষেত্রে কী হবে তার উপর নির্ভর করে।

বিকল্প 1: কেবল একটি asdict()পদ্ধতি যুক্ত করুন।

সমস্যার বর্ণনার ভিত্তিতে আমি asdictঅন্যান্য উত্তরগুলির দ্বারা প্রস্তাবিত জিনিসগুলি করার পদ্ধতিটি খুব বেশি বিবেচনা করব । এর কারণ এটি প্রদর্শিত হচ্ছে না যে আপনার অবজেক্টটি সত্যই সংগ্রহের অনেক বেশি:

class Wharrgarbl(object):

    ...

    def asdict(self):
        return {'a': self.a, 'b': self.b, 'c': self.c}

নীচের অন্যান্য বিকল্পগুলি ব্যবহার করা অন্যদের জন্য বিভ্রান্তিকর হতে পারে যদি না এটি খুব স্পষ্ট না হয় তবে কোন অবজেক্টের সদস্যরা পুনরাবৃত্তি করবেন না বা কী-মান জোড়া হিসাবে নির্দিষ্ট করবেন না।

বিকল্প 1 এ:'typing.NamedTuple' (বা বেশিরভাগ সমতুল্য 'collections.namedtuple') থেকে আপনার শ্রেণি উত্তরাধিকারী করুন এবং আপনার সরবরাহিত _asdictপদ্ধতিটি ব্যবহার করুন ।

from typing import NamedTuple

class Wharrgarbl(NamedTuple):
    a: str
    b: str
    c: str
    sum: int = 6
    version: str = 'old'

একটি _asdictপদ্ধতি সহ নূন্যতম প্রচেষ্টা সহ আপনার ক্লাসে প্রচুর কার্যকারিতা যুক্ত করার জন্য একটি নামযুক্ত টুপল ব্যবহার করা খুব সুবিধাজনক উপায় । যাইহোক, একটি সীমাবদ্ধতা হ'ল উপরে প্রদর্শিত হিসাবে, এনটি এতে সমস্ত সদস্যকে অন্তর্ভুক্ত করবে _asdict

এমন সদস্য যদি আপনি আপনার অভিধানে অন্তর্ভুক্ত করতে চান না, তবে আপনাকে _asdictফলাফলটি পরিবর্তন করতে হবে :

from typing import NamedTuple

class Wharrgarbl(NamedTuple):
    a: str
    b: str
    c: str
    sum: int = 6
    version: str = 'old'

    def _asdict(self):
        d = super()._asdict()
        del d['sum']
        del d['version']
        return d

আর একটি সীমাবদ্ধতা হ'ল এনটি কেবল পঠনযোগ্য। এটি পছন্দসই বা নাও হতে পারে।

বিকল্প 2: বাস্তবায়ন করুন __iter__

এটি পছন্দ করুন, উদাহরণস্বরূপ:

def __iter__(self):
    yield 'a', self.a
    yield 'b', self.b
    yield 'c', self.c

এখন আপনি ঠিক করতে পারেন:

dict(my_object)

এটি কাজ করে কারণ নির্মাণকারী একটি অভিধান তৈরি করতে dict()জোড়ের পুনরাবৃত্তিকে গ্রহণ করে (key, value)। এটি করার আগে, নিজেকে এই প্রশ্নটি জিজ্ঞাসা করুন যে কীটিকে সিরিজের কী হিসাবে এই উপাদানটি পুনরাবৃত্তি করা হবে - এই পদ্ধতিতে মান জোড়াসমূহ তৈরি করার পক্ষে সুবিধাজনক - তবে dictঅন্যান্য প্রসঙ্গে আসলে আশ্চর্যজনক আচরণ হতে পারে। উদাহরণস্বরূপ, নিজেকে প্রশ্ন জিজ্ঞাসা করুন "এর আচরণটি কী হওয়া উচিত list(my_object)...?"

অতিরিক্ত হিসাবে, নোট করুন যে সরাসরি আইটেম obj["a"]সিনট্যাক্স ব্যবহার করে মানগুলি অ্যাক্সেস করা কার্যকর হবে না এবং কীওয়ার্ড যুক্তি আনপ্যাকিংয়ের কাজ করবে না। তাদের জন্য, আপনাকে ম্যাপিং প্রোটোকলটি প্রয়োগ করতে হবে।

বিকল্প 3: ম্যাপিং প্রোটোকলটি প্রয়োগ করুন । এটি ব্যবহার না করে একটিতে ingালাই -দ্বারা-কী আচরণের অ্যাক্সেস করে এবং আনপ্যাকিং আচরণ সরবরাহ করে (dict__iter__{**my_obj} যদি সমস্ত কীগুলি স্ট্রিং হয় ( dict(**my_obj)) থাকে তবে ) এবং কীওয়ার্ড আনপ্যাকিং আচরণ সরবরাহ করে ।

ম্যাপিং প্রোটোকলের জন্য আপনি দুটি পদ্ধতি একসাথে (ন্যূনতম) সরবরাহ করতে হবে: keys()এবং __getitem__

class MyKwargUnpackable:
    def keys(self):
        return list("abc")
    def __getitem__(self, key):
        return dict(zip("abc", "one two three".split()))[key]

এখন আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

>>> m=MyKwargUnpackable()
>>> m["a"]
'one'
>>> dict(m)  # cast to dict directly
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)  # unpack as kwargs
{'a': 'one', 'b': 'two', 'c': 'three'}

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

>>> {**m}
{'a': 'one', 'b': 'two', 'c': 'three'}

মনে রাখবেন যে ম্যাপিং প্রোটোকল সরাসরি কোনও বস্তু কাস্ট করার সময় পদ্ধতির চেয়ে বেশি অগ্রাধিকার গ্রহণ করে (কোয়ার্গ আনপ্যাকিং ব্যবহার না করে, অর্থাত্ )। সুতরাং এটি possible- এবং কখনও কখনও convenient- হয় বস্তুর একটি iterable হিসাবে ব্যবহার কারণ বিভিন্ন আচরণ আছে (যেমন, ) বনাম যখন কাস্ট একটি ( )।__iter__dictdict(m)list(m)dictdict(m)

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

যদি এই প্রশ্নের উত্তর হ্যাঁ হয় হয় তবে পরবর্তী বিকল্পটি বিবেচনা করা সম্ভবত একটি ভাল ধারণা।

বিকল্প 4: 'collections.abc'মডিউলটি ব্যবহার করে দেখুন ।

আপনার ক্লাসটি অন্য ব্যবহারকারীদের কাছ থেকে নেওয়া 'collections.abc.Mappingবা 'collections.abc.MutableMappingসিগন্যাল করা যা সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে আপনার ক্লাসটি একটি ম্যাপিং * এবং আশা করা যায় যে সেভাবে আচরণ করা উচিত।

আপনার প্রয়োজন অনুসারে আপনি এখনও নিজের অবজেক্টটিকে কাস্ট করতে পারেন dict, তবে সম্ভবত এটি করার খুব কম কারণ থাকবে। হাঁসের টাইপিংয়ের কারণে, আপনার ম্যাপিং অবজেক্টটিকে একটিতে কাস্ট করতে বিরক্ত করা dictবেশিরভাগ সময়ের অতিরিক্ত অতিরিক্ত অপ্রয়োজনীয় পদক্ষেপ।

এই উত্তরটিও সহায়ক হতে পারে।

নীচের মন্তব্যে যেমন উল্লেখ করা হয়েছে: এটি উল্লেখ করার মতো বিষয় যে এইভাবে dictআব্বু পদ্ধতিটি করা আপনার অবজেক্ট শ্রেণিকে মূলত একটি পছন্দসই শ্রেণিতে পরিণত করে (ধরে নিচ্ছেন আপনি MutableMappingকেবলমাত্র পঠিত Mappingবেস শ্রেণিটি ব্যবহার করেন না )। আপনি যা করতে সক্ষম হবেন তা dictআপনি নিজের শ্রেণীর অবজেক্টের সাথে করতে পারেন। এটি কাঙ্ক্ষিত হতে পারে বা নাও হতে পারে।

numbersমডিউলে সংখ্যাসূচক অ্যাব্যাকগুলি দেখার বিষয়টিও বিবেচনা করুন :

https://docs.python.org/3/library/numbers.html

যেহেতু আপনি নিজের বস্তুটিকে intএকটিতেও intকাস্ট করছেন তাই এটি আপনার ক্লাসকে মূলত পূর্ণ পরিসরে পরিণত করা আরও বুদ্ধিমান হতে পারে যাতে কাস্টিং প্রয়োজন হয় না।

বিকল্প 5: dataclassesমডিউলটি ব্যবহার করার জন্য অনুসন্ধান করুন (কেবলমাত্র পাইথন 3.7), এতে সুবিধাজনক asdict()ইউটিলিটি পদ্ধতি অন্তর্ভুক্ত রয়েছে ।

from dataclasses import dataclass, asdict, field, InitVar

@dataclass
class Wharrgarbl(object):
    a: int
    b: int
    c: int
    sum: InitVar[int]  # note: InitVar will exclude this from the dict
    version: InitVar[str] = "old"

    def __post_init__(self, sum, version):
        self.sum = 6  # this looks like an OP mistake?
        self.version = str(version)

এখন আপনি এটি করতে পারেন:

    >>> asdict(Wharrgarbl(1,2,3,4,"X"))
    {'a': 1, 'b': 2, 'c': 3}

বিকল্প 6: ব্যবহার করুন typing.TypedDict, যা পাইথন 3.8 যোগ করা হয়েছে ।

উল্লেখ্য: বিকল্প 6 সম্ভাবনা থাকে না কি ওপি, কিংবা এই প্রশ্ন শিরোনাম ভিত্তিক অন্য পাঠক, খুঁজছেন। নীচে অতিরিক্ত মন্তব্য দেখুন।

class Wharrgarbl(TypedDict):
    a: str
    b: str
    c: str

এই অপশনটি ব্যবহার করে, ফলে বস্তুর একটি হলdict (: এটা জোর না একটি Wharrgarbl)। এটিকে কোনও ডিকের কাছে "কাস্ট" করার কোনও কারণ নেই (যদি আপনি অনুলিপি না দিয়ে থাকেন)।

এবং যেহেতু অবজেক্টটি একটিdict , তাই আরম্ভের স্বাক্ষরটি একই রকম dictএবং এটি কেবল কীওয়ার্ড আর্গুমেন্ট বা অন্য কোনও অভিধান গ্রহণ করে।

    >>> w = Wharrgarbl(a=1,b=2,b=3)
    >>> w
    {'a': 1, 'b': 2, 'c': 3}
    >>> type(w)
    <class 'dict'>

জোর দেওয়া : উপরের "শ্রেণি" Wharrgarblআসলে মোটেই নতুন ক্লাস নয়। dictটাইপ চেকারের জন্য বিভিন্ন ধরণের ক্ষেত্রের সাথে টাইপযুক্ত বস্তু তৈরির জন্য এটি কেবল সিনট্যাকটিক চিনি ।

যেমন এই কোডটি আপনার কোডের পাঠকদের (এবং মাইপির মতো কোনও প্রকারের পরীক্ষককে) সংকেত দেওয়ার জন্য বেশ সুবিধাজনক হতে পারে যে এই জাতীয় কোনও dictবস্তুর নির্দিষ্ট মানের ধরণের নির্দিষ্ট কী থাকবে বলে আশা করা যায়।

তবে এর অর্থ আপনি উদাহরণস্বরূপ অন্যান্য পদ্ধতি যুক্ত করতে পারবেন না যদিও আপনি চেষ্টা করতে পারেন:

class MyDict(TypedDict):
    def my_fancy_method(self):
        return "world changing result"

... তবে এটি কার্যকর হবে না:

>>> MyDict().my_fancy_method()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'my_fancy_method'

* "ম্যাপিং" dict-র মতো হাঁসের ধরণের স্ট্যান্ডার্ড "নাম" হয়ে গেছে


4
ওপি যেভাবে প্রভাব পেতে পারে এটি পাওয়ার এটি একটি উপায়, তবে আপনার সম্ভবত এটি স্পষ্ট করা উচিত যে এর অন্যান্য প্রভাব রয়েছে, উদাহরণস্বরূপ for k, v in my_objectএছাড়াও সক্ষম করা হবে।
zwol

@ রিকটিচি আমি দেখতে পাচ্ছি আপনি এ্যাসডিক্ট পয়েন্ট দিয়ে কী চালাচ্ছেন। আমার অবশ্যই অবজেক্টগুলি আবৃত্তিযোগ্য হতে হবে না।
পেন্যান্ট

অন্যান্য লিংকটিপস: // স্ট্যাকওভারফ্লো / প্রশ্ন / ques১17১17 / স্পিথন-ডিকোরিয়াস-ফর্ম-অ্যানোবজেক্টস-ফিল্ডস-এ উল্লিখিত হিসাবে আমরা কেবল ভার্স ফাংশনটি কেন ব্যবহার করতে পারি। আমি কি এই প্রশ্নে কিছু মিস করছি?
ব্যবহারকারী

@user ওপি প্রশ্নের চেয়েছিলেন শুধুমাত্র সদস্যদের a, bএবং cমধ্যে dictvarsফাংশন বেশী যে চেয়েছিলেন করা হয় নি সহ বস্তু সদস্যদের সব একটি অভিধান আসতে হবে: sumএবং version। কিছু ক্ষেত্রে varsকাজ করবে তবে এটি আমার অভিজ্ঞতার মতো অলঙ্কার নয়। সাধারণত লোকেরা আরও স্পষ্ট করে বলে, "আমি এখন আমার অভিধানকে একটি অভিধানে ফেলছি" উদাহরণস্বরূপ obj.asdict()। সহ vars, এটি সাধারণত আরও কিছু obj_kwargs = vars(obj)অনুসরণ করে অনুসরণ করা হয় MyObject(**obj_kwargs)। অন্য কথায়: varsবেশিরভাগ অবজেক্ট অনুলিপি করতে ব্যবহৃত হয়।
মনিকাকে সমর্থন করে

যে পদ্ধতিটি ফিরে self.__dict__আসবে সে সম্পর্কে কীভাবে ?
ব্যবহারকারী 32882

19

এমন কোনও যাদু পদ্ধতি নেই যা আপনি যা চান তা করবে। উত্তরটি যথাযথভাবে নামকরণ করা হয়। মূলত অনুপ্রাণিত হয়ে asdictএকটি সরল রূপান্তরকরণের জন্য যুক্তিসঙ্গত পছন্দ । তবে আপনার পদ্ধতিতে স্পষ্টতই একটি বিশেষ যুক্তি থাকবে যা সেই নাম থেকে তাত্ক্ষণিকভাবে সুস্পষ্ট নাও হতে পারে; আপনি কেবলমাত্র শ্রেণীর রাজ্যের একটি উপসেট ফিরিয়ে দিচ্ছেন। আপনি যদি আরও কিছু ভার্বোজের নাম নিয়ে আসতে পারেন যা ধারণাগুলি স্পষ্টভাবে জানিয়ে দেয়, আরও ভাল।dictnamedtuple

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


হ্যাঁ, শ্রেণীর পুরো রাজ্যের একটি উপসেট ফিরিয়ে দেওয়া, প্রাসঙ্গিকতার মানগুলি যা আমি অর্জন করার চেষ্টা করছি। আমার কাছে কিছু "লুকানো" মান সঞ্চিত আছে যা গণনা / তুলনা ইত্যাদির জন্য জিনিসগুলিকে দ্রুত করে তোলে তবে এগুলি এমন কোনও কিছুই নয় যা কোনও মানুষ দেখতে বা খেলতে চায় এবং এগুলি সত্যই বস্তুটির প্রতিনিধিত্ব করে না।
পেন্যান্ট

@ tr3buchet আপনার উদাহরণ কোড, যারা মান সূচনাকারী জন্য পাস করতে । এটি কি আপনার আসল কোডে সেভাবেই আছে? এটি অদ্ভুত বলে মনে হচ্ছে ক্যাশেড গণনাগুলি আর্গুমেন্ট হিসাবে পাস করা হবে।
jpmc26

না সব সময়ে, আমি শুধু একটি উদাহরণ প্রদান এরকম ছিল
ঝোঁক

কেবলমাত্র এটি লক্ষ করতে চাই যে ডক্সগুলি__iter__ অন্যান্য উত্তরের মতামত ব্যবহার করে সাদৃশ্যপূর্ণ বলে মনে হচ্ছে : "ম্যাপিংয়ের জন্য এটি ধারকটির কীগুলির দ্বারা পুনরাবৃত্তি হওয়া উচিত এবং এটি পদ্ধতি পদ্ধতি () হিসাবেও উপলব্ধ করা উচিত।"
dbenton

@dbenton ওপি যা করছে তা নয় বা অন্যান্য উত্তরগুলি কী সুপারিশ করছে। ওপি'র অবজেক্টটি কোনও "ধারক" নয়, যা এই প্রসঙ্গে মূলত সংগ্রহের প্রতিশব্দ হিসাবে ব্যবহৃত হচ্ছে। ওপির অবজেক্টটি ম্যাপিং দ্বারা সাধারণত বোঝানো হয় না। একটি ম্যাপিং এমন একটি জিনিস যা কী এবং মানগুলির একটি স্বেচ্ছাসেবী সংখ্যা থাকে এবং এটি Mappingবেস শ্রেণিকে প্রসারিত করে । নির্দিষ্ট কোনও নামযুক্ত বৈশিষ্ট্যযুক্ত কোনও বস্তু এই বিভাগে আসে না।
jpmc26

11

এই জাতীয় কিছু সম্ভবত কাজ করবে

class MyClass:
    def __init__(self,x,y,z):
       self.x = x
       self.y = y
       self.z = z
    def __iter__(self): #overridding this to return tuples of (key,value)
       return iter([('x',self.x),('y',self.y),('z',self.z)])

dict(MyClass(5,6,7)) # because dict knows how to deal with tuples of (key,value)

ওহ আকর্ষণীয়! টিউপসগুলির একটি পুনরাবৃত্ত, আমি এটি বিবেচনা করি নি। আমি একটি দ্রুত পরীক্ষা করব
পেন্যান্ট

এছাড়াও, x, y, এবং z এর সমস্ত মানকে যে তালিকার উপর ভিত্তি করে তৈরি করা হয়েছে তার তালিকায় স্ন্যাপশটের একটি তালিকার একটি ইটার ফিরিয়ে দেওয়া returning ক্ষেত্রে যদি 3 টি উত্পাদনের বিবৃতি দেওয়া থাকে তবে এটি সম্ভব (একটি ক্ষুদ্র উইন্ডো, তবে সেখানে) যে থ্রেডযুক্ত পরিবেশে এটি চালানোর ফলে অন্য থ্রেডের ফলে y বৈশিষ্ট্য বা z অ্যাট্রিবিউটকে পরিবর্তন করা যেতে পারে যা রিপোর্ট করা x, y এবং z সামঞ্জস্যপূর্ণ নয়।
PaulMcG

@ পলম্যাকগুইয়ার: সিপিথন কি গ্যারান্টি দেয় যে তারা সকলেই জোড়ানের কোডের সাথে সামঞ্জস্য থাকবে? আমি ভাবতাম যে অন্য থ্রেডটি নির্ধারিত হতে পারে, উদাহরণস্বরূপ, সাথে প্রথম টিপল xতৈরি হওয়ার পরে , তবে দ্বিতীয় টিপলের সাথে আগে y। আমি কি ভুল, এবং প্রকৃতপক্ষে তালিকা অনুধাবন থ্রেড শিডিংয়ের ক্ষেত্রে পারমাণবিক?
স্টিভ জেসোপ

এখন আপনি যা জিজ্ঞাসা করেছেন, আমি বুঝতে পেরেছি যে এমনকি পাইস্টনের থ্রেড সুইচারের উত্স স্তরের নয়, বাইটকোড স্তরে এটি করার ফলে তালিকা অনুধাবনও পারমাণবিকের গ্যারান্টিযুক্ত নয়। তবে আপনার এক্সপোজারটি কেবল তালিকা তৈরির সময়কালের জন্য - একবার তালিকা তৈরি হয়ে গেলে, বৈশিষ্ট্যগুলির কোনও আপডেটের বিষয়টি বিবেচনা করে না (সম্পত্তি বৈশিষ্ট্যগুলি পরিবর্তনযোগ্য বস্তু না হলে)। disআসল বাইকোডগুলি দেখতে মডিউলটি ব্যবহার করা সেরা ।
PaulMcG

11

আমি মনে করি এটি আপনার পক্ষে কাজ করবে।

class A(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

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

a = A(1,2,3,4,5)
print dict(a)

আউটপুট

a 'এ': 1, 'সি': 3, 'বি': 2, 'যোগ': 6, 'সংস্করণ': 5


যোগফল এবং সংস্করণ কি ঘটেছে? __dict__প্রস্তাবিত অন্যান্য উত্তরের মতো এটি অ্যাক্সেসের চেয়ে কীভাবে আলাদা ?
জোড়ান ব্যাসলি

এটা ডিক্ট নয় ইটারিটেমসে কলটি একটি পুনরাবৃত্তির ফেরত দেয়
গ্যারেট আর

4
আমি এই উত্তরটি পছন্দ করি ... তবে
ওপি'র

এই উত্তরটি সত্যই @ জোড়ানবিসলে থেকে আলাদা নয়। পার্থক্যটি হ'ল তিনি বাছাই করা হয়েছে তবে আপনার সামগ্রীতে গ্রাস করে self.__dict__যা আইটেমটির অভিধান সংস্করণে আমি চাই না contains
পেন্যান্ট

6

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

def to_dict(self):
    class_vars = vars(MyClass)  # get any "default" attrs defined at the class level
    inst_vars = vars(self)  # get any attrs defined on the instance (self)
    all_vars = dict(class_vars)
    all_vars.update(inst_vars)
    # filter out private attributes
    public_vars = {k: v for k, v in all_vars.items() if not k.startswith('_')}
    return public_vars

1

সমস্যার পুরো প্রসঙ্গটি না জেনে বলা শক্ত, তবে আমি ওভাররাইড করব না __iter__

আমি __what_goes_here__ক্লাসে প্রয়োগ করব ।

as_dict(self:
    d = {...whatever you need...}
    return d

না, যে কি ভেরিয়েবলের মধ্যে সংরক্ষণ করা হয়।
Zizouz212

4
আমি বিশেষভাবে উল্লেখ w.__dict__করেছি যে আমার যা প্রয়োজন তা করেন না।
পেন্যান্ট

তবে __dict__ওভাররাইড করা যায়, তাই না?
নয়েজ ওয়াটারফিড

@ নোয়েজ ওয়াটারফিড না এটি কোনও যাদু পদ্ধতি (সম্ভবত আপনি এটি ওভাররাইড করতে পারেন তবে এর অন্তত কিছুটা বলতে ভয় পাওয়া যায় না)
জোড়ান ব্যাসলি

4
ডিক থেকে উত্তরাধিকারী হোন না, বা সম্ভবত আরও ভাল, কেবল ডিক হিসাবে ফেরত দেওয়ার জন্য ক্লাসে একটি পদ্ধতি তৈরি করুন।
নয়েজ ওয়াটারফিড

0

আমি এমন একটি ক্লাস লিখার চেষ্টা করছি যা "উভয়" ক listবা এ dict। আমি চাই যে প্রোগ্রামার এই বস্তুকে একটি list(কীগুলি বাদ দিয়ে) বা "উভয়ই" কাস্ট করতে সক্ষম হবেdict ( ।

পাইথন যেভাবে বর্তমানে .ালাই করে dict(): এটি সেই পাসওয়ার্ডটির Mapping.update()সাথে কল করে। এটি পাইথন রেপোর কোড :

def update(self, other=(), /, **kwds):
    ''' D.update([E, ]**F) -> None.  Update D from mapping/iterable E and F.
        If E present and has a .keys() method, does:     for k in E: D[k] = E[k]
        If E present and lacks .keys() method, does:     for (k, v) in E: D[k] = v
        In either case, this is followed by: for k, v in F.items(): D[k] = v
    '''
    if isinstance(other, Mapping):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, "keys"):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value

If স্টেটমেন্টের সর্বশেষ সাবসকেসটি যেখানে এটি পুনরাবৃত্তি করে তা হল otherবেশিরভাগ লোকের মনে। তবে, আপনি দেখতে পাচ্ছেন, কোনও keys()সম্পত্তি থাকাও সম্ভব । এটির সাথে মিলিয়ে __getitem__()একটি সাবক্লাস একটি অভিধানে যথাযথভাবে কাস্ট করা সহজ হওয়া উচিত:

class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __keys__(self):
        return ["a", "b", "c"]

    def __getitem__(self, key):
        # have obj["a"] -> obj.a
        return self.__getattribute__(key)

তাহলে এটি কাজ করবে:

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}

আপনি ম্যাপিং প্রোটোকলটি কার্যকর করেছেন। উপরে আমার উত্তর 3 বিকল্প দেখুন । আপনি যদি listকীগুলি একটি __iter__ড্রপিংও করতে চান তবে আপনি একটি পদ্ধতি যুক্ত করতে পারেন যা মানগুলির মাধ্যমে পুনরাবৃত্তি করে এবং কাস্টিং dictএখনও কাজ চালিয়ে যাবে। নোট করুন যে অভিধানগুলির সাথে সাধারণত, আপনি যদি একটি তালিকায় কাস্ট করেন তবে এটি কেইওয়াইসকে ফিরিয়ে দেবে, আপনার প্রয়োজনীয় মানগুলি নয়। আপনার কোড ব্যবহার করা অন্য লোকের জন্য এটি অবাক করে দিতে পারে যদি না এটি কেন ঘটে তা স্পষ্ট না হয়।
রিক মনিকা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.