কমপক্ষে পাঁচটি ছয়টি উপায় রয়েছে। পছন্দসই উপায়টি আপনার ব্যবহারের ক্ষেত্রে কী হবে তার উপর নির্ভর করে।
বিকল্প 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)
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)
{'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]
version: InitVar[str] = "old"
def __post_init__(self, sum, version):
self.sum = 6
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-র মতো হাঁসের ধরণের স্ট্যান্ডার্ড "নাম" হয়ে গেছে