210321 March of 2021 (1)

Alex of the year 2020 & 2021·2021년 3월 21일
0

TIL_diary

목록 보기
13/13
post-thumbnail

[python] Pythonic

나 역시 파이써닉한 코드 << 가 Ultimate goal인 많은 사람들 중 하나인데
그러면서도 파이써닉한 코드가 정확히 무엇인지 설명하기는 어려운 것이 사실이었다.

  • import 작성 순서 : 내장 임포트문 --> 외부 모듈 임포트문
  • import 시 최대한 wildcard 사용 자제
  • 변수명 : 언더바를 사용한 소문자 snake_case 사용
  • = 기준으로 앞 뒤 한 칸씩 띄어주기. 단, 괄호 안에 파라미터를 넣는 경우에는 빈칸이 X
  • 79 컬럼 제한 (코드 한 줄당)
  • Comprehension 및 indexing, f-string 등의 Generic한 표현을 적극 사용
  • swap 시 temp 사용 X
a = 1000
b = 10

a, b = b, a
print(a,b)
>>> 10, 1000

pythonic한 코드에 관련된 글 몇 개를 읽었는데, 사실상 우리 회사에서 사용하고 있는 코딩 컨벤션이 파이써닉한 코드를 만들기 위한 모든 노력이었다는 것을 깨달았다. (넘 당연한 이야기인가..허허)

[python] List Comprehension vs. Generator Expression

List Comprehension

  • iterable한 list 객체를 생성하기 위한 방법
  • It is an elegant way of defining and creating a list. List Comprehension allows us to create a list using for loop with lesser code. What normally takes 3-4 lines of code, can be compressed into just a single line.
  • 정리하자면, for문을 이용하여 리스트 객체를 만들 때에 단 한줄로 세 네줄의 코드 작성과 같은 효과를 내게 해주는 강력하고 elegant한 방식.
  • [예시] list comprehensio을 이용한 2차원 리스트 만들어보기
def practice():
    arr = [[0 for _ in range(5)] for _ in range(5)]
    print(arr)
practice()
>>> [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
  • LC를 잘 이해하기 위한 효과적인 그림

Generator Expression

  • Generator Expressions are somewhat similar to list comprehensions, but the former doesn’t construct list object. Instead of creating a list and keeping the whole sequence in the memory, the generator generates the next element in demand.
    When a normal function with a return statement is called, it terminates whenever it gets a return statement. But a function with a yield statement saves the state of the function and can be picked up from the same state, next time the function is called.
    The Generator Expression allows us to create a generator without the yield keyword.
  • 정리하자면, LC와 비슷하지만 실제 리스트를 생성하여 메모리에 올리지는 않음. 일반적으로 return문을 가진 함수는 return문의 등장과 함께 함수가 종료되고 메모리에서 삭제(해당 함수의 상태값 저장 X)되는 반면, yield문은 해당 함수의 상태를 저장하기 때문에 다음번에 그 함수가 호출되었을 때에 바로 그 상태의 값을 내보내줄 수 있다. GE의 경우 실제로 yield문을 사용하지 않아도 yield문을 포함하는 generator를 생성하게 해준다.
  • GE를 잘 이해하기 위한 효과적인 그림

List Comprehension vs. Generator Expression

1. 프린트 찍어보면 각각이 무엇을 저장하는지, 나타내는지 알 수 있다

2. GE : more memory-efficient

The generator yields one item at a time and generates item only when in demand. Whereas, in a list comprehension, Python reserves memory for the whole list. Thus we can say that the generator expressions are memory efficient than the lists.

# import getsizeof from sys module 
from sys import getsizeof 

comp = [i for i in range(10000)] 
gen = (i for i in range(10000)) 

#gives size for list comprehension 
x = getsizeof(comp) 
print("x = ", x) 

#gives size for generator expression 
y = getsizeof(gen) 
print("y = ", y) 

>>> 
x =  87624
y =  88

3. GE : more time-efficient

There is a remarkable difference in the execution time. Generator expressions are faster than list comprehension and hence time efficient.

#List Comprehension: 
import timeit 

print(timeit.timeit('''list_com = [i for i in range(100) if i % 2 == 0]''', number=1000000)) 

>>> 8.118047142050102


#Generator Expression: 
import timeit 

print(timeit.timeit('''gen_exp = (i for i in range(100) if i % 2 == 0)''', number=1000000)) 

>>> 0.7548244756850693

[참고] GE + lambda : 범용성 UP

위에서 작성한 코드는 range(100), if % 2 == 0에서 100과 2부분을 바꿀 수 없다는 단점이 있다. (재사용성 및 범용성 낮을 저)
하지만 람다식과 함께라면 재사용성 및 범용성이 뛰어난 코드로 변모할 수 있다.
ge = lambda limit, int: (i for i in range(1, limit + 1) if i % int == 0)


LC, GE를 이용하여 동일한 Output을 출력하려면 (위에서 1번에 해당하는 차이를 없앨 수 있을까?)

1. GE로 선언된 함수 자체를 파고 들어서 하나씩 print하기 (GeeksForGeeks 추천)

2. GE로 선언된 함수를 list화 시켜 LC로 만들어버리고, 그 리스트를 출력하기 (내가 주로 사용하는 방식)

Reference:
https://www.geeksforgeeks.org/python-list-comprehensions-vs-generator-expressions/

[VS Code] 줄 번호 이동하기

간지를 위해 빔을 사용하고 싶었지만 간지보다 실력, 작업 속도를 맞추기 위해 VS code에 정착한 상황이다. 조금 슬픈 마음이 들지만 어쩔 수 없다. 난 실용성을 (지나치게) 중시하는 ESTJ....

여튼 줄번호 이동을 위한 vs code 단축키는 command + G 후 줄 번호 이다.

[etc.] 마이그레이션

django에는 다음과 같은 명령어가 있다.

  1. python manage.py makemigrations
    models.py (MVC 모델의 실제 M에 해당)를 작성한 후, 모델의 내용을 하나의 마이그레이션 파일로 저장하기 위한 명령어
    (차후 모델에 변경 사항이 생겼을 때도 이 명령어를 쳐줘야 한다)
  2. python manage.py migrate
    마이그레이션 파일로 저장한 것을 실제 연결된 DB에 적용시키기 위한 명령어
    (이 때 이제 좀 사람 짜증나게 하는 에러가 종종 발생하기 때문에 --fake등의 방법을 총동원하여 정신 못차리는 장고를 다루어야하는 순간이 때때로 발생한다)
  3. python manage.py showmigrations
    마이그레이션 파일로 저장하고, DB에 적용한 것이 잘 적용되었는지 확인하기 위한 명령어

파이썬 프레임워크 django로 처음 개발을 시작한 나는 이 명령어들을 익히어 실제 개발에 사용하고 있(는 정도가 아니라 없음 못함)기 때문에, 당연히 장고단 내의 마이그레이션의 의미만 생각해봤다. 그러나 일반적인 마이그레이션의 정의는 다음과 같았다.

협의의 마이그레이션 (django)

  • 모델 작성하고(첫 작성이든 수정이든) 테이블 스키마 작성할 때 마이그레이션을 한다고 표현

광의의 마이그레이션 (django 이외에도)

  • 기존 데이터의 변형 및 수정, 이관 등을 행하는 것
  • == DB 마이그레이션, DB 이전, DB 이관, DB 이행
  • 모델에 있는 데이터 —> DBMS하는 그 작업도 역시 마이그레이션이라 이름 (협의의 마이그레이션)
  • [ex] 차세대 프로젝트 시 기존 DB를 타 DB로 변경하거나 통합시스템 구축 시 여러 DB를 하나의 DB로 합치는 것

[django] Validator, Normalize_email

Validator 의미

A validator is a callable that takes a value and raises a ValidationError if it doesn’t meet some criteria. Validators can be useful for re-using validation logic between different types of fields.

Validator 예시

from django.core.validators import validate_email
from django.core.exceptions import ValidationError

Normalize_email 의미

A classmethod that normalizes email addresses by lowercasing the domain portion of the email address.

Normalize_email 위치

django > contrib > auth > models > BaseUserManager

[python] String rsplit() Method

The rsplit() method splits a string into a list, starting from the right.
If no "max" is specified, this method will return the same as the split() method.
Note: When maxsplit is specified, the list will contain the specified number of elements plus one.

split()는 앞에서부터 delimiter를 기준으로 스트링을 나누지만rsplit()는 뒤에서부터 스트링을 나눔

str = "//SF"
result = str1.rsplit('/')
print(result)

# 실행 결과:
['', '', 'SF']

하지만 분할 횟수를 넣어주면 어떨까?

str1 = "//SF"
result = str1.rsplit('/', **1**)
print(result)

# 실행 결과:
['/', 'SF']
profile
Backend 개발 학습 아카이빙 블로그입니다. (현재는 작성하지 않습니다.)

0개의 댓글