파이썬의 사전에서 속성 설정


답변:


172

물론입니다.

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

최신 정보

Brent Nash가 제안한 것처럼 키워드 인수도 허용하여 더 유연하게 만들 수 있습니다.

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)키워드 인수도 수행 할 수있는 init 메서드 (예 : "e = Employee (name = 'Oscar')"를 사용할 수있는 추가 이점을 얻을 때 초기 데이터를 전달 하거나 사전 (예 : "e = Employee ( ** dict) ").
Brent,

2
Employee(some_dict)Employee(**some_dict)API를 모두 제공하는 것은 일관성이 없습니다. 어느 쪽이든 더 나은 것이 제공되어야합니다.
Mike Graham

4
인수의 기본값을 ()대신 으로 설정하면 다음 None과 같이 할 수 def __init__(self, iterable=(), **kwargs): self.__dict__.update(iterable, **kwargs)있습니다.
Matt Anderson

4
나는 그것이 오래된 질문이라는 것을 알고 있지만, 목록 이해력을 사용하여 두 줄로 할 수 있다고 덧붙이고 싶습니다. 예를 들면 :[[setattr(self,key,d[key]) for key in d] for d in some_dict]
TZ

2
왜 이것이 파이썬에 간단한 방식으로 내장되지 않았는지 알고 싶습니다. 나는 이것을 사용하여 python GeoIP2 API 던지기를 처리하고 있습니다. AddressNotFoundError(이 경우 수정 된 데이터를 반환하기 위해)-PHP ( (object) ['x' => 'y']) 에서 너무 쉬운 일 이 Python에서 너무 많은
찌그러짐을

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. 모든 필드가 미리 무엇인지 알 수 없습니다. 이 경우 개체 네임 스페이스를 오염시키는 대신 데이터를 dict로 저장해야합니다. 속성은 정적 액세스를위한 것입니다. 이 경우는 다음과 같습니다.

    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. 구현 방법은 van의 답변을 참조하십시오.


시나리오가 두 극단 사이 어딘가에 있다면 어떻게 될까요? 이것이 바로 이것에 대한 유스 케이스이며, 현재 AFAICT는 DRY와 파이썬 방식으로 이것을 할 방법이 없습니다.
DylanYoung

15

를 사용하여 객체의 속성에 액세스하고 해당 객체에 __dict__대한 update 메서드를 호출 할 수 있습니다.

>>> 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__구현 아티팩트이며 사용해서는 안됩니다. 또한 이것은 클래스에 대한 설명 자의 존재를 무시합니다.
Ignacio Vazquez-Abrams

1
@Ignacio "구현 아티팩트"란 무엇을 의미합니까? 우리가 인식하지 말아야 할 것은 무엇입니까? 아니면 다른 플랫폼에 존재하지 않을 수 있습니까? (예 : Windows의 Python vs. Linux의 Python) 어떤 대답이 허용됩니까?
OscarRyz

12
__dict__구현 아티팩트가 아니라 언어의 문서화 된 부분입니다.
Dave Kirby

3
사용 setattr__dict__직접 액세스하는 것보다 것이 좋습니다 . 당신은 __dict__거기에 있지 않거나 당신이 그것을 사용할 때 당신이 원하는 것을하지 않을 수있는 많은 것들을 염두에 두어야합니다 __dict__. 그러나 setattr실제로하는 것과 거의 동일합니다 foo.bar = baz.
Mike Graham

1
@DaveKirby : 그것은의 일반적인 사용 보인다 __dict__:에 좋습니다 docs.python.org/tutorial/classes.html#id2을
equaeghe

11

속성 이름을 사전의 키로 사용하지 않는 이유는 무엇입니까?

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)

또는 속성 오류를 발생시키는 대신 알 수없는 값에 대해 None을 반환 할 수 있습니다. (web2py 스토리지 클래스에서 사용되는 트릭)


7

settattr정말 지원이 필요한 경우 사용하는 대답 이 갈 길이 라고 생각합니다 dict.

그러나 Employeeobject가 .namedict 구문 ( ['name']) 대신 도트 구문 ( )으로 액세스 할 수있는 구조 일 경우 namedtuple을 사용할 수 있습니다. 과 같이 .

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")
simno

1

dict를 사용하는 것과 비슷하게 kwargs를 다음과 같이 사용할 수 있습니다.

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.