본문 바로가기
코딩테스트

[python] 파이썬 알고리즘 인터뷰 : 2일차 - 파이썬 문법

by 얘리밍 2024. 2. 2.
320x100
728x90

 

 

 

파이썬 고급 문법에 대해 알아보자 

 

 

 

# 인덴트

 

공백 4칸을 원칙으로 함.

 

  • 첫번째 줄에 파라미터가 있으면 -> 파라미터가 시작되는 부분에 보기 좋게 맞춘다. 
  • 첫번째 줄에 파라미터가 없으면 -> 공백 4칸 인덴트를 한 번 더 추가하여 다른 행과 구분되도록 한다. 

 

# 첫 줄 파라미터 있을 때
foo = long_func_name(var_one, var_two,
                    var_three, var_four)


# 없을 때
def long_func_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

 

 

 


 

 

# 네이밍 컨벤션

 

 

파이썬 변수명 네이밍 컨벤션은 자바와 다르다. 스네이크 케이스를 기본으로 한다. 

 

  • 자바 : 카멜 케이스(단어를 대소문자로 구분하여 섞어서 작명하는 방식)
  • 파이썬 : 스네이크 케이스(각 단어를 언더스코어(_)로 구분함)

 

따라서 파이썬 변수명이나 함수명에는 언더바를 사용해 표기하도록 하자! 

 

# 카멜 케이스
camelCase: int = 1

# 스네이크 케이스
snake_case: int = 1

 

 

 


 

 

 

# 타입 힌트 

 

 

타입 힌트 : 파이썬은 동적 타이핑 언어임에도 불구하고, 타입을 지정할 수 있게 해주는 것

 

 

# 타입 지정 안한 경우 -> 어떤 숫자를 넘겨야 하는 지 알 수 없음 
def fn(a):
    
 
# 타입 힌트로 지정한 경우 
def fn(a: int) -> bool:

 

 

 

주의할 점)

 

파이썬은 동적 할당이므로 아래와 같이 문자열에 정수를 할당하여도 

문자열이 아닌 정수 타입을 반환한다. 

 

 

a: str = 1
type(a)

<class 'int'>

 

 

 


 

 

# 리스트 컴프리헨션

 

  • 리스트 컴프리헨션 : 기존 리스트를 기반으로 새로운 리스트를 만들어 내는 구문 

 

파이썬은 map, filter와 같은 함수형 기능을 지원하며 람다 표현식 또한 지원한다.

지나친 리스트 컴프리헨션 사용은 가독성을 떨어뜨리므로 표현식이 2개를 넘지 않게 하는 것이 좋다. 

 

 

a = list(map(lambda x :x+10, [1,2,3]))
print(a)

# 결과 [11,12,13]

 

 

 

a = [n  * 2 for n in range(1, 10 + 1) if n % 2 == 1]
print(a)


# 결과 [2, 6, 10, 14, 18]

 

 

  • 딕셔너리의 경우 

    기존

 

# 기존 
a = {}
for key, value in dic.items():
    a[key] = value

 

 

 

     리스트 컴프리헨션 사용 시, 

 

a = {key: value for key, value in dic.items()}

 

 

 


 

 

# 제너레이터 

 

  • 제너레이터 : 루프의 반복 동작을 제어할 수 있는 루틴 형태 
  • yield 구문을 사용한다. 

 

기존의 return 구문은 값을 리턴 하고 모든 함수의 동작을 종료한다. 

하지만 yield 는 제너레이터가 여기까지 실행 중이던 값을 내보낸다는 뜻으로 중간값을 리턴한 다음, 함수는 종료되지 않고

계속해서 맨 끝에 도달할 때까지 실행된다. 

 

def get_natural_number():
    n = 0
    while True:
        n += 1
        yield n 
        
        
 # 종료 구문이 없으므로 값을 계속해서 내보냄

 

 

 

만약 값을 내보내고 싶다면 next()를 통해 추출한다. 

 

 

 

g = get_natural_number()
for _ in range(100):
    print(next(g))

 

 

 

아래와 같이 100까지 출력되는 것을 볼 수 있다. 

 

 

 

 

 

여러 타입의 값을 하나의 함수에서 생성하는 것도 가능하다. 

 

 

def generator():
    yield 1
    yield 'string'
    yield True


g = generator()
print(next(g))
print(next(g))
print(next(g))

 

 

 

 

 

 

 

 


 

 

 

# range 

 

  • range() : 제너레이터의 방식을 활용하는 대표적인 함수

a와 b의 길이를 비교해 보면 둘 다 동일한 100만개가 출력된다. 

 

a = [n for n in range(1000000)]
b = range(1000000)

print(len(a))
print(len(b))

 

 

 

그러나 차이점은 a는 이미 생성된 값이 담겨 있고, b 는 생성해야 한다는 조건이 있다. 

 

이제 둘의 메모리를 비교해 보면 확연히 차이가 난다. 

 

 

print(sys.getsizeof(a))
print(sys.getsizeof(b))

 

 

 

 

b가 메모리 점유율이 훨씬 더 적은 것을 알 수 있다. b는 미리 생성하지 않은 값이므로 메모리 점유율이 더 작다.

그렇다고 인덱스에 접근이 안되는 것은 아니다. 

 

 

print(b[999])

 

 

 

 

 

 


 

 

# enumerate 

 

  • enumerate() : 열거하다 라는 뜻의 함수. 인덱스와 값을 함께 리턴해줌

 

a = [1,2,3,2,45,2,5]
b = list(enumerate(a))
print(b)


# 결과 [(0, 1), (1, 2), (2, 3), (3, 2), (4, 45), (5, 2), (6, 5)]

 

 

 

인덱스와 값을 함께 출력하고 싶을 때 사용하면 유용하다. 

 

for i, v in enumerate(a):
	print(i, v)

 

 

 


 

 

# 나눗셈 연산자

 

  • // : 정수형을 나눗셈할 때 동일한 정수형을 결과로 리턴함(내림 연산자 역할)
  • 즉, 몫을 구하는 연산자이다.

 

5 // 3

# 결과: 1

 

 

  • % : 나머지를 구하는 연산자 

 

5 % 3

# 결과 : 2

 

 

 

몫과 나머지를 동시에 구하려면 divmod() 함수를 사용하면 된다.

 

 

divmod(5, 3)

# 결과 : (1, 2)

 

 

 


 

 

# print

 

각각의  출력 방법에 대해 알아보겠다. 

 

 

1. 기본 띄어쓰기 출력 

 

print('A1', 'B1')

A1 B2

 

 

 

2. 구분자 지정 출력 -> sep 사용

 

print('A1', 'B1', sep=',')

A1, B2

 

 

 

3. 줄바꿈 없이 출력 -> end 사용

 

print() 함수는 항상 줄바꿈을 하기 때문에

end 파라미터를 공백으로 처리하여 줄바꿈을 하지 않도록 제한 가능하다. 

 

 

print('aa', end=' ')
print('bb')

aa bb

 

 

 

4. 리스트 출력하기 (한 줄로)

 

 

a = ['A', 'B']
print(' '.join(a))


A B

 

 

 

5. format 사용하기 

 

 

idx = 1
fruit = "Apple"

print('{0}: {1}'.format(idx + 1, fruit))

# 인덱스 생략도 가능
print('{}: {}'.format(idx + 1, fruit))

# 결과 
2: Apple

 

 

 

6. f- string 사용 ( 3.6 + 에서만 사용 가능) 

 

print(f'{idx + 1} : {fruit}')

2: Apple

 

 


 

 

# pass

 

pass는 널 연산으로 아무것도 하지 않는 기능.

인덴트 오류나 불필요한 오류를 방지할 수 있다. 코드를 인터페이스부터 구현한 다음에 추후 구현을 진행 가능함. 

 

class MyClass(object):
    def method_a(self):
        pass
    def method_b(self):
        print("Method B")


c = MyClass()

 

 

 

 


 

 

# locals

 

  • locals() : 로컬에 선언된 모든 변수를 조회할 수 있는 명령.

 

디버깅할 때 많은 도움이 된다. 

 

import pprint

pprint.pprint(locals())

 

 

클래스 내부 로컬 변수를 출력해 준다

 

 

 


 

 

# 구글 파이썬 스타일 가이드 

 

 

YES

 

if not users:
    print('no users')

if foo == 0:
    self.handle_zero()

if i % 10 == 0:
    self.handle_multiple_of_ten()

 

 

 

 

NO

 

if len(users) == 0:
    print('no users')

if foo is not None and not foo:
    self.handle_zero()

if i % 10:
    self.handle_multiple_of_ten()

 

 

 

길이가 없다는 말은 값이 없다는 뜻으로 not users 로도 충분하다. 

값을 비교할 때는 비교 대상이 되는 값을 직접 비교하는 것이 좋다. 

 

 

 

 

 

출처 : 파이썬 알고리즘 인터뷰 | 박상길

728x90
반응형