기술 정리 & CS/기술면접 대비

[기술면접 대비] Python & 자료구조

yubi5050 2023. 6. 18. 12:47

Python 자료구조

👉 Python의 list, dictionary의 메모리 접근 시간 복잡도

리스트 시간 복잡도

  • append, pop() : 특정 원소 추가, 삭제 - O(1)
  • insert(), remove() : 특정 위치 원소 추가,삭제 - O(N)
  • sort() : 정렬 - O(Nlog(N))

 

dictionary 시간 복잡도

  • 내부적으로 해시테이블을 사용
  • 데이터의 검색, 삽입, 삭제, 수정 - O(1)

 

👉 Python List는 Array vs Linked-list?

Python의 List의 원소로는 다양한 자료형을 내포할 수 있어, Array처럼 연속된 메모리에 저장되기 어려움. 연속되지 않은 메모리에 저장된다는 점에서 Linked List와 좀 더 가깝지만, 다음 주소를 가리키는 방식이 아니기 때문에 Linked List 와도 다르며, 독자적인 방식(key(인덱스)-value(주소)로 예상)이 있는 것으로 보임 (참고 링크)

 

👉 Immutable, mutable 차이 

변경할 수 있는 객체면 mutable, 변경할 수 없는 객체면 immutable 객체라고 함.
정수, 실수, 문자열, 튜플(정적배열) 은 변경이 불가능 : immutable 객체
list(동적배열), dictionary 변경 가능 : mutable 객체


👉 list comprehension vs for loop - append() 차이

python의 list에서 append() 되어 크기가 변경되면 새로 메모리를 할당 받아 기존보다 더 큰 리스트를 만들고 값을 복사하는 형태. 따라서 for loop로 append() 를 계속 호출하게되면, 메모리 재할당에 비용이 드므로, list comprehension이 더 좋음.

 

👉 Tuple이 List 보다 정적 데이터 정의에 더 좋은 이유 (적합한 이유)

Tuple과 List가 1억 byte 크기인 리스트를 생성한다고 하면,

List는 변경(append 등) 발생되는 신규 메모리 할당에서 좀 더 나은 성능을 위해 1억 1천 byte로 여유공간 할당
Tuple은 변경(append 등) 연산 지원 X, 여유공간 할당 없이 1억 Byte 할당
따라서 Tuple 이 정적 데이터에 더 적합


👉 Dictionary과 Set 공통점과 차이점

Dictionary과 Set모두 HashTable 기반으로 작동하여 조회, 추가, 삭제 등에 대한 시간 복잡도가 O(1) 이다. Hash Table 알고리즘이 안좋다면, 성능이 안좋아진다.
Dictionary는 Key : value 로 이루어짐
Set은 Key로만 이루어짐

 

알고리즘

👉 Stack vs Queue

Stack은 후입선출의 구조로 나중에 들어온 데이터가 먼저 나가는 구조

ex) 브라우저의 뒤로가기 버튼이 2개의 stack으로 구현

Queue는 선입선출의 구조로 먼저 들어온 데이터가 먼저 나가는 구조

ex) 은행 상담 창구

 

👉  HashTable

key, value 형태의 자료 구조

적은 리소스로 많은 데이터 효율적 관리 가능

key 인덱스 기반 검색으로 빠른 시간 복잡도를 가짐 (검색, 삽입, 삭제 - O(1))

데이터 캐싱에 많이 사용 (get, put 자주 발생 로직)

 

Python 개발 & 디자인패턴

👉 SOLID 개발 원칙이란?

  • SRP (단일 책임 원칙) : 모든 클래스는 각자 하나의 책임만 가지고 수행 (ex. DB 생성 + 삽입,삭제 => 생성 / 삽입,삭제)
  • OCP (개방 폐쇄 원칙) : 기능을 추가할 때 기존의 코드가 변경되면 안된다.
  • LSP (리스코프 치환 원칙) : 자식클래스는 부모클래스를 대체할 수 있도록 설계 되야 한다.
  • ISP (인터페이스 분리 원칙) : 하나의 인터페이스보단 구체적인 여러개의 인터페이스를 쓰는 것이 좋다.
  • DIP (의존관계원칙) : 다른 것에 상속이나 의존할 때, 추상화 된 것에 의존하는 것이 좋다

 

👉 착한 함수란? 

함수는 가급적 작게, 한번에 하나의 작업만 수행하도록 작성하는 방식

 

👉 디자인 패턴 이란? 장점은?

SW 개발 과정간 발견 된 설계 노하우를 패턴으로 정리 한 것

장점 : 일정한 설계 방식을 통해 코드를 좀더 빠르게 이해가능

 

👉 팩토리 생성 패턴이란? 

객체를 직접 생성하지 않고 Factory 객체를 사용하는 패턴
- 장점으로는 직접 객체를 생성하는 것을 막아주고 DI를 통해 값만 바꿔준다거나 하면, 결합도를 낮춰주는 효과

ex) 아시아 건설사, 유럽 건설사 2개 객체 생성 => 건설사 Interface 추가 하고 DI로 건설사를 아시아~, 유럽~ 바꿔가며 생성

 

👉 결합도를 낮춘다는 것의 의미?

결합도를 낮춘다는 건 바꿔야될 변경 코드가 적은 것

 

👉 싱글톤 패턴 이란?

인스턴스를 오직 1개만 생성하는 패턴

ex) DB Connection 객체, 스레드 풀(스레드 관리하는 매니저)에 주로 사용

 

👉 어댑터 패턴 이란?

어댑터를 사용하여 호환되지 않는 인터페이스를 호환 되도록 하는 패턴으로, 향후 인터페이스가 바뀌더라도 어댑터에 하위들이 캡슐화 되기 때문에 수정할 필요 x

ex) 아시아 건설사는 build(), 유럽 건설사는 make() 가 존재 (둘은 같은 기능임) => 건설사 interface의 do()함수 실행 및 유럽 Adapter do() / 아시아 Adapter do() 중 선택 => 즉 같은 기능을 수행하는 두개의 다른 함수(외부라이브러리)를 호환하여 사용 가능

 

👉 템플릿 패턴 이란?

상속을 통해 부모 클래스의 기능을 확장할 때 사용하는 방법으로, 부모클래스에서는 변하지 않는 기능을 구현해두고, 자식 클래스에선 확장할 기능을 상속 받아 구현하는 것

 

Python 객체지향

👉 OOP 란?

Object Oriented Programming으로 객체 지향 기반의 프로그래밍을 의미

 

👉 객체 생성과 초기화 ( __new__ vs __init__ )

객체의 생성( __new__) 초기화( __init__) 이라는 메서드가 호출됨

  • __new__ : 객체의 생성 과정시 호출 - 생성과정에 관여하고 싶을 때
  • __init__ : 생성된 객체에 속성(property)을 추가시 호출 - 초기화

ex) 사용자가 어떠한 목적을 가지고 (singleton) 클래스의 생성 과정(기존에 생성된 인스턴스가 있다면 그걸 사용하자)에 관여하고 싶을 때, 직접 __new__ 메서드를 클래스에 추가함으로써 object 클래스의 __new__를 오버라이딩 하여 사용자의 __new__ 메소드가 호출되도록 함. (만일 클래스에 __new__ 메소드를 오버라이딩 하여 선언하지 않으면, 알아서 object 클래스의 __new__가 호출되어 객체가 생성)

 

👉 클래스 생성시 init / new 함수를 작성 하지 않으면?

__init__ 함수, __new__ 함수는 클래스 내에 만들어두지 않아도 자동으로 실행됨

 

👉 클래스의 클래스 변수와 인스턴스 변수의 차이는?

클래스 변수는 클래스 내부에 선언되어, 해당 클래스를 바탕으로 만들어진 모든 인스턴스가 공유하는 데이터

인스턴스 변수는 초기화시 선언되어, 각 인스턴스마다 가지고 있는 고유한 데이터

 

👉 __call__  vs __init__ 차이는?

__init__은 클래스에서 만든 객체를 초기화 할 때 사용

__call__은 실제 인스턴스가 호출 됬을 때 사용

ex) a = calc(3,4) -> init 호출 /  a(3,4) -> call 호출

 

👉 super () 란?

상속 관계에서 상속의 대상인 부모 클래스를 호출하는 함수

ex) super().__init__(data) ->  부모 클래스의 생성자를 호출함 (부모 클래스의 클래스 변수 외에, 초기화 가 필요하다는 뜻)

 

 

👉 상속(Inheritance), 오버라이딩, 오버로딩 차이는 ?

  • 상속(inheritance) : 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것
  • 오버로딩(Overloading) : 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 기술
  • 오버라이딩(Overriding) : 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의해서 사용

 

👉 상속 하는 이유?

코드 재사용성을 높여, 코드 중복을 줄이고 유지보수 편리를 위해

 

Python 유틸

👉  Python Decorator를 사용하는 이유?

기존 함수의 로직에 포함되지 않는 추가적인 기능을 수행하고 구현하고 싶을 때

 

👉 Decorator의 예제 중 @staticmethod vs @classmethod 차이

staticmethod : 클래스 객체를 생성하지 않더라도 외부에서 사용 가능하게 하는 것
ex) 소속된 객체의 변수를 활용 (의존성 있음) + 외부에서도 필요한 유틸리티성 일 때 (관련 링크)

 

classmethod : 특정 클래스로 만들어진 객체 인스턴스들을 일괄적으로 제어 할 때 or 여러 다형성으로 호출 되는 생성자를 wrapping 할 때 (관련 링크)

 

Classmethod : 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용

Staticmethod : 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을 사용

 

👉 Decorator 활용 경험

1. 모델 학습에 필요한 모델 가중치가 서버에 다운받아 져있는지 체크용도 없으면 S3 재로딩

2. Query Debugger 데코 만들어서 API 하나 함수에 달고 해당 Method 수행 시간 속도 체크 및 Query 수나 시간 등 print

 

👉 Python 시간 측정 프로파일링 도구

%timeit 매직명령어, time.time(),, decorator 활용

 

Python 언어 & GIL & GC

👉 Python이 느린 이유는?

동적 Type언어로 언어의 자료형을 해석하고 Type을 부여하는 과정에 비용이 소모되기 때문 

ex) a=1 b=2  c=a+b을 처리시

a에 1할당 => a타입판단 => a 값 정수 1 설정 => b에 1할당 => b타입판단 => b 값 정수 2 설정 =>
덧셈 연산 호출 => 객체 c 생성 => c자료형 정수 설정 => c 값 정수 3 설정

 

👉 Python의 GIL 이란? Multi-Thread가 단일 Thread보다 느릴 수 있는 이유?

GIL은 Global Interpreter Lock으로 Python에서 메모리 사용에 차용한 규칙

 

Python은 한 스레드가 해당 자원을 사용할 때 Lock을 걸어서 온전히 점유하여 사용. 다른 스레드가 사용하지 못함. Multi-Thread로 사용시 다른 스레드로 자원이 넘어가는 과정에서 Context-switching에 대한 비용이 추가되기 때문에, 더 느릴 수 있음.

https://yubi5050.tistory.com/158

 

👉 Python의 메모리 관리 방법 중 GC란?

Python은 메모리 관리 방법으로 GC(Garbage Collector)를 사용.

Reference Counting은 참조 횟수가 0이 되면 자동으로 메모리를 해제 (메모리 교체 방식의 LRU - Least Recently Used)와 비슷.

Python 객체 생성시 해당 객체의 reference count를 증가시키고, 해제시 1감소 0되면 해제

참고 링크 : https://otugi.tistory.com/338

 

👉 Python, CPython, Cython 차이

Python : Language
CPython : Python의 Interpreter로 python을 Bytecode로 컴파일하여 CPU가 이해할 수 있도록 함
Cython : C언어로 변환하여 컴파일 할 수 있도록 사용하는 가장 일반적인 도구 (numpy, pandas, scipy)
- 컴파일을 수행한다는 것은 컴파일러가 할 수 있는 최적화 과정을 거쳐준다는 것 => 파이썬의 느린속도 대응 가능
- 미리 컴파일 하는 방식으로 AOT(Ahead of time)라고도 불림 (JIT와 반대 대응됨)
Pypy : 일반 Python 실행환경을 대체하는 비 Numpy 코드를 위한 JIT(Just-in-time) 컴파일러. 파이썬 코드를 Native 어셈블리 언어로 변환)
- 실제 PyPy도 배포가 가능하며 CPython 보다 속도가 더 빠름. 단 numpy와 같이 사용되지 않을 때 유효하며, 내장 모듈로 multiprocessing도 내제되어 있어, multiprocessing 병렬 처리가 요구되는 문제가 있다면 속도 향상 가능성 높음

참고링크 : https://yomangstartup.tistory.com/108

 

👉 Python(Cpython)의 GC와 PyPy의 GC 차이

Cpython은 참조 카운팅(Reference counting)을 사용하여 참조 횟수가 0이 되면 자동으로 메모리를 해제함
PyPy는 나중에 메모리를 제거하는 마크 앤 스윕(Mask and sweep) 방식 사용

 

Python 기초

👉 파이썬에서의 매개변수와 인자의 차이를 설명해주세요.

함수를 정의할 때 넘겨주는 변수를 매개변수, 매개변수의 실제값 (즉 함수 호출되면서 매개변수에 들어가는 값)을 인자라고 함. ex) plus(a,b)의 a,b는 매개변수, plus(3,4) 의 3,4는 인자

 

👉 str() 과 __str__ () 과의 차이는?

str은 클래스 객체이고, __str__은 메소드이다. 내부적으로는 str 인스턴스가 만들어지면서 내부적으로 __str__ 함수가 실행되는 것

 

👉 Doctstring 과 주석의 차이

주석 : 코드에 대한 이해를 돕기 위해 사용됨 ex) # 이 기능은~

docstring : 문서화 문자열의 줄임말로 코드를 설명하기 위한 목적으로 사용 """ 이 기능은 ~ """

 

👉 매직 메서드와 예시 

"__Method__" 형태의 인스턴스(객체)가 생성될 때 인터프리터에 의해 자동으로 호출되는 메소드

__init__, __call__, __getattribute__ 등이 있다.

 

👉  Python의 객체지향 vs 절차지향

객체지향 프로그래밍, 절차지향 프로그래밍은 프로그래밍 패러다임

 

객체 지향이 적절한 경우

- 복잡한 문제를 해결해야 할 때 (대규모 프로젝트, 현실 세계의 모델링)

- 재사용성이 중요한 경우 (향후 기능 확장, 유지보수가 예상되는 경우)

- 코드의 가독성 + 유지보수 용이하게 하고 싶을 때

 

절차 지향이 적절한 경우

- 단순한 문제를 해결해야 할 때

- 빠른 프로토 타이핑이 필요한 경우

- 코드의 간결함이 우선되는 경우

 

결론 : 파이썬은 객체지향, 절차지향 을 모두 지원하므로, 상황에 맞게 적절한 패러다임을 선택