[TIL 1/3] getattr, setattr, hasattr, delattr 사용법 & 활용

김경민·2023년 1월 10일
0

TIL

목록 보기
12/15
post-thumbnail

getattr, setattr, hasattr, delattr 사용법 & 활용

getattr : 속성값, 메서드 가져오기

getattr(객체, 속성 이름 [, 속성이 없을 때 반환 값])

getattr(...)
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case.

예제

class 통장:
    def __init__(self, 개설_축하_금액):
        """통장 개설!!ㅊㅊ"""
        self.통장액수 = 개설_축하_금액
        
    def 입금(self, 입금액):
        self.통장액수 += 입금액
        
    def 출금(self, 출금액):
        self.통장액수 -= 출금액
  • 사용자에게서 입금 출금의 행위를 입력 받고 금액도 입력 받아보겠다.

몸이 힘들어질 수도 있는 방법

테스트_통장 = 통장(5000)
x = input('입금 or 출금?') # 입금
y = input('얼마나?')
테스트_통장.x(int(y)) # SyntaxError, 테스트_통장."입금"(int(5000))
  • x는 "입금" 혹은 "출금"으로 들어온다고 했을 때, if문을 사용한다면 아래와 같이 할 수 있을 것이다.
if x == '입금':
    return 테스트_통장.입금(int(y))
elif x == '출금':
    return 테스트_통장.출금(int(y))
  • 하지만 입금, 출금만 있는게 아니라 입입금과 출출금 등 새로운 메서드들을 추가한다고 생각하면 if문이 계속 늘어날 것이다.
  • 이렇게 나누는 분기가 명확하다면 getattr을 사용해 보자

확장하기 편해지는 방법

x = input('입금 or 출금?') # 입금
y = input('얼마나?')
func = getattr(테스트_통장, x) # 테스트_통장."입금" >>> 테스트_통장.입금
func(int(y))

setattr()

getattr(객체, 속성 이름, 지정 값)

setattr(obj, name, value, /)
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
  • object에 새로운 속성을 추가하고 값은 value로 줍니다.

hasattr()

hasattr(객체, 속성 이름)

hasattr(obj, name, /)
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
  • 속성이 있는지 True False로 반환합니다. getattr 혹은 setattr 시에 유효성 검사를 할 수도 있겠죵?
  • if not hasattr(테스트_통장, x): return "입력 제대로!";

delattr()

delattr(객체, 속성 이름)

delattr(obj, name, /)
    Deletes the named attribute from the given object.
    
    delattr(x, 'y') is equivalent to ``del x.y''
  • 객체의 속성을 지웁니다.

활용하기(까리하고 편리하게, 개인용)

페이히어 기업과제로 가계부를 만들기를 받았다. django를 사용했고,

지출에 해당하는 것만 구현하면 됐지만, 상세 내용에 수입/지출의 값을 넣고 싶었다. 또한 일별 총 수입/지출의 값을 넣으려 설계했다.

그러기 위해서 상세 내용의 수입/지출 내역을 쓰면 일별 수입/지출 또한 바뀌어야했다.

그래서 생성/삭제 시에 변경되는 값을 바꾸기 위해 아래와 같이 만들었는데 getattr과 setattr을 사용하면 확장성 있게 바뀔 수 있겠다.

바꾸기 전

def add_income_expense(self, instance):
    money_type = instance.money_type
    is_expense = True if money_type == '0' else False

    if is_expense:
        instance.day_log.expense += instance.money
    else:
        instance.day_log.income += instance.money

def sub_income_expense(self, instance):
    money_type = instance.money_type
    is_expense = True if money_type == '0' else False

    if is_expense:
        instance.day_log.expense -= instance.money
    else:
        instance.day_log.income -= instance.money
        

바꾼 후

func_dict = {
    "add" : lambda x,y : x+y,
    "sub" : lambda x,y : x-y,
}
money_type = {
    "0" : "expense",
    "1" : "income"
}

def add_or_sub_income_expense(self, instance, op):
    
    money_type = instance.money_type
    func = func_dict[op]
    x = getattr(instance.day_log, money_type[money_type])
    money = func(x, instance.money)
    
    setattr(instance.day_log, income_or_expoense[money_type], money)
  • 눈에 한번에 잘 들어오는 것은 바꾸기 전이긴 하다. 하지만 상황에 따라 다르겠지만 확장성은 아래가 더 좋을지도?

나아가서..

  • django를 사용하고 있는데 model이나 serializer에서 저장 시 자동적으로 업데이트가 될 수 있게 만들 수 있을건데 뭐가 더 괜찮을지는 생각을 해봐야겠당
profile
적은 대로 된다.

0개의 댓글