[PYTHON] 파이썬 : __getattr __ ()을 구현하는 방법?
PYTHON파이썬 : __getattr __ ()을 구현하는 방법?
내 수업은 예를 들어 :
class MyClass(object):
def __init__(self):
self.data = {'a': 'v1', 'b': 'v2'}
그런 다음 dict의 키를 MyClass 인스턴스와 함께 사용하여 dict에 액세스하려고합니다. 예를 들면 다음과 같습니다.
ob = MyClass()
v = ob.a # Here I expect ob.a returns 'v1'
이것이 __getattr__에 의해 구현되어야한다는 것을 알고 있지만 파이썬에 익숙하지는 않습니다. 구현 방법을 정확히 모르겠습니다.
해결법
-
==============================
1.
class MyClass(object): def __init__(self): self.data = {'a': 'v1', 'b': 'v2'} def __getattr__(self, attr): return self.data[attr]
>>> ob = MyClass() >>> v = ob.a >>> v 'v1'
__setattr__을 구현할 때는주의해야합니다. 몇 가지 수정을해야합니다.
class MyClass(object): def __init__(self): # prevents infinite recursion from self.data = {'a': 'v1', 'b': 'v2'} # as now we have __setattr__, which will call __getattr__ when the line # self.data[k] tries to access self.data, won't find it in the instance # dictionary and return self.data[k] will in turn call __getattr__ # for the same reason and so on.... so we manually set data initially super(MyClass, self).__setattr__('data', {'a': 'v1', 'b': 'v2'}) def __setattr__(self, k, v): self.data[k] = v def __getattr__(self, k): # we don't need a special call to super here because getattr is only # called when an attribute is NOT found in the instance's dictionary try: return self.data[k] except KeyError: raise AttributeError
>>> ob = MyClass() >>> ob.c = 1 >>> ob.c 1
속성을 설정할 필요가 없다면 namedtuple 만 사용하면된다. 예.
>>> from collections import namedtuple >>> MyClass = namedtuple("MyClass", ["a", "b"]) >>> ob = MyClass(a=1, b=2) >>> ob.a 1
기본 인수를 원하면 래퍼 클래스를 작성할 수 있습니다.
class MyClass(namedtuple("MyClass", ["a", "b"])): def __new__(cls, a="v1", b="v2"): return super(MyClass, cls).__new__(cls, a, b)
아니면 함수로 더 멋지게 보일 수도 있습니다.
def MyClass(a="v1", b="v2", cls=namedtuple("MyClass", ["a", "b"])): return cls(a, b)
>>> ob = MyClass() >>> ob.a 'v1'
-
==============================
2.파티에 늦어 지지만이 점을 더 잘 설명하는 두 가지 훌륭한 리소스를 발견했습니다 (IMHO).
파티에 늦어 지지만이 점을 더 잘 설명하는 두 가지 훌륭한 리소스를 발견했습니다 (IMHO).
http://western-skies.blogspot.com.br/2008/02/complete-example-of-getattr-in-python.html에서 설명한대로 self .__ dict__를 사용하여 __getattr__ 내에서 필드를 순서대로 액세스해야합니다 무한 재귀를 피할 수 있습니다. 제공된 예제는 다음과 같습니다.
참고 : 두 번째 줄 (위)에서 파이썬 적 방법이 더 있습니다 (has_key는 분명히 파이썬 3에서 삭제되었습니다).
if attrName not in self.__dict__:
다른 리소스 (http://farmdev.com/src/secrets/magicmethod/#introducing-getattr)는 __getattr__이 객체에 속성이없는 경우에만 호출되며, hasattr은 객체가있는 경우 항상 True를 반환한다고 설명합니다. __getattr__에 대한 구현. 다음 예제를 통해 데모를 제공합니다.
-
==============================
3.
class A(object): def __init__(self): self.data = {'a': 'v1', 'b': 'v2'} def __getattr__(self, attr): try: return self.data[attr] except: return "not found" >>>a = A() >>>print a.a v1 >>>print a.c not found
-
==============================
4.나는 이것을 받아들이고 싶다.
나는 이것을 받아들이고 싶다.
나는 어딘가에서 그것을 가져 갔지만, 나는 기억하지 않는다.
class A(dict): def __init__(self, *a, **k): super(A, self).__init__(*a, **k) self.__dict__ = self
이것은 속성과 항목 액세스가 동일한 dict에 매핑되도록 객체의 __dict__을 자체와 동일하게 만듭니다.
a = A() a['a'] = 2 a.b = 5 print a.a, a['b'] # prints 2 5
-
==============================
5.중첩 된 사전과 사전을 처리하는 @ glglgl의 대답이 원래 사전에있는 목록의 내부에 확장 된 것을 알아 냈습니다.
중첩 된 사전과 사전을 처리하는 @ glglgl의 대답이 원래 사전에있는 목록의 내부에 확장 된 것을 알아 냈습니다.
class d(dict): def __init__(self, *a, **k): super(d, self).__init__(*a, **k) self.__dict__ = self for k in self.__dict__: if isinstance(self.__dict__[k], dict): self.__dict__[k] = d(self.__dict__[k]) elif isinstance(self.__dict__[k], list): for i in range(len(self.__dict__[k])): if isinstance(self.__dict__[k][i], dict): self.__dict__[k][i] = d(self.__dict__[k][i])
-
==============================
6.생성자를 통해 클래스 사전을 초기화 할 수 있습니다.
생성자를 통해 클래스 사전을 초기화 할 수 있습니다.
def __init__(self,**data):
그리고 그것을 다음과 같이 부르십시오.
f = MyClass(**{'a': 'v1', 'b': 'v2'})
__setattr__에서 액세스 (읽기)되는 모든 인스턴스 속성은 부모 (수퍼) 메소드를 사용하여 한 번만 선언해야합니다.
super().__setattr__('NewVarName1', InitialValue)
또는
super().__setattr__('data', dict())
그런 다음 일반적인 방법으로 액세스하거나 할당 할 수 있습니다.
self.data = data
__setattr__에서 액세스되지 않는 인스턴스 속성은 일반적인 방식으로 선언 할 수 있습니다.
self.x = 1
재정의 된 __setattr__ 메소드는 이제 새 변수를 선언하기 위해 자체 내부의 부모 메소드를 호출해야합니다.
super().__setattr__(key,value)
완전한 수업은 다음과 같이 보일 것입니다 :
class MyClass(object): def __init__(self, **data): # The variable self.data is used by method __setattr__ # inside this class, so we will need to declare it # using the parent __setattr__ method: super().__setattr__('data', dict()) self.data = data # These declarations will jump to # super().__setattr__('data', dict()) # inside method __setattr__ of this class: self.x = 1 self.y = 2 def __getattr__(self, name): # This will callback will never be called for instance variables # that have beed declared before being accessed. if name in self.data: # Return a valid dictionary item: return self.data[name] else: # So when an instance variable is being accessed, and # it has not been declared before, nor is it contained # in dictionary 'data', an attribute exception needs to # be raised. raise AttributeError def __setattr__(self, key, value): if key in self.data: # Assign valid dictionary items here: self.data[key] = value else: # Assign anything else as an instance attribute: super().__setattr__(key,value)
테스트:
f = MyClass(**{'a': 'v1', 'b': 'v2'}) print("f.a = ", f.a) print("f.b = ", f.b) print("f.data = ", f.data) f.a = 'c' f.d = 'e' print("f.a = ", f.a) print("f.b = ", f.b) print("f.data = ", f.data) print("f.d = ", f.d) print("f.x = ", f.x) print("f.y = ", f.y) # Should raise attributed Error print("f.g = ", f.g)
산출:
f.a = v1 f.b = v2 f.data = {'a': 'v1', 'b': 'v2'} f.a = c f.b = v2 f.data = {'a': 'c', 'b': 'v2'} f.d = e f.x = 1 f.y = 2 Traceback (most recent call last): File "MyClass.py", line 49, in <module> print("f.g = ", f.g) File "MyClass.py", line 25, in __getattr__ raise AttributeError AttributeError
-
==============================
7.나는이 도구가 더 시원하다고 생각한다.
나는이 도구가 더 시원하다고 생각한다.
class MyClass(object): def __init__(self): self.data = {'a': 'v1', 'b': 'v2'} def __getattr__(self,key): return self.data.get(key,None)
from https://stackoverflow.com/questions/16237659/python-how-to-implement-getattr by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Python으로 구동되는 PhantomJS / Selenium의 CSS / 기타 리소스 다운로드 방지 (0) | 2018.11.02 |
---|---|
[PYTHON] 파이썬으로 UUID v1에서 시간 추출하기 (0) | 2018.11.02 |
[PYTHON] 판다 열 순서를 재 배열하는 방법? (0) | 2018.11.02 |
[PYTHON] matplotlib - 이미지를 변수에 저장 (0) | 2018.11.02 |
[PYTHON] "% s"% 형식과 "{0}". format () vs "?"형식 (0) | 2018.11.02 |