파이썬을 쓰면 볼 수 있는 None은 값이 없음을 나타내는 특별한 객체입니다.
보통 None이 아무것도 없음을 나타내는 것처럼,
None은 함수가 값을 반환하지 않을 때, 또는 변수에 초기값을 지정하지 않을 때 사용됩니다.
None은 싱글톤 객체입니다.즉, 프로그램 내에서 하나의 None객체만 존재합니다. 이는 다음과 같은 코드로 확인해 볼 수 있습니다.
a = None
b = None
print(f"a is b : {a is b}")
print()
#다른 큰 수여도 상관 없음
c = 200000000000000000000000 * 9999999999999999999999999999999999999999999999999
d = 200000000000000000000000 * 9999999999999999999999999999999999999999999999999
print(f"c is d : {c is d}")
print(f"c == d : {c == d}")
print()
e = [1]
f = [1]
print(f"e is f : {e is f}")
print(f"e == f : {e == f}")
a is b : True
c is d : False
c == d : True
e is f : False
e == f : True
앞서 얘기한거처럼 Python은 None을 하나의 싱글톤 객체로만 생성합니다.
같은 객체를 참조할 때 True를 반환하는 is연산자를 통해서 모든 None 참조가 하나의 객체를 가리킨다는 것을 알 수 있습니다.
파이썬은 자주 사용되거나 크기가 작은 객체, 불변 객체(immutable objects)(None, True, False 등)를 미리 저장해놨다가 필요할 때 재사용하는 캐싱 기법을 사용하고 있습니다.
예를 들어, 값이 작은 정수 같은 값은 프로그램에서 여러 번 사용될 가능성이 높습니다. 그래서 이 값이 다시 사용될 때마다 메모리를 새로 할당하는 것이 아닌 기존에 저장한 값을 재사용하는 것입니다.
하지만 너무 큰 값이거나, 가변 객체(mutable objects)(리스트, 딕셔너리, 집합 등) 경우에는 캐싱해놓지 않습니다. 따라서 만약 두 번째 경우에서 값을 작은 값으로 하면 결과가 True로 바뀌게 됩니다.
코드
c = 1000
d = 1000
print(f"c is d : {c is d}")
print(f"c == d : {c == d}\n")
c is d : True
c == d : True
None은 NoneType이라는 고유한 타입을 가지고 있습니다.print(type(None))
<class 'NoneType'>
None은 불리언 판별을 할 때, False로 평가됩니다.if not None:
print("None은 False 입니다.")
None은 False 입니다.
def my_function():
pass
result = my_function()
print(result) # 출력: None
def greet(name=None):
if name is None:
print("Hello, Stranger!")
else:
print(f"Hello, {name}!")
greet() # 출력: Hello, Stranger!
greet("Alice") # 출력: Hello, Alice!
data = None
if data is None: # 만약 data에 값이 없다면 값을 초기화
print("데이터가 없습니다.")
data = "Initial_Value"
None과 isNone을 비교 목적으로 사용할 때는 == 또는 != 대신 is 또는 is not을 사용하는 것이 권장됩니다.
if var is None:
print("변수가 None입니다.")
이는 None이 싱글톤 객체이기 때문으로, 한 프로그램 내에서 하나의 객체만 존재하는 싱글톤 객체의 특성상 값을 비교하는 == 연산자 보단 객체의 동일성을 검사하는 is 연산자를 쓰는게 권장됩니다.
None과 다른 언어의 null다른 프로그래밍 언어에도 None과 비슷한 null이라는 개념이 있습니다. 이 둘은 값이 없음을 의미하기도 하고, 실제로 둘은 비슷한 기능을 담당하고 있습니다. 다만 세부적으로 들어가면서 차이가 생깁니다.
| 언어 | 키워드 | 설명 |
|---|---|---|
| 파이썬 | None | 값이 없음을 나타내는 특별한 객체입니다. NoneType의 유일한 인스턴스로, is 연산자를 사용해 비교합니다. |
| 자바 | null | 객체가 아무런 값을 참조하지 않을 때 사용됩니다. 모든 참조형 변수에 할당될 수 있으며, == 연산자로 비교합니다. |
| C# | null | 참조형 변수와 nullable 값형에 값이 없음을 나타냅니다. == 연산자를 사용해 비교합니다. |
| C++ | nullptr (C++11 이상), NULL, 0 | 포인터가 아무런 객체도 가리키지 않음을 나타냅니다. nullptr은 타입이 명확한 최신 표준입니다. NULL은 전통적인 매크로이며, 0은 정수형 상수로도 사용됩니다. |
| C | NULL | 포인터가 아무런 객체도 가리키지 않음을 나타내는 매크로입니다. 보통 ((void*)0)으로 정의됩니다. |
타입 시스템 및 표현 방식:
None은 NoneType의 유일한 객체으로, 모든 상황에서 동일하게 사용됩니다.null은 참조형에만 사용되며, 값형에서는 nullable 타입을 통해 사용됩니다.nullptr은 C++11부터 도입된 명확한 포인터 리터럴이며, 이전에는 NULL이나 0을 사용했습니다.NULL은 전통적으로 ((void*)0)으로 정의되며, 포인터와 관련된 상황에서 사용됩니다.비교 방법:
is 연산자를 사용하여 None과 비교합니다.if 변수 is None:
print("변수는 아무 값도 가지고 있지 않습니다.")== 연산자를 사용하여 null 또는 nullptr과 비교합니다.if (변수 == null) {
System.out.println("변수는 null입니다.");
}if (포인터 == nullptr) {
std::cout << "포인터는 nullptr입니다." << std::endl;
}== 연산자를 사용하여 NULL과 비교합니다.if (포인터 == NULL) {
printf("포인터는 NULL입니다.\n");
}기본값 처리:
NULL이나 nullptr을 명시적으로 할당하지 않으면, 포인터는 쓰레기 값을 가질 수 있습니다.객체 지향 특성:
None은 객체이므로, 모든 객체와 마찬가지로 메서드를 호출하거나 속성을 가질 수 없지만, 타입 체킹이 명확하게 가능합니다.null은 객체 참조가 없음을 나타내며, null 참조에 접근하면 NullPointerException(자바)이나 NullReferenceException(C#)이 발생합니다.nullptr이나 NULL은 단순히 메모리 주소 0을 나타내며, 이를 역참조하면 정의되지 않은 동작이 발생할 수 있습니다.