면접준비[프론트,백,데이터,CS]/InterView 준비 [ 백엔드 ]

[ 백엔드 면접준비 : Python ] Python 면접 질문 정리_01

안다미로 : Web3 & D.S 2024. 12. 21. 21:12

 

 

 

 

[ 백엔드 면접준비 : Python ] Python 면접 질문 정리_01

 


 

Ⅰ. 리스트와 튜플의 차이는?


 

1. 가변성 측면(Mutability).

 

∇ 리스트 (List)

리스트는 가변 객체(mutable)이다.

그래서 선언 후 리스트의 안에 요소 값을 수정, 삭제 가능하다 

  • 리스트는 대괄호 [ ]
  • 리스트가 더 많은 메모리를 소모한다. 더 느리다
  • 리스트가 삽입과 삭제같은 프로그래밍 작업을 수행하는데 더 낫다.

 

  튜플 (Tuple)

튜플은 불변 객체(immutable)이다.

그래서 선언 후 리스트 안에 값을 수정, 삭제 불가능하다 

  • 튜플은 소괄호 ( )
  • 튜플은 리스트보다 더 적은 메모리를 소모한다. 더 빠르다
  • 튜플 데이터타입이 요소들에 접근하기에 더 적절하다.

     

    튜플의 주요 특징.

 

           1. 불변성 : 한 번 생성된 튜플은 변경할 수 없습니다.

           2. 인덱싱과 슬라이스 : 리스트와 마찬가지로 인덱싱과 슬라이싱이 가능합니다.

           3. 패킹과 언패킹 : 여러 값을 하나의 튜플로 묶거나 튜플의 요소를 개별 변수로 분리 가능합니다.

 

 

 

2. 메모리 및 성능.

 

 

    튜플과 메모리 최적화.

            - 튜플은 리스트에 비해 메모리 사용량이 적고, 처리속도가 빠르다는 장점이 있습니다.

 

                   1. 불변성 : 아까 설명했듯이 튜플은 변경할 수 없는 불변(immutable)한 객체이기 떄문에,

                                     파이썬은 튜플을 활용해서, 메모리를 더 효율적으로 관리할 수있습니다.

 

                                      a. 고정된 크기

                                           : 튜플은 생성 시 크기가 고정되므로,   파이썬은 정확히 필요한 만큼의 메모리만 할당합니다.

                                               튜플은 변경될 수 없기에 내부 구조가 더 단순합니다.

                                               이로 인해 메모리 사용량이 줄어들고 접근 속도가 빨라집니다.

                                       <->

                                       반면, 리스트는 '가변적'이므로 추가 공간을 미리 할당합니다.

 

                   2. 튜플 캐싱 : 파이썬은 작은 크기의 튜플을 메모리에 캐시(저장)하여 재사용합니다.

                                          이는 성능 향상과 메모리 효율성을 위한 최적화 기법입니다.

 

                                  a. 작은 튜플 생성

                                           : 프로그램에서 작은 크기의 튜플(일반적으로 20개 이하 요소 가진 튜플) 을 생성할 때

                                                    파이썬은 이를 특별한 메모리 영역에 저장합니다.

                                  b. 재사용 

                                           : 동일한 내용의 튜플이 다시 필요할 때,

                                                  파이썬은 새로운 메모리를 할당하지 않고 이미 저장된 튜플을 재사용합니다.

                                  c. 메모리 효율성

                                          : 동일한 튜플에 대해 반복적으로 메모리를 할당하고 해제하는 과정 간소화.

a = (1, 2)
b = (1, 2)
print(id(a), id(b)) #2070272464768 2070272464768 동일하게 출력

    -> a,b는 동일한 메모리 주소를 가리킵니다.  파이썬이 두 번째 튜플을 생성할 때 이미 캐싱 된 튜플을 재사용했기 때문. !

 

 

 

                                            

 

3. 사용 케이스.

 

       ∇ 리스트 (List) 사용 적합한 케이스.

                 √ 데이터가 빈번한 수정이 필요한 경우.

                 √ 동적인 데이터 처리.

                 √ 삽입*삭제 작업 많은 경우.

                 √ ex) 장바구니 항목, 실시간 데이터 관리.

 

       ∇ 튜플(Tuple) 사용 적합한 케이스.

                 √ 변경되지 않아야 하는 데이터들을 사용하는 경우.

                 √ 성능 최적화가 필요한 경우

                 √ 삽입*삭제 작업 많은 경우.

                 √ ex) 장바구니 항목, 실시간 데이터 관리.

 

 

           튜플을 사용해야 하는 경우.

 

                 1. 불변 데이터 표현

                        : 변경되지 않아야 하는 데이터를 저장할 때 튜플을 사용합니다.

                               ex) 좌표, 개인정보, 설정 값 등

 

                 2. 딕셔너리 키

                        : 튜플은 해시 가능하므로, 딕셔너리의 키로 사용할 수 있습니다.

 

                 3. 함수의 반환값

                       : 여러 값을 반환할 때 튜플을 사용하면 편리합니다.

 

                 4. 네임드 튜플

                      : collections 모듈의 namedtuple을 사용하여, 필드에 이름을 부여 가능합니다.

 

       

4. 주요 메서드 차이.

       

       ∇ 리스트 (List) 메서드.

                 √ append()

                 √ remove()

                 √ insert()

                 √ sort()

 

       ∇ 튜플(Tuple) 메서드.

                 √ count()

                 √ index()

 

 

5.  코드 예시.

 

# List 예시
fruits = ['apple', 'banana', 'cherry']
fruits.append('date')  # 추가 가능

# Tuple 예시
coordinates = (10, 20)
# coordinates[0] = 15  # 불가능, TypeError 발생

 

 

 

 


 

Ⅱ. 파이썬의 주요 특징,


  

       ◆ 인터프리터 언어 [ Interpreter Language ]

 

               : 파이썬은 인터프리터 언어이므로,  실행하기 전에 '컴파일'을 할 필요가 없습니다.

 

 

          + ∇ 인터프리터 (interpreter)  vs 컴파일러(compiler)

                 :: "인터프리터"는 인간의 언어를 한줄*한줄 씩 통역해서 기계에게 알려주는 동시통역 방식.

                          -> 실행시간(runtime) 전에 기계 레벨 코드를 만드는 컴파일 언어와 다르게 소스코드를 바로 실행합니

                 ::  "컴파일러"는 입력문 전체를 인지한 이후에 통역하는 방식.   

 

 

          + ∇ 인터프리터 (interpreter)  vs 컴파일러(compiler) 예시

 

                 "인터프리터" 예시

                        :: PHP, Ruby, Python, JavaScript

 

                 "컴파일러" 예시

                        :: C, C++, Rust, Go,

 

           + Java는 하이브리드 언어라는 괴상한 이름으로 불립니다. 컴파일 언어와 인터프리터 언어플 혼합한 형태입니다.

 


 

   

       ◆ 객체 지향 프로그래밍 [ OOP, Object Oriented Programming ]

              - 파이썬은 클래스와 구성 및 상속을 함께 정의할 수 있다는 점에서 '객체지향프로그래밍'에 매우 적합합니다.

 

 

 

       ◆ 동적 타이핑 [ Dynamic Typing ]

               : 파이썬은 변수 유형을 명시할 필요가 없습니다. 이것을 동적 타이핑(Dynamic Typing)이라고 합니다.

 

                   <-> 정적 타이핑(Static Typing)

                           : 데이터 타입을 정해주는 방식을 정적 타이핑(static Typing)이라고 합니다.

 

 

 


 

 

Ⅲ. PEP 8 이란 무엇인가?


      ★ PEP 8 은 파이썬 스타일 가이드입니다.

           PEP 8은 문서로써, 파이썬 코드를 잘 작성하기 위한 가이드라인과 모범 사례들을 제공합니다.

 

            -> 즉 읽기 쉽고 눈에 보기 좋은 코딩 스타일을 장려합니다.

 


 

Ⅳ. 파이썬에서 메모리 관리는 어떻게 이루어지는가??


 

       ◆ 파이썬의 메모리 관리.

 

             ▽ 메모리 구조.

 

               ○ 파이썬은 "힙(Heap) 메모리 구조"를 사용하여 객체와 자료구조를 저장합니다.

                     -> 모든 파이썬 객체는 이 힙 영역에 위치하며, 이는 파이썬 인터프리터에 의해 관리됩니다.

 

                             ++ 스택(Stack) 메모리는 함수 호출 시 지역 변수를 저장하는 데 사용되며,

                                          함수가 종료되면 자동으로 메모리가 해제됩니다.

 

 

             ▽ 가비지 컬렉션.

 

               ○ 파이썬은 가비지 컬렉터(Garbage Collector)를 통해 메모리를 관리합니다.

                      -> 사용되지 않는 객체를 자동으로 감지하고 메모리를 해제하여 메모리 누수를 방지합니다.

 

               ○ 가비지 컬렉터는 주기적으로 실행되며,  

                     주로 "참조 카운팅(Reference Counting)" & " 주기적 수집(Generational Collection) " 방식을 사용합니다.

 

                           -> 참조 카운팅 : 각 객체는 자신을 참조하는 변수의 수를 기록합니다.

                                                         참조 카운트가 0이 되면 해당 객체는 메모리에서 해제됩니다.

 

                           -> 주기적 수집 : 서로 참조하는 객체들이 있을 경우 참조 카운트가 0이 되지 않더라도

                                                    주기적으로 이러한 객체들을 검사하여 메모리를 해제합니다.

 

             ▽메모리 할당.

 

               ○ 파이썬은 메모리를 동적으로 할당합니다.

                      == 프로그램 실행 중에 필요에 따라 메모리를 요청하고 해제합니다.

 

               ○ C언어의 메모리 관리 함수와는 달리, 파이썬은 이러한 과정을 자동으로 처리하여 

                       코더의 부담을 줄여줍니다.

 

 

             ▽메모리 최적화.

 

               ○ 프로그래머는 메모리 사용을 최적화하기 위해 불필요한 객체를 삭제하거나

                        'del' 키워드를 사용하여 참조를 제거할 수 있습니다.

 

               ○ '메모리 프로파일링 도구'를 사용하여 메모리 사용량을 분석하고,

                        성능을 개선 할 수 있습니다.

 

 

◎ 메모리 관리의 중요성

       :: 효율적인 메모리 관리는 프로그램의 성능과 안전성에 큰 영향을 미칩니다.

               메모리 누수나 과도한 메모리 사용은 프로그램의 실행 속도를 저하시킬 수 있습니다.

 

 

 


 

 

Ⅴ.  GIL은 무엇이고,  파이썬의 쓰레드의 안정성은?


 

       ▣ GIL은 무엇인가

 

             : GIL은 전역 인터프리터 락(Global Interpreter Lock) 으로

                파이썬의 멀티쓰레드 환경에서의 안정성을 보장하기 위해서 사용되는 '동기화 메커니즘' 입니다.

 

                 GIL은 한 번에 하나의 스레드만 파이선 바이트코드로  실행할 수 있도록 제한하는 락으로서,

                 데이터의 일관성을 유지하고 경쟁 상태를 방지합니다.

 

 

   

   ▣ GIL의 존재 이유.

 

              1.메모리 관리의 안전성.

 

                       ●  파이썬의 레퍼런스 카운팅{reference counting}  방식 보호.

 

                                   * 레퍼런스 카운팅

                                          - 객체에 대한 참조의 수를 세어서, 참조 수가 0이 될 때 해당 객체의 메모리를 해제하는 방식.

                                              + 메모리 누수를 방지하는데 도움을 주지만, '순환 참조' 같은 문제를 야기할 수 있습니다.

 

                                   * 파이썬- 가비지 컬렉션.

                                    -> 파이썬은 이러한 순환참조를 문제를 해결하기 위해, "가비지 컬렉션" 기법도 함께 사용합니다 !

                                             ->> 가비지 컬렉터는 주기적으로 객체의 참조 관계를 검사하여,

                                                       '순환참조'를 처리하고 더 이상 사용되지 않는 객체를 메모리에서 제거합니다.

 

 

                       ●  메모리 누수 및 경쟁 상태(Race Condition) 방지.

 

 

              2. 스레드 안전성 보장.

 

                       ●  여러 스레드가 동시에 객체에 접근할 때 발생할 수 있는 문제 해결.

 

                       ●  복잡한 락 메커니즘 대신 단일 인터프리터 락 사용.

 

 

 

   ▣ GIL의 작동 원리.

                       ●  한 스레드가 GIL을 획득하면, 다른 스레드는 대기.

                       ●  I/O 작업이나 일정 시간 후  GIL을 다른 스레드에 양도.

                       ●  멀티코어 환경에서도 실제로는 한 번에 하나의 스레드만 실행.

 

                                                             

           


   ▣ 파이썬 쓰레드 안전성

            :: "쓰레드 안전성"은 멀티스레드 환경에서

                 공유 자원에 대한 일관되고 예측 가능한 접근을 보장하는 프로그래밍 특성 입니다.

 

                 ▶ 위에서 설명한 GIL 덕분에 파이썬에서는 쓰레드가 동시에 실행될 때 발생할 수 있는

                         데이터 경합(race condition)문제를 어느 정도 완화할 수 있습니다.

 

                 ▶ 그러나, GIL이 있는 상태에서도, 쓰레드가 GIL을 잃게 되면 다른 쓰레드가 실행될 수 있으므로

                         코드의 안전성을 확보하기 위해서는 적절한 동기화 기법이 필요합니다.

 

 

       ◎ 동기화 기법.

              ● Lock : 쓰레드가 특정 자원에 접근할 때 Lock을 사용하여 다른 쓰레드가 동시에 접근하지 못하도록 합니다.

              ● RLock : 재진입 가능한 Lock으로, 같은 쓰레드가 여러 번 Lock을 획득할 수 있습니다.

              ● Semaphore : 특정 수의 쓰레드만 자원에 접근할 수 있도록 제한합니다.

              ● Event: 쓰레드간의 통신을 위해 사용되며, 특정 이벤트가 발생할 때까지 대기할 수 있습니다.

 

 

 

☆ 파이썬은 GIL을 통해 멀티쓰레딩 환경에서 안전성을 제공하지만, 

             개발자는 동기화 기법을 통해 코드의 안전성을 확보해야 합니다.