일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- wecode
- Jest
- 트랜잭션
- async/await
- OSI7계층
- Django
- bcrypt
- status code
- rebase
- 자바스크립트
- TypeError: this.boardRepository.createBoard is not a function
- manytomanyfield
- on_delete
- django westagram
- westagram
- 노드
- 스코프
- 실행 컨텍스트
- 호이스팅
- pm2
- javascript
- crud2
- nodeJS
- docker
- node
- CORS
- typescript
- JWT
- 장고초기세팅
- 프로미스
- Today
- Total
될때까지
Python 왓더@property? 본문
요새는 책이랑 유튜브를 같이 보면서 공부를 하고 있다. 깔끔한 파이썬 탄탄한 백엔드 책을 보면서 플라스크를, 유튜브 오지랖 파이썬을 보면서는 장고를 공부하고 있다. 백엔드 책을 보면서 이제까지 잘 따라가다가 mysql설치하고 실행하는 부분에서 계속 오류가 뜬다.. ERROR! The server quit without updating PID file (/usr/local/var/mysql/~~~~-MacBook-Pro-2019.local.pid) 구글링해서 나오는 해결법 다 해봤지만 여전히 실패 실패 실패. 스트레스 ^^ 이럴 땐 잠시 쉬었다가 다시 도전해야지.. 후 다시 해보면 또 될꺼야 힘내자!
@property # 응???? 너는 뭐니???
def coupon(self):
if self.coupon_id:
return Coupon.objects.get(id=self.coupon_id)
return None
def get_discount_total(self):
if self.coupon:
if self.get_product_total() >= self.coupon.amount:
return self.coupon.amount
return Decimal(0)
def get_total_price(self):
return self.get_product_total() - self.get_discount_total()
그렇게 답답했던 터미널과 flask는 치우고, 평화롭게 오지랖 파이썬 웹 프로그래밍 강의를 보며 장고 프로젝트를 따라하고 있었다. 근데 오늘은 너까지 왜그러니 근데 갑자기 등장한 @property... 너는 누구니? 영상에서도 깊게 설명을 해주지않았다. 그냥 원래는 coupon_id로 접근해야하는데 @property때문에 coupon이라고 쓸 수 있는거다라는 게 끝.. 😭 안돼요 저는 이게 뭔 지 모르는 걸요! 쿠폰으로 쓸 수 잇다니 이게 무슨 소리일까 궁금해서 유튜브, 책, 구글링 등 찾아보면서 내가 알아낸 부분들을 정리해보고자 한다. 잘 정리할 수... 있겠지?
먼저 @property를 이해하는 데 가장 큰 도움이 된 유튜브 링크 첨부!
class Employee:
def __init__(self, first, last):
self.first = first
self.last = last
self.email = first + '.' + last + '@email.com'
def fullname(self):
return '{} {}'.format(self.first, self.last)
emp_1 = Employee('John', 'Smith')
print(emp_1.first) # John
print(emp_1.email) # John.Smith@email.com
print(emp_1.fullname()) # John Smith
위에 첨부한 유튜브 영상를 보면서 배운 내용을 정리해보자. 먼저 Employee 클래스는 first, last를 받아 first, last, email을 정의한다. 그리고 fullname이란 메소드도 있는 데, 이 메소드는 전체 이름을 출력하는 역할을 담당한다. 각각 프린트문으로 출력을 해보면, 입력한 값이 그대로 잘 출력되는 걸 볼 수 있다.
그렇다면 emp_1객체를 생성하고 나서, John으로 입력했던 first를 변수에 직접 접근하여 Jim으로 바꿔보면 어떤 일이 일어날까?
emp_1 = Employee('John', 'Smith')
emp_1.first = 'Jim'
print(emp_1.first) # Jim
print(emp_1.email) # John.Smith@email.com
print(emp_1.fullname()) # Jim Smith
짜---잔!! emp_1.first와 emp_1.fullname()은 Jim으로 값이 잘 바뀌었지만, emp_1.email은 Jim이 아닌 John으로 출력된 걸 볼 수 있다. 메소드로 정의한 fullname은 현재의 first와 last의 값을 가져오기 때문에 문제가 없다. 우리가 first나 last의 값를 바꿀 때 마다 email을 매번 수동으로 바꿔줘야 한다니.. 이게 얼마나 귀찮은 일인가. 우리가 이름이나 성을 수정하면 이메일도 자동으로 업데이트되는 게 편하다. 그렇다면 fullname 메소드처럼 email도 메소드로 만들면 되지 않을까? email도 fullname처럼 메소드로 정의해보자.
class Employee:
def __init__(self, first, last):
self.first = first
self.last = last
# __init__메소드에서 정의한 email을 아래에 메소드로 새로 정의했다.
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
def fullname(self):
return '{} {}'.format(self.first, self.last)
emp_1 = Employee('John', 'Smith')
emp_1.first = 'Jim'
print(emp_1.first) # Jim
print(emp_1.email) # 에러 발생
print(emp_1.fullname())
__init__메소드에서 정의했던 email을 메소드로 새로 정의했다. 잘 실행되면 좋으련만.. 에러가 발생한다. email은 def를 붙여 우리가 함수로 변경해줬으니, 실행시에도 email이 아닌 email()로 호출을 해야한다.
emp_1 = Employee('John', 'Smith')
emp_1.first = 'Jim'
print(emp_1.first) # Jim
print(emp_1.email()) # Jim.Smith@email.com
print(emp_1.fullname()) # Jim Smith
그럼 John이였던 first가 Jim으로 잘 바뀐 걸 확인할 수 있다. 하지만 이 방법은 좋지 않다. 우리가 클래스 내부의 코드를 수정해버렸으므로, Employee 클래스를 사용하는 모든 곳에서도 코드 수정이 이루어져야한다. 오우 노.. 이 얼마나 좋지 않은 방법인가!? 저 괄호만 없앨 수 있다면 좋을텐데.. 저 괄호를 제거하고 속성처럼 이메일에 접근할 수 있는 방법이 없을까? 이럴때 property 데코레이터를 사용한다.
class Employee:
def __init__(self, first, last):
self.first = first
self.last = last
@property
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
def fullname(self):
return '{} {}'.format(self.first, self.last)
emp_1 = Employee('John', 'Smith')
emp_1.first = 'Jim'
print(emp_1.first) # Jim
print(emp_1.email) # Jim.Smith@email.com
print(emp_1.fullname()) # Jim Smith
클래스에서 이메일을 메소드로 정의했지만, 괄호없이 속성처럼 접근하여 실행이 제대로 이뤄지는 걸 볼 수 있다! 그러면 클래스를 쓰고 있는 다른 곳에서도 코드 수정할 필요가 없이 깔끔하게 해결이 된다. fullname메소드 역시 프로퍼티 데코레이터를 사용하면 괄호없이 호출이 가능하다. @property를 붙인 함수는 ()로 호출을 안해도 된다는 걸 알았다. 이어서 영상에서는 setter에 대해서도 알려준다.
class Employee:
def __init__(self, first, last):
self.first = first
self.last = last
@property
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
@property
def fullname(self):
return '{} {}'.format(self.first, self.last)
emp_1 = Employee('John', 'Smith')
emp_1.fullname = 'Corey Schafer'
print(emp_1.first) # 에러 발생
print(emp_1.email)
print(emp_1.fullname)
fullname을 입력하면, 저절로 first, email이 나눠지면 좋겠다. 이대로 실행하면 can't set attribute라는 에러를 만나게 된다. 이럴때 @setter를 사용하면 문제를 해결할 수 있다.
class Employee:
def __init__(self, first, last):
self.first = first
self.last = last
@property
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
@property
def fullname(self):
return '{} {}'.format(self.first, self.last)
# setter를 정의한다.
# 메소드의 이름은 fullname으로 동일하게 정의할 것
@fullname.setter
def fullname(self, name): # 여기서 name은 들어올 fullname을 의미
first, last = name.split(' ')
self.first = first
self.last = last
emp_1 = Employee('John', 'Smith')
emp_1.fullname = 'Corey Schafer' # name = Corey Schafer
print(emp_1.first) # Corey
print(emp_1.email) # Corey.Schafer@email.com
print(emp_1.fullname) # Corey Schafer
메소드의 이름은 동일하게 지어주고, @setter를 붙여줌으로써 에러없이 코드가 실행되는 걸 확인했다. emp_1의 fullname을 Corey Schafer로 정의하는 순간, @fullname.setter로 찾아가서 대입된 이름 Corey Schafer를 공백 기준으로 나누고, first와 last에 각각 값을 set(할당)하게 된다. email을 실행하게 될 때도, 현재의 first와 last가 Corey, Schafer이므로 이 정보가 적용된 email이 출력된다.
property 데코레이터와 setter 데코레이터를 잘 사용하면, 클래스를 사용하는 사람들은 코드를 변경할 필요가 없이 동일한 방식으로 해당 속성에 계속 접근할 수 있기 때문에 편리한 방법이다.
그렇게 하나를 배웠다👍
'학습 > 살이되고 뼈가되어라' 카테고리의 다른 글
Error Code: 1241. Operand should contain 1 column(s) (0) | 2022.09.04 |
---|---|
.gitignore에 나중에 추가한 파일이 추적될 때 (0) | 2022.07.21 |
Django render, redirect 차이점이 뭐야? (0) | 2022.04.27 |
Django settings.py : CART_ID = 'cart_item' ..? 왜만들지? (0) | 2022.04.27 |
Study :: '깔끔한 파이썬 탄탄한 백엔드' (0) | 2022.04.25 |