একটি বস্তুর ক্ষেত্র থেকে পাইথন অভিধান


342

আপনি কি জানেন যে কোনও স্বেচ্ছাচারিত বস্তু থেকে অভিধান তৈরি করার জন্য কোনও অন্তর্নির্মিত ফাংশন রয়েছে কিনা? আমি এরকম কিছু করতে চাই:

>>> class Foo:
...     bar = 'hello'
...     baz = 'world'
...
>>> f = Foo()
>>> props(f)
{ 'bar' : 'hello', 'baz' : 'world' }

দ্রষ্টব্য: এটিতে পদ্ধতিগুলি অন্তর্ভুক্ত করা উচিত নয়। কেবল ক্ষেত্র।

উত্তর:


421

দ্রষ্টব্য যে পাইথন ২.7-এ সেরা অনুশীলন হ'ল নতুন-স্টাইলের ক্লাসগুলি (পাইথন 3 এর সাথে প্রয়োজনীয় নয়) ব্যবহার করা

class Foo(object):
   ...

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

>>> class A(object):
...   def __init__(self):
...     self.b = 1
...     self.c = 2
...   def do_nothing(self):
...     pass
...
>>> a = A()
>>> a.__dict__
{'c': 2, 'b': 1}

একটি ভাল পদ্ধতির (দ্বারা প্রস্তাবিত রবার্ট মন্তব্য) builtin হয় varsফাংশন:

>>> vars(a)
{'c': 2, 'b': 1}

বিকল্পভাবে, আপনি যা করতে চান তার উপর নির্ভর করে উত্তরাধিকার সূত্রে উত্তম হতে পারে dict। তারপরে আপনার ক্লাসটি ইতিমধ্যে একটি অভিধান এবং আপনি যদি চান তবে আপনি ওভাররাইড করতে পারেন getattrএবং / অথবা setattrকল করে ডিকটি সেট করতে পারেন। উদাহরণ স্বরূপ:

class Foo(dict):
    def __init__(self):
        pass
    def __getattr__(self, attr):
        return self[attr]

    # etc...

3
যদি এ এর ​​বৈশিষ্ট্যগুলির মধ্যে একটিতে কাস্টম গেটার থাকে তবে কী হবে? (@ প্রপার্টি ডেকরেটার সহ একটি ফাংশন)? এটি কি এখনও _______________ প্রদর্শিত হয়? এর মূল্য কী হবে?
জাকদানস

11
__dict__যদি বস্তু স্লট (বা সি মডিউলে সংজ্ঞায়িত) ব্যবহার করে তবে কাজ করবে না।
এন্টিমোনি

1
শ্রেণি অবজেক্টের জন্য কি এই পদ্ধতির সমতুল্য? IE এর পরিবর্তে f = Foo () ব্যবহার করুন এবং তারপরে f .__ ڈک__, সরাসরি Foo করুন __ ডিক__?
শিফায়

49
দুঃখিত, আমি এই দেরীতে আসছি, তবে এটি করা উচিত নয় vars(a)? আমার পক্ষে __dict__সরাসরি ডাকা ভাল fe
রবার্ট

2
দ্বিতীয় উদাহরণের জন্য __getattr__ = dict.__getitem__আচরণটির প্রতিলিপি তৈরির জন্য আরও ভাল করা উচিত , তবে আপনি এটিও চান __setattr__ = dict.__setitem__এবং __delattr__ = dict.__delitem__সম্পূর্ণ নেছের জন্য।
তাধগ ম্যাকডোনাল্ড-জেনসেন

140

পরিবর্তে x.__dict__এটি ব্যবহার করার জন্য এটি আসলে আরও অজগর vars(x)


3
একমত। নোট করুন যে আপনি MyClass(**my_dict)শ্রেণীর বৈশিষ্ট্যগুলি মিরর করে এমন কোনও প্যারামিটার দিয়ে একটি কনস্ট্রাক্টরকে সংজ্ঞায়িত করেছেন ধরে ধরেও টাইপ করে আপনি অন্য উপায়ে (ডিক্ট>> শ্রেণি) রূপান্তর করতে পারেন । ব্যক্তিগত বৈশিষ্ট্য অ্যাক্সেস বা ডিকাকে ওভাররাইড করার দরকার নেই।
tvt173

2
কেন আপনি এটি আরও পাইথোনিক ব্যাখ্যা করতে পারেন?
হিউ ডাব্লু

1
প্রথমত, পাইথন সাধারণত কলিংস ডান্ডার আইটেমগুলি সরাসরি বন্ধ করে দেয় এবং এটিকে পরোক্ষভাবে অ্যাক্সেস করার জন্য প্রায়শই কোনও পদ্ধতি বা ফাংশন (বা অপারেটর) থাকে। সাধারণভাবে, জঘন্য বৈশিষ্ট্য এবং পদ্ধতিগুলি একটি বাস্তবায়নের বিশদ এবং "র‍্যাপার" ফাংশনটি আপনাকে দুটি পৃথক করতে দেয়। দ্বিতীয়ত, আপনি varsফাংশনটিকে ওভাররাইড করতে পারেন এবং অবজেক্টটি নিজেই পরিবর্তন না করে অতিরিক্ত কার্যকারিতা প্রবর্তন করতে পারেন ।
বেরিসালভ লোপাক

1
এটি এখনও ব্যর্থ হয় যদি আপনার শ্রেণি __slots__যদিও ব্যবহার করে ।
সিজেড

এটি সঠিক, এবং আমি সর্বদা অনুভব করি যে এটি প্রসারিত varsকরা, অর্থাৎ __dict__"স্লটেড" শ্রেণীর সমমানের ফেরত দেওয়া ভাল দিক হতে পারে । আপাতত, এটি এমন __dict__সম্পত্তি যুক্ত করে অনুকরণ করা যেতে পারে যা প্রত্যাবর্তন করে {x: getattr(self, x) for x in self.__slots__}(যদিও এটি কোনওভাবেই কার্যকারিতা বা আচরণকে প্রভাবিত করে কিনা তা নিশ্চিত নয়)।
বেরিসালভ লোপাক

59

dirBuiltin আপনি সব বস্তুর বৈশিষ্ট্যাবলী মত বিশেষ পদ্ধতি সহ দেব __str__, __dict__এবং অন্যদের যা আপনি সম্ভবত চাই না আভা। তবে আপনি এর মতো কিছু করতে পারেন:

>>> class Foo(object):
...     bar = 'hello'
...     baz = 'world'
...
>>> f = Foo()
>>> [name for name in dir(f) if not name.startswith('__')]
[ 'bar', 'baz' ]
>>> dict((name, getattr(f, name)) for name in dir(f) if not name.startswith('__')) 
{ 'bar': 'hello', 'baz': 'world' }

সুতরাং এটি আপনার propsফাংশনটিকে এভাবে সংজ্ঞায়িত করে কেবলমাত্র ডেটা বৈশিষ্ট্যগুলি না ফেরার পদ্ধতিগুলিতে প্রসারিত করতে পারে :

import inspect

def props(obj):
    pr = {}
    for name in dir(obj):
        value = getattr(obj, name)
        if not name.startswith('__') and not inspect.ismethod(value):
            pr[name] = value
    return pr

1
এই কোড পদ্ধতি অন্তর্ভুক্ত। পদ্ধতিগুলি বাদ দেওয়ার কোনও উপায় আছে কি? আমার কেবলমাত্র অবজেক্টের ক্ষেত্রগুলি দরকার। ধন্যবাদ
জুলিও সিজার

ismethodফাংশন ধরেনা উদাহরণ: inspect.ismethod(str.upper)inspect.isfunctionযদিও এর চেয়ে বেশি সহায়ক নয়। এখনই কীভাবে এটি পৌঁছানো যায় তা নিশ্চিত নয়।
এহতেশ চৌধুরী

অসম্পূর্ণভাবে পুনরাবৃত্তি করতে এবং এখানে সমস্ত ত্রুটি গভীরতার সাথে উপেক্ষা করার জন্য আমি কিছু টুইট করেছি, ধন্যবাদ! gist.github.com/thorsummoner/bf0142fd24974a0ced778768a33a3069
থারস্মমনার

26

আমি উভয় উত্তরের সংমিশ্রণে স্থির করেছি:

dict((key, value) for key, value in f.__dict__.iteritems() 
    if not callable(value) and not key.startswith('__'))

এটিও কাজ করে, তবে সচেতন থাকুন যে এটি কেবল ক্লাসে নয়, উদাহরণের ভিত্তিতে নির্ধারিত বৈশিষ্ট্যগুলি দেবে (যেমন আপনার উদাহরণে ক্লাস
ফুও

সুতরাং, jcarrascal, আপনি প্রপস () এর মতো কোনও ফাংশনে উপরের কোডটি মোড়ানো থেকে ভাল, তবে আপনি প্রপস (চ) বা প্রপস (ফু) কল করতে পারেন। লক্ষ্য করুন যে আপনি 'ইনলাইন' কোড লেখার চেয়ে ফাংশন লেখার চেয়ে প্রায় সবসময়ই ভাল are
কোমরানা

সুন্দর, বিটিডব্লু নোট এটি পাইথন 2.7 এর জন্য, পাইথন 3 রেলপেস ইটারাইটেমস () জন্য কেবল আইটেম () সহ।
মর্টেন

আর কি staticmethod? এটা না callable
অ্যালেক্স

17

আমি ভেবেছিলাম আপনি কীভাবে কোনও জিনিসকে ডিকের মাধ্যমে অনুবাদ করতে পারেন তা দেখানোর জন্য আমি কিছুটা সময় নেব dict(obj)

class A(object):
    d = '4'
    e = '5'
    f = '6'

    def __init__(self):
        self.a = '1'
        self.b = '2'
        self.c = '3'

    def __iter__(self):
        # first start by grabbing the Class items
        iters = dict((x,y) for x,y in A.__dict__.items() if x[:2] != '__')

        # then update the class items with the instance items
        iters.update(self.__dict__)

        # now 'yield' through the items
        for x,y in iters.items():
            yield x,y

a = A()
print(dict(a)) 
# prints "{'a': '1', 'c': '3', 'b': '2', 'e': '5', 'd': '4', 'f': '6'}"

এই কোডের মূল বিভাগটি হ'ল __iter__ফাংশন।

মতামতগুলি যেমন ব্যাখ্যা করে, প্রথম জিনিসটি আমরা ক্লাসের আইটেমগুলি ধরে আছি এবং '__' দিয়ে শুরু হওয়া কোনও কিছু রোধ করি।

এটি তৈরি করার dictপরে আপনি updateডিক ফাংশনটি ব্যবহার করতে পারেন এবং উদাহরণটি পাস করতে পারেন__dict__

এটি আপনাকে সদস্যদের একটি সম্পূর্ণ ক্লাস + উদাহরণ অভিধান দেবে। এখন যা আছে তা হ'ল তাদের উপর পুনরাবৃত্তি হবে এবং ফলাফলগুলি অর্জন করবে।

এছাড়াও, আপনি যদি এটি প্রচুর ব্যবহার করার পরিকল্পনা করে থাকেন তবে আপনি একটি @iterableশ্রেণি সাজসজ্জা তৈরি করতে পারেন ।

def iterable(cls):
    def iterfn(self):
        iters = dict((x,y) for x,y in cls.__dict__.items() if x[:2] != '__')
        iters.update(self.__dict__)

        for x,y in iters.items():
            yield x,y

    cls.__iter__ = iterfn
    return cls

@iterable
class B(object):
    d = 'd'
    e = 'e'
    f = 'f'

    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        self.c = 'c'

b = B()
print(dict(b))

এটি সমস্ত পদ্ধতিও গ্রহণ করবে তবে আমাদের কেবল শ্রেণি + উদাহরণ ক্ষেত্রের প্রয়োজন। হয়ত dict((x, y) for x, y in KpiRow.__dict__.items() if x[:2] != '__' and not callable(y))সমাধান করবে? তবে এখনও staticপদ্ধতিগুলি থাকতে পারে :(
অ্যালেক্স

15

একটি স্বেচ্ছাসেবী বস্তু থেকে অভিধান তৈরি করতে , এটি ব্যবহারের পক্ষে যথেষ্ট __dict__

এটি সেই বৈশিষ্ট্যগুলি বাদ দেয় যা বস্তুটি তার শ্রেণি থেকে উত্তরাধিকার সূত্রে আসে। উদাহরণ স্বরূপ,

class c(object):
    x = 3
a = c()

hasattr (a, 'x') সত্য, তবে 'x' a .__ ڈک__ তে উপস্থিত হয় না


এক্ষেত্রে এর সমাধান কী? যেহেতু vars()কাজ করে না
21_19

এক্ষেত্রে সমাধানটি dirহ'ল @ শোল্ড_বে_কর্মিং । সে সম্পর্কে অন্যান্য উত্তর দেখুন।
অ্যালবার্ট

8

দেরিতে উত্তর তবে সম্পূর্ণতা এবং গুগলারের সুবিধার জন্য সরবরাহ করা হয়েছে:

def props(x):
    return dict((key, getattr(x, key)) for key in dir(x) if key not in dir(x.__class__))

এটি ক্লাসে সংজ্ঞায়িত পদ্ধতিগুলি প্রদর্শন করবে না, তবে এটি ল্যাম্বডাসকে অর্পণ করা ক্ষেত্রগুলি বা ডাবল আন্ডারস্কোর দিয়ে শুরু হওয়া অঞ্চলগুলি সহ এখনও ক্ষেত্রগুলি প্রদর্শন করবে।


6

আমি মনে করি সহজতম উপায় হ'ল ক্লাসের জন্য একটি গাইটাইটম অ্যাট্রিবিউট তৈরি করা । আপনার যদি অবজেক্টটিতে লেখার দরকার পড়ে তবে আপনি একটি কাস্টম সেট্যাট্র্টার তৈরি করতে পারেন । এখানে গেটিটমের উদাহরণ রয়েছে :

class A(object):
    def __init__(self):
        self.b = 1
        self.c = 2
    def __getitem__(self, item):
        return self.__dict__[item]

# Usage: 
a = A()
a.__getitem__('b')  # Outputs 1
a.__dict__  # Outputs {'c': 2, 'b': 1}
vars(a)  # Outputs {'c': 2, 'b': 1}

ডিক একটি অভিধানে অবজেক্ট অ্যাট্রিবিউটস তৈরি করে এবং অভিধানের জিনিসটি আপনার প্রয়োজনীয় আইটেমটি পেতে ব্যবহার করা যেতে পারে।


এই উত্তরের পরে এখনও কোনও জিনিস থেকে অভিধান কীভাবে পাওয়া যায় তা পরিষ্কার নয়। বৈশিষ্ট্য নয়, পুরো অভিধান;)
ম্যাক্সকরিউকোভ

6

ব্যবহারের একটি খারাপ দিক __dict__ এটি অগভীর; এটি কোনও সাবক্লাসকে অভিধানে রূপান্তর করবে না।

আপনি যদি পাইথন 3.5 বা তার বেশি ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন jsons:

>>> import jsons
>>> jsons.dump(f)
{'bar': 'hello', 'baz': 'world'}

3

আপনি যদি নিজের বৈশিষ্ট্যের অংশ তালিকা করতে চান তবে ওভাররাইড করুন __dict__:

def __dict__(self):
    d = {
    'attr_1' : self.attr_1,
    ...
    }
    return d

# Call __dict__
d = instance.__dict__()

আপনার যদি instanceকিছু বড় ব্লক ডেটা পাওয়া যায় এবং আপনি dরেডিসে বার্তার সারিটির মতো চাপ দিতে চান তবে এটি অনেকটা সহায়তা করে ।


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

0

অজগর 3:

class DateTimeDecoder(json.JSONDecoder):

   def __init__(self, *args, **kargs):
        JSONDecoder.__init__(self, object_hook=self.dict_to_object,
                         *args, **kargs)

   def dict_to_object(self, d):
       if '__type__' not in d:
          return d

       type = d.pop('__type__')
       try:
          dateobj = datetime(**d)
          return dateobj
       except:
          d['__type__'] = type
          return d

def json_default_format(value):
    try:
        if isinstance(value, datetime):
            return {
                '__type__': 'datetime',
                'year': value.year,
                'month': value.month,
                'day': value.day,
                'hour': value.hour,
                'minute': value.minute,
                'second': value.second,
                'microsecond': value.microsecond,
            }
        if isinstance(value, decimal.Decimal):
            return float(value)
        if isinstance(value, Enum):
            return value.name
        else:
            return vars(value)
    except Exception as e:
        raise ValueError

এখন আপনি নিজের শ্রেণীর ভিতরে উপরের কোড ব্যবহার করতে পারেন:

class Foo():
  def toJSON(self):
        return json.loads(
            json.dumps(self, sort_keys=True, indent=4, separators=(',', ': '), default=json_default_format), cls=DateTimeDecoder)


Foo().toJSON() 

0

vars() দুর্দান্ত, তবে নেস্টেড অবজেক্ট অবজেক্টের জন্য কাজ করে না

নেস্টেড অবজেক্টের অবজেক্টকে ডিকে রূপান্তর করুন:

def to_dict(self):
    return json.loads(json.dumps(self, default=lambda o: o.__dict__))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.