পাইথনে অভিধান থেকে বৈশিষ্ট্যগুলি সেট করুন


102

পাইথনের অভিধান থেকে এমনভাবে কোনও অবজেক্ট তৈরি করা সম্ভব যে প্রতিটি কী সেই বস্তুর একটি বৈশিষ্ট্য?

এটার মতো কিছু:

 d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

 e = Employee(d) 
 print e.name # Oscar 
 print e.age + 10 # 42 

আমি মনে করি এটি এই প্রশ্নের বিপরীতমুখী হতে হবে: কোনও বস্তুর ক্ষেত্র থেকে পাইথন অভিধান

উত্তর:


172

অবশ্যই, এরকম কিছু:

class Employee(object):
    def __init__(self, initial_data):
        for key in initial_data:
            setattr(self, key, initial_data[key])

হালনাগাদ

ব্রেন্ট ন্যাশের পরামর্শ অনুসারে, আপনি কীওয়ার্ড আর্গুমেন্টগুলিকেও অনুমতি দিয়ে এটিকে আরও নমনীয় করতে পারেন:

class Employee(object):
    def __init__(self, *initial_data, **kwargs):
        for dictionary in initial_data:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])

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

e = Employee({"name": "abc", "age": 32})

বা এই মত:

e = Employee(name="abc", age=32)

বা এমনকি এটি পছন্দ:

employee_template = {"role": "minion"}
e = Employee(employee_template, name="abc", age=32)

4
আপনি যদি প্রাথমিক উপাত্ত পাস করেন তবে আপনি def __init__(self,**initial_data)ডিআইডি পদ্ধতির অতিরিক্ত সুবিধা পেয়ে যা কীওয়ার্ড আর্গুমেন্টগুলিও করতে পারে (উদাঃ "ই = কর্মচারী (নাম = 'অস্কার'))" বা কেবল অভিধানে নিন (যেমন "ই = কর্মচারী ( ** ডিক্ট) ")।
ব্রেন্ট লিখেছেন কোড

2
Employee(some_dict)এবং Employee(**some_dict)API গুলি উভয়ই অফুরন্ত নয়। যা ভাল তা সরবরাহ করা উচিত।
মাইক গ্রাহাম

4
আপনাকে আপনার ARG ডিফল্ট সেট করেন তাহলে ()পরিবর্তে None, আপনি এটা এত পছন্দ কর পারে: def __init__(self, iterable=(), **kwargs): self.__dict__.update(iterable, **kwargs)
ম্যাট অ্যান্ডারসন

4
আমি জানি এটি পুরানো প্রশ্ন, তবে আমি কেবল যুক্ত করতে চাই যে এটি তালিকা বোঝার সাথে দুটি লাইনে করা যেতে পারে, উদাহরণস্বরূপ:[[setattr(self,key,d[key]) for key in d] for d in some_dict]
TZ

2
আমি কেন জানতে চাই যে এটি কিছু সাধারণ উপায়ে অজগর হিসাবে তৈরি করা হয়নি। আমি পাইথন জিওআইপি 2 এপিআই নিক্ষেপকারীদের সাথে ঝুঁকির সাথে মোকাবিলা করার জন্য এটি ব্যবহার করছি AddressNotFoundError(এই ক্ষেত্রে সঠিক তথ্য ফিরিয়ে দেওয়ার পরিবর্তে ফুঁপিয়ে ফেলার জন্য) - আমি এটি পাগল পেয়েছি যে পিএইচপি-তে খুব সহজ কিছু ( (object) ['x' => 'y']) পাইথনে এত
ক্রাফ্টের দরকার পড়েছিল

46

এইভাবে বৈশিষ্ট্য নির্ধারণ করা কোনও সমস্যা সমাধানের প্রায় সেরা উপায় নয়। উভয় ক্ষেত্রেই:

  1. সময়ের আগে সমস্ত ক্ষেত্র কী হওয়া উচিত তা আপনি জানেন। সেক্ষেত্রে আপনি সমস্ত বৈশিষ্ট্য স্পষ্টভাবে সেট করতে পারেন। এই মত দেখতে হবে

    class Employee(object):
        def __init__(self, name, last_name, age):
            self.name = name
            self.last_name = last_name
            self.age = age
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(**d) 
    
    print e.name # Oscar 
    print e.age + 10 # 42 

    অথবা

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

    class Employee(object):
        def __init__(self, data):
            self.data = data
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(d) 
    
    print e.data['name'] # Oscar 
    print e.data['age'] + 10 # 42 

মূলত কেস 1 এর সমতুল্য আরেকটি সমাধান হ'ল ব্যবহার করা collections.namedtuple। কীভাবে এটি প্রয়োগ করা যায় তার জন্য ভ্যানের উত্তর দেখুন।


এবং যদি দৃশ্যটি আপনার দুটি চূড়ান্ততার মাঝে থাকে? এটি হ'ল এটির জন্য ব্যবহারের কেস এবং এটিএফআইসিটি বর্তমানে কোনও DRY এবং পাইথোনিক উপায়ে এটি করার কোনও উপায় নেই।
ডিলান ইয়ং

14

আপনি এর সাথে কোনও অবজেক্টের বৈশিষ্ট্যগুলি অ্যাক্সেস করতে __dict__এবং এতে আপডেট পদ্ধতির কল করতে পারেন:

>>> class Employee(object):
...     def __init__(self, _dict):
...         self.__dict__.update(_dict)
... 


>>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

>>> e = Employee(dict)

>>> e.name
'Oscar'

>>> e.age
32

3
__dict__এটি একটি বাস্তবায়ন নিদর্শন এবং ব্যবহার করা উচিত নয়। এছাড়াও, এটি ক্লাসে বর্ণনাকারীদের অস্তিত্বকে উপেক্ষা করে।
ইগনাসিও ওয়াজকেজ-আব্রামস

1
@ ইগনাসিও "বাস্তবায়ন নিদর্শন" বলতে আপনার অর্থ কী? আমাদের কী তা সচেতন হওয়া উচিত নয়? বা এটি বিভিন্ন প্ল্যাটফর্মে উপস্থিত নাও হতে পারে? (উদাঃ উইন্ডোজের পাইথন বনাম লিনাক্সে পাইথন) একটি গ্রহণযোগ্য উত্তর কী হবে?
অস্কাররাইজ

12
__dict__ভাষার একটি নথিভুক্ত অংশ, বাস্তবায়ন শৈলী নয়।
ডেভ কার্বি

3
সরাসরি setattrঅ্যাক্সেস ব্যবহার করা পছন্দনীয় __dict__। আপনাকে অনেকগুলি বিষয় মনে রাখতে হবে __dict__যা আপনি যখন ব্যবহার করবেন তখন যা চান তা না করার কারণ হতে পারে না __dict__, তবে setattrবাস্তবে করার মতো কার্যত অভিন্ন foo.bar = baz
মাইক গ্রাহাম

1
@ ডেভকির্বি: মনে হচ্ছে এটির সাধারণ ব্যবহারের __dict__বিরুদ্ধে পরামর্শ দেওয়া হচ্ছে: ডকস.পিথন.আর
স্লাসস

10

কেন কেবল অভিধানের কী হিসাবে বিশিষ্ট নামগুলি ব্যবহার করবেন না?

class StructMyDict(dict):

     def __getattr__(self, name):
         try:
             return self[name]
         except KeyError as e:
             raise AttributeError(e)

     def __setattr__(self, name, value):
         self[name] = value

আপনি নামযুক্ত আর্গুমেন্ট, টিপলসের একটি তালিকা, বা একটি অভিধান, বা পৃথক বৈশিষ্ট্যযুক্ত কার্যাদি, যেমন:

nautical = StructMyDict(left = "Port", right = "Starboard") # named args

nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary

nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list

nautical4 = StructMyDict()  # fields TBD
nautical4.left = "Port"
nautical4.right = "Starboard"

for x in [nautical, nautical2, nautical3, nautical4]:
    print "%s <--> %s" % (x.left,x.right)

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


7

আমি মনে করি যে উত্তরটি ব্যবহার settattrকরেই যদি আপনার সত্যিকারের সমর্থন প্রয়োজন হয় তবে যাবেন dict

তবে যদি Employeeঅবজেক্টটি কেবল এমন কাঠামো হয় যা আপনি .nameডিক সিনট্যাক্স ( ['name']) এর পরিবর্তে ডট সিনট্যাক্স ( ) দিয়ে অ্যাক্সেস করতে পারেন তবে আপনি নামটির মতো এটি ব্যবহার করতে পারেন :

from collections import namedtuple

Employee = namedtuple('Employee', 'name age')
e = Employee('noname01', 6)
print e
#>> Employee(name='noname01', age=6)

# create Employee from dictionary
d = {'name': 'noname02', 'age': 7}
e = Employee(**d)
print e
#>> Employee(name='noname02', age=7)
print e._asdict()
#>> {'age': 7, 'name': 'noname02'}

আপনার কাছে _asdict()অভিধান হিসাবে সমস্ত বৈশিষ্ট্য অ্যাক্সেস করার পদ্ধতি রয়েছে তবে আপনি কেবল নির্মাণের সময় অতিরিক্ত গুণাবলী যুক্ত করতে পারবেন না


6

উদাহরণস্বরূপ বলুন

class A():
    def __init__(self):
        self.x=7
        self.y=8
        self.z="name"

আপনি একবারে বৈশিষ্ট্য সেট করতে চান

d = {'x':100,'y':300,'z':"blah"}
a = A()
a.__dict__.update(d)

1
আপনি সুবিধার জন্য কী / মান ব্যবহার করতে পারেন:a.__dict__.update(x=100, y=300, z="blah")
9

1

ডিক ব্যবহারের অনুরূপ, আপনি ঠিক তেমন কাওয়ার্গ ব্যবহার করতে পারেন:

class Person:
   def __init__(self, **kwargs):
       self.properties = kwargs

   def get_property(self, key):
       return self.properties.get(key, None)

   def main():
       timmy = Person(color = 'red')
       print(timmy.get_property('color')) #prints 'red'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.