import vs require
Import vs. Require 참고 및 출처
Import vs. Require 참고 및 출처
일시적 사각지대(Temporal Dead Zone, TDZ) 일시적 사각지대(Temporal Dead Zone, TDZ)는 JavaScript에서 변수가 선언되었지만 아직 초기화되지 않은 상태로 존재하는 코드 영역을 의미한다. 이 개념은 ES6(ECMAScript 2015)에서 let과 const 키워드가 도입되면서 함께 등장했다. TDZ는 변수가 스코프에 들어가는 시점(코드 블록의 시작)부터 해당 변수의 선언문이 실행되는 시점까지의 구간을 가리킨다. 이 구간에서는 변수가 존재하지만 접근할 수 없는 상태이다. 1 2 3 4 5 6 { // TDZ 시작 (x에 대한) console.log(x); // ReferenceError: Cannot access 'x' before initialization let x = 10; // TDZ 종료 (x에 대한) console.log(x); // 10 (정상 작동) } 위 예제에서 x는 블록의 시작부터 존재하지만(호이스팅됨), let x = 10이 실행되기 전까지는 접근할 수 없다. 이 기간이 바로 TDZ이다. ...
Hoisting 호이스팅(Hoisting)은 JavaScript 엔진이 코드를 실행하기 전에 변수, 함수, 클래스 또는 임포트의 선언부를 스코프의 최상단으로 끌어올리는 것처럼 동작하는 JavaScript의 메커니즘으로, 이름 그대로 ‘끌어올린다(hoist)‘는 의미를 가진다. 그러나 실제로 코드가 물리적으로 재배치되는 것은 아니다. 이는 JavaScript 엔진의 컴파일 과정에서 일어나는 일종의 추상적 개념이다. 호이스팅은 JavaScript의 핵심 메커니즘 중 하나로, 코드의 실행 방식에 영향을 미친다. 효과적인 JavaScript 개발자가 되기 위해서는 호이스팅의 개념과 다양한 선언 방식에 따른 차이점을 이해하는 것이 중요하다. 모던 JavaScript에서는 let과 const를 사용하여 변수를 선언하고, 함수 표현식을 활용하는 것이 호이스팅으로 인한 예기치 않은 동작을 방지하는 데 도움이 된다. 또한, 모든 변수를 스코프의 최상단에서 선언하는 습관을 들이면 호이스팅으로 인한 혼란을 최소화할 수 있다. ...
Variable Declarations JavaScript에서 변수 선언(Variable Declarations)은 프로그램에서 데이터를 저장하고 참조하는 데 사용되는 중요한 개념이다. 변수 선언 방식에 따라 변수의 **유효 범위(Scope)**와 재할당 가능 여부 등이 결정된다. ES6(ECMAScript 2015) 이전에는 var 키워드만을 사용하여 변수를 선언했으나, 이후 let과 const 키워드가 도입되어 보다 다양한 변수 선언이 가능해졌다. JavaScript에서는 주로 세 가지 키워드를 사용하여 변수를 선언한다: var 키워드 사용 let 키워드 사용 const 키워드 사용 Var 키워드 var는 JavaScript의 가장 오래된 변수 선언 방식이다. ...
변수 명명 규칙(Variable Naming Rules) JavaScript의 변수 명명 규칙(Variable Naming Rules)은 코드의 가독성과 유지보수성을 높이는 데 중요한 역할을 한다. 좋은 변수 이름을 사용하면 코드를 처음 보는 사람도 더 쉽게 이해할 수 있고, 나중에 자신이 작성한 코드를 다시 볼 때도 의도를 빠르게 파악할 수 있다. 필수 규칙 (문법적 제약) 변수 이름에는 다음과 같은 필수 규칙이 적용된다: 문자, 숫자, 밑줄(_), 달러 기호($)만 사용 가능하다. 1 2 3 let userName = "John"; // 올바른 이름 let user_name = "John"; // 올바른 이름 let $price = 100; // 올바른 이름 변수 이름은 숫자로 시작할 수 없다 (문자, 밑줄, 또는 달러 기호로 시작해야 한다). ...
Type Casting 파이썬에서는 다양한 내장 함수를 사용하여 데이터 타입을 변환할 수 있다. 데이터 타입을 변환할 때에는 문자열을 숫자로 변환할 때는 해당 문자열이 유효한 숫자 형식이어야 한다. 실수를 정수로 변환할 때는 소수점 이하가 버려진다. 복잡한 데이터 구조(리스트, 딕셔너리 등)를 변환할 때는 주의가 필요하다. 등을 주의해야 한다. 정수로 변환 (int()) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # 정수형 변환 float_num = 3.14 int_num = int(float_num) # 3 (소수점 이하 버림) # 실수형 변환 a = float("10.5") # 문자열을 실수로 integer = 5 # 정수를 실수로 float_num = float(integer) # 5.0 b = float(10) # 문자열을 숫자로 변환 str_num = "123" number = int(str_num) # 123 float_num = float("3.14") # 3.14 # 진수 변환 binary_str = "1010" decimal = int(binary_str, 2) # 10 (2진수를 10진수로) hex_str = "1A" decimal = int(hex_str, 16) # 26 (16진수를 10진수로) 문자열로 변환 (str()) ...
ES Modules vs. CommonJS 자바스크립트 애플리케이션이 복잡해지면서 코드를 모듈화하는 방법이 중요해졌다. 이에 두 가지 주요 모듈 시스템인 CommonJS와 ES Modules가 등장했다. 이 두 시스템은 각각 고유한 특성과 사용 사례를 가지고 있다. JavaScript 모듈 시스템의 선택은 프로젝트의 요구 사항, 타겟 환경, 그리고 기존 코드베이스에 크게 의존한다. 최신 프로젝트에서는 ES Modules의 채택이 증가하는 추세이지만, CommonJS는 Node.js 생태계에서 여전히 중요한 역할을 하고 있다. 두 시스템의 장단점을 이해하고, 필요에 따라 적절한 시스템을 선택하거나 하이브리드 접근 방식을 채택하는 것이 좋다. 또한, 점진적으로 ES Modules로 마이그레이션하는 전략을 고려할 수 있으며, 이를 통해 모던 JavaScript의 이점을 활용하면서 기존 코드의 호환성도 유지할 수 있다. ...
Python-Special Methods 클래스에 특별한 기능을 부여하는 특수한 메소드. 언더스코어 두 개로 둘러싸인 이름을 가지며, 파이썬 인터프리터에 의해 특정 상황에서 자동으로 호출된다. 객체 생성 및 초기화 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Example: def __new__(cls, *args, **kwargs): # 객체 생성 전에 호출되는 메서드 print("1. __new__ 호출: 객체 생성") # 실제 객체 생성 instance = super().__new__(cls) return instance def __init__(self, value): # 객체 초기화 메서드 print("2. __init__ 호출: 객체 초기화") self.value = value def __del__(self): # 객체가 소멸될 때 호출되는 메서드 print("3. __del__ 호출: 객체 소멸") # 사용 예시 obj = Example(10) # __new__와 __init__ 호출 del obj # __del__ 호출 객체 표현 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): # 사용자 친화적인 문자열 표현 return f"{self.name} ({self.age}세)" def __repr__(self): # 개발자를 위한 상세한 문자열 표현 return f"Person(name='{self.name}', age={self.age})" def __format__(self, format_spec): # 형식화된 문자열 표현 if format_spec == 'brief': return f"{self.name}" return str(self) # 사용 예시 person = Person("홍길동", 30) print(str(person)) # __str__ 호출 print(repr(person)) # __repr__ 호출 print(format(person, 'brief')) # __format__ 호출 __str__와 __repr__의 차이 특징 str repr 목적 사용자 친화적 출력 개발자 친화적 출력 사용 print() 함수 디버깅, 개발 상세도 간단한 설명 상세한 정보 형식 읽기 쉬운 형식 정확한 정보 포함 연산자 오버로딩 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): # + 연산자 return Vector(self.x + other.x, self.y + other.y) def __sub__(self, other): # - 연산자 return Vector(self.x - other.x, self.y - other.y) def __mul__(self, scalar): # * 연산자 return Vector(self.x * scalar, self.y * scalar) def __truediv__(self, scalar): # / 연산자 return Vector(self.x / scalar, self.y / scalar) def __floordiv__(self, scalar): # // 연산자 return Vector(self.x // scalar, self.y // scalar) def __mod__(self, scalar): # % 연산자 return Vector(self.x % scalar, self.y % scalar) def __pow__(self, power): # ** 연산자 return Vector(self.x ** power, self.y ** power) def __lshift__(self, other): # << 연산자 return self.x << other.x, self.y << other.y def __rshift__(self, other): # >> 연산자 return self.x >> other.x, self.y >> other.y def __and__(self, other): # & 연산자 return self.x & other.x, self.y & other.y def __or__(self, other): # | 연산자 return self.x | other.x, self.y | other.y def __xor__(self, other): # ^ 연산자 return self.x ^ other.x, self.y ^ other.y v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # 벡터 덧셈 print(v1 * 2) # 벡터 스칼라 곱 단항 연산자 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Number: def __init__(self, value): self.value = value def __pos__(self): # 단항 + 연산자 return Number(+self.value) def __neg__(self): # 단항 - 연산자 return Number(-self.value) def __abs__(self): # abs() 함수 return Number(abs(self.value)) def __invert__(self): # ~ 연산자 return Number(~self.value) n = Number(5) print(abs(n).value) # 절대값 print((~n).value) # 비트 반전 비교 연산자 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 31 class Temperature: def __init__(self, celsius): self.celsius = celsius def __eq__(self, other): # == 연산자 return self.celsius == other.celsius def __ne__(self, other): # != 연산자 return self.celsius != other.celsius def __lt__(self, other): # < 연산자 return self.celsius < other.celsius def __le__(self, other): # <= 연산자 return self.celsius <= other.celsius def __gt__(self, other): # > 연산자 return self.celsius > other.celsius def __ge__(self, other): # >= 연산자 return self.celsius >= other.celsius t1 = Temperature(20) t2 = Temperature(25) print(t1 < t2) # 온도 비교 컨테이너 메소드 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 31 32 33 34 35 36 37 38 class CustomList: def __init__(self, items): self.items = items def __len__(self): # len() 함수 return len(self.items) def __getitem__(self, index): # 인덱싱 return self.items[index] def __setitem__(self, index, value): # 인덱스로 값 설정 self.items[index] = value def __delitem__(self, index): # 인덱스로 항목 삭제 del self.items[index] def __iter__(self): # 이터레이션 return iter(self.items) def __next__(self): # 다음 항목 반환 if not self.items: raise StopIteration return self.items.pop(0) def __contains__(self, item): # in 연산자 return item in self.items cl = CustomList([1, 2, 3, 4, 5]) print(len(cl)) # 길이 print(cl[2]) # 인덱싱 print(3 in cl) # 포함 여부 속성 접근 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 class DynamicAttributes: def __init__(self): self._attributes = {} def __getattr__(self, name): # 존재하지 않는 속성 접근 return self._attributes.get(name, None) def __setattr__(self, name, value): # 속성 설정 if name == '_attributes': super().__setattr__(name, value) else: self._attributes[name] = value def __delattr__(self, name): # 속성 삭제 del self._attributes[name] def __getattribute__(self, name): # 모든 속성 접근 시 호출 print(f"Accessing attribute: {name}") return super().__getattribute__(name) da = DynamicAttributes() da.new_attr = 42 print(da.new_attr) del da.new_attr 호출 가능 객체 1 2 3 4 5 6 7 class Adder: def __call__(self, x, y): # 객체를 함수처럼 호출 return x + y add = Adder() print(add(3, 4)) # 객체를 함수처럼 사용 컨텍스트 관리 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class FileManager: def __init__(self, filename): self.filename = filename def __enter__(self): # with 문 진입 시 호출 self.file = open(self.filename, 'w') return self.file def __exit__(self, exc_type, exc_value, traceback): # with 문 종료 시 호출 self.file.close() with FileManager('test.txt') as f: f.write('Hello, World!') 피클링 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pickle class Picklable: def __init__(self, value): self.value = value def __reduce__(self): # 객체의 직렬화 방법 정의 return (self.__class__, (self.value,)) obj = Picklable(42) pickled = pickle.dumps(obj) unpickled = pickle.loads(pickled) print(unpickled.value) 기타 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class CustomNumber: def __init__(self, value): self.value = value def __hash__(self): # hash() 함수 return hash(self.value) def __bool__(self): # bool() 함수 return bool(self.value) def __index__(self): # 정수형 변환 return int(self.value) cn = CustomNumber(42) print(hash(cn)) print(bool(cn)) print(list(range(cn))[0]) # __index__ 사용 참고 및 출처
Python - Iterators 데이터 컬렉션의 요소들을 순차적으로 접근할 수 있게 해주는 객체 이터레이터의 기능과 역할 데이터 스트림에서 한 번에 하나의 항목을 반환 현재 항목과 방문한 항목을 추적 컨테이너의 요소에 순차적으로 접근 메모리를 효율적으로 사용 이터레이터의 특징 __iter__() 및 __next__() 메서드를 구현하여 이터레이터 프로토콜을 따름 next() 함수를 사용하여 다음 요소에 접근 모든 요소를 순회한 후 StopIteration 예외 발생 지연 평가(lazy evaluation)를 지원하여 필요한 요소만 생성 활용 대용량 파일 처리 데이터베이스 쿼리 결과 처리 스트리밍 데이터 처리 메모리 효율적인 데이터 처리 실시간 데이터 생성 이터레이터의 종류 기본 이터레이터 가장 일반적인 형태의 이터레이터. __iter__와 __next__ 메서드를 구현하여 만든다. ...
Structural Pattern Matching Python 3.10부터 도입된 구조적 패턴 매칭(Structural Pattern Matching) 은 데이터의 구조와 값을 기반으로 코드의 흐름을 제어하는 강력한 기능이다. 이는 기존의 if-elif-else 문을 대체하거나 보완하여 코드의 가독성과 유지보수성을 향상시키는 데 유용하다. 기본 개념 및 문법 구조적 패턴 매칭은 match 문과 case 절을 사용하여 구현된다. match 문은 주어진 표현식을 평가하고, 각 case 절은 해당 표현식의 결과와 비교할 패턴을 정의한다. 가장 먼저 일치하는 패턴의 코드 블록이 실행된다. 1 2 3 4 5 6 7 match 표현식: case 패턴1: # 패턴1과 일치할 때 실행할 코드 case 패턴2: # 패턴2와 일치할 때 실행할 코드 case _: # 어떤 패턴과도 일치하지 않을 때 실행할 코드 여기서 case _:는 와일드카드 패턴으로, 앞의 어떤 패턴과도 일치하지 않을 때 실행된다. ...