None Type trong Python
None là một giá trị đặc biệt trong Python đại diện cho “không có giá trị” hoặc “giá trị rỗng”. Nó là một object duy nhất thuộc kiểu NoneType.
1. Giới thiệu về None
Định nghĩa
None là một constant đặc biệt trong Python:
- Đại diện cho sự vắng mặt của giá trị
- Là singleton - chỉ có một instance duy nhất trong Python
- Thuộc kiểu dữ liệu
NoneType
# Tạo biến với giá trị None
result = None
print(result) # None
print(type(result)) # <class 'NoneType'>
# None là singleton - chỉ có 1 instance
a = None
b = None
print(a is b) # True (cùng object trong bộ nhớ)None vs 0, False, "" (chuỗi rỗng)
# None khác với 0
print(None == 0) # False
print(None is 0) # False
# None khác với False
print(None == False) # False
print(None is False) # False
# None khác với chuỗi rỗng
print(None == "") # False
print(None is "") # False
# None khác với list rỗng
print(None == []) # False
# Nhưng None là falsy value
print(bool(None)) # False2. Khi nào sử dụng None?
Giá trị mặc định cho tham số hàm
def greet(name=None):
if name is None:
print("Hello, Guest!")
else:
print(f"Hello, {name}!")
greet() # Hello, Guest!
greet("Alice") # Hello, Alice!
# Ứng dụng thực tế: tham số tùy chọn
def create_user(username, email=None, phone=None):
user = {"username": username}
if email is not None:
user["email"] = email
if phone is not None:
user["phone"] = phone
return user
print(create_user("john"))
# {'username': 'john'}
print(create_user("alice", email="alice@example.com"))
# {'username': 'alice', 'email': 'alice@example.com'}
print(create_user("bob", email="bob@example.com", phone="123-456"))
# {'username': 'bob', 'email': 'bob@example.com', 'phone': '123-456'}Hàm không có return statement
def print_message(msg):
print(msg)
# Không có return statement
result = print_message("Hello")
print(result) # None
# Các hàm chỉ có return (không có giá trị) cũng trả về None
def early_return(x):
if x < 0:
return # Tương đương return None
return x * 2
print(early_return(-5)) # None
print(early_return(5)) # 10Khởi tạo biến chưa có giá trị
# Khởi tạo biến sẽ gán sau
result = None
# Logic xử lý
if some_condition:
result = calculate_something()
else:
result = calculate_other_thing()
# Kiểm tra biến chưa được gán
user_input = None
while user_input is None:
user_input = input("Nhập tên (không để trống): ").strip()
if not user_input:
user_input = None
print("Tên không được để trống!")
print(f"Xin chào, {user_input}!")Đánh dấu không tìm thấy kết quả
def find_user(user_id, users):
"""Tìm user theo ID, trả về None nếu không tìm thấy"""
for user in users:
if user['id'] == user_id:
return user
return None # Không tìm thấy
users = [
{'id': 1, 'name': 'Alice'},
{'id': 2, 'name': 'Bob'}
]
user = find_user(1, users)
if user is not None:
print(f"Found: {user['name']}")
else:
print("User not found")
user = find_user(999, users)
if user is None:
print("User not found") # In ra dòng này3. Kiểm tra None
Sử dụng ‘is’ và ‘is not’ (KHUYẾN KHÍCH)
# ✅ ĐÚNG: Dùng 'is' để kiểm tra None
value = None
if value is None:
print("Value is None")
if value is not None:
print("Value has a value")
else:
print("Value is None") # In ra dòng nàyTại sao không nên dùng == với None?
# ❌ KHÔNG KHUYẾN KHÍCH: Dùng ==
value = None
if value == None: # Hoạt động nhưng không được khuyến khích
print("Value is None")
# ✅ NÊN DÙNG: is
if value is None:
print("Value is None")
# Lý do:
# - 'is' kiểm tra identity (cùng object)
# - '==' kiểm tra equality (giá trị bằng nhau)
# - None là singleton, nên dùng 'is' chính xác và nhanh hơnNone trong điều kiện boolean
# None là falsy value
value = None
# Cách 1: Kiểm tra trực tiếp
if not value:
print("Value is None or falsy")
# Cách 2: Kiểm tra rõ ràng (TỐT HƠN)
if value is None:
print("Value is definitely None")
# Vấn đề khi dùng not:
numbers = [] # List rỗng
# ❌ Không chính xác
if not numbers:
print("numbers is None") # KHÔNG ĐÚNG - numbers là [], không phải None
# ✅ Chính xác
if numbers is None:
print("numbers is None")
else:
print("numbers is not None, but may be empty") # Đúng4. None với Collections
None trong List
# List chứa None
items = [1, None, 3, None, 5]
print(items) # [1, None, 3, None, 5]
# Đếm số lượng None
count_none = items.count(None)
print(count_none) # 2
# Lọc None ra khỏi list
filtered = [x for x in items if x is not None]
print(filtered) # [1, 3, 5]
# Thay thế None bằng giá trị khác
replaced = [x if x is not None else 0 for x in items]
print(replaced) # [1, 0, 3, 0, 5]None trong Dictionary
# Dictionary với giá trị None
user = {
'name': 'John',
'email': None,
'phone': None
}
# Lọc các key có giá trị None
active_fields = {k: v for k, v in user.items() if v is not None}
print(active_fields) # {'name': 'John'}
# Phương thức get() trả về None nếu key không tồn tại
user = {'name': 'Alice'}
email = user.get('email')
print(email) # None
# get() với giá trị mặc định
email = user.get('email', 'no-email@example.com')
print(email) # no-email@example.comNone vs Missing Key
data = {
'a': 1,
'b': None,
# 'c' không tồn tại
}
# Kiểm tra key tồn tại
print('a' in data) # True
print('b' in data) # True (tồn tại nhưng giá trị None)
print('c' in data) # False (không tồn tại)
# Phân biệt None và missing key
if 'b' in data:
if data['b'] is None:
print("Key 'b' exists but value is None")
if 'c' in data:
print("Key 'c' exists")
else:
print("Key 'c' does not exist")5. None với Functions
Hàm trả về None ngầm định
def no_return():
x = 5 + 5
result = no_return()
print(result) # None
# Các hàm built-in cũng có thể trả về None
numbers = [3, 1, 2]
result = numbers.sort() # sort() sắp xếp in-place, không return gì
print(result) # None
print(numbers) # [1, 2, 3] (đã được sắp xếp)Pattern: Optional Return Value
def divide(a, b):
"""Chia a cho b, trả về None nếu b = 0"""
if b == 0:
return None
return a / b
# Sử dụng
result = divide(10, 2)
if result is not None:
print(f"Result: {result}") # Result: 5.0
result = divide(10, 0)
if result is None:
print("Cannot divide by zero") # In ra dòng nàyĐối số mặc định mutable - Cẩn thận!
# ❌ NGUY HIỂM: Dùng list làm giá trị mặc định
def add_item(item, items=[]): # KHÔNG NÊN
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] - KHÔNG MONG MUỐN!
print(add_item(3)) # [1, 2, 3] - KHÔNG MONG MUỐN!
# ✅ ĐÚNG: Dùng None và tạo mới bên trong
def add_item_correct(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item_correct(1)) # [1]
print(add_item_correct(2)) # [2] - ĐÚNG!
print(add_item_correct(3)) # [3] - ĐÚNG!
# Truyền list sẵn có
my_list = [10, 20]
print(add_item_correct(30, my_list)) # [10, 20, 30]6. Nullish Coalescing (Giá trị mặc định)
Sử dụng ‘or’ operator
# Cung cấp giá trị mặc định cho None
name = None
display_name = name or "Guest"
print(display_name) # Guest
# ⚠️ CẨN THẬN: 'or' kiểm tra falsy, không chỉ None
age = 0
display_age = age or 18
print(display_age) # 18 (KHÔNG ĐÚNG - 0 cũng là falsy!)
# ✅ CHÍNH XÁC: Kiểm tra None cụ thể
age = 0
display_age = age if age is not None else 18
print(display_age) # 0 (ĐÚNG)Pattern: Default Values
def get_config(config=None):
"""Trả về config hoặc giá trị mặc định"""
default_config = {
'debug': False,
'timeout': 30,
'max_retries': 3
}
if config is None:
return default_config
# Merge với default (override)
return {**default_config, **config}
# Sử dụng mặc định
print(get_config())
# {'debug': False, 'timeout': 30, 'max_retries': 3}
# Override một số giá trị
print(get_config({'debug': True, 'timeout': 60}))
# {'debug': True, 'timeout': 60, 'max_retries': 3}7. None trong Class
Thuộc tính khởi tạo None
class User:
def __init__(self, username, email=None):
self.username = username
self.email = email
self.phone = None # Sẽ set sau
def set_phone(self, phone):
self.phone = phone
def get_contact_info(self):
info = [self.username]
if self.email is not None:
info.append(f"Email: {self.email}")
if self.phone is not None:
info.append(f"Phone: {self.phone}")
return ", ".join(info)
# Sử dụng
user1 = User("john")
print(user1.get_contact_info()) # john
user2 = User("alice", "alice@example.com")
user2.set_phone("123-456-7890")
print(user2.get_contact_info())
# alice, Email: alice@example.com, Phone: 123-456-7890Optional Chain Pattern
class Address:
def __init__(self, street, city):
self.street = street
self.city = city
class Person:
def __init__(self, name, address=None):
self.name = name
self.address = address
# Truy cập an toàn với None
person1 = Person("John")
person2 = Person("Alice", Address("123 Main St", "NYC"))
# ❌ NGUY HIỂM: Không kiểm tra None
# print(person1.address.city) # AttributeError
# ✅ AN TOÀN: Kiểm tra None
if person1.address is not None:
print(person1.address.city)
else:
print("No address") # In ra dòng này
# Với person2
if person2.address is not None:
print(person2.address.city) # NYC
# Python 3.10+: Match-case
def get_city(person):
match person.address:
case None:
return "Unknown"
case Address(city=city):
return city
print(get_city(person1)) # Unknown
print(get_city(person2)) # NYC8. Best Practices
✅ NÊN làm
# 1. Dùng 'is None' để kiểm tra
if value is None:
print("Value is None")
# 2. Dùng None cho tham số mặc định mutable
def create_list(items=None):
if items is None:
items = []
return items
# 3. Return None rõ ràng khi không tìm thấy
def find_item(item_id):
# ...
if not found:
return None
return item
# 4. Sử dụng type hints (Python 3.5+)
from typing import Optional
def get_user(user_id: int) -> Optional[dict]:
# Có thể trả về dict hoặc None
if user_exists(user_id):
return {'id': user_id}
return None❌ KHÔNG NÊN làm
# 1. Không dùng == để so sánh None
if value == None: # KHÔNG TỐT
pass
# 2. Không dùng list/dict làm default argument
def bad_function(items=[]): # NGUY HIỂM
pass
# 3. Không nhầm lẫn None với falsy values
if not value: # CÓ THỂ SAI - value có thể là 0, [], "", False
pass
# Tốt hơn:
if value is None:
pass9. Bài tập thực hành
Bài 1: Tìm kiếm an toàn
def safe_get(data, *keys, default=None):
"""Lấy giá trị nested dictionary an toàn"""
for key in keys:
if data is None or not isinstance(data, dict):
return default
data = data.get(key)
return data if data is not None else default
# Test
user = {
'name': 'John',
'address': {
'city': 'NYC',
'zipcode': '10001'
}
}
print(safe_get(user, 'name')) # John
print(safe_get(user, 'address', 'city')) # NYC
print(safe_get(user, 'address', 'country')) # None
print(safe_get(user, 'address', 'country', default='USA')) # USA
print(safe_get(user, 'phone', 'mobile')) # NoneBài 2: Filter None
def remove_none(data):
"""Loại bỏ None khỏi nested structures"""
if isinstance(data, dict):
return {k: remove_none(v) for k, v in data.items() if v is not None}
elif isinstance(data, list):
return [remove_none(item) for item in data if item is not None]
return data
# Test
data = {
'name': 'John',
'email': None,
'phones': ['123-456', None, '789-012'],
'address': {
'street': '123 Main',
'city': None,
'country': 'USA'
}
}
cleaned = remove_none(data)
print(cleaned)
# {'name': 'John', 'phones': ['123-456', '789-012'],
# 'address': {'street': '123 Main', 'country': 'USA'}}Tổng kết
Nonelà giá trị đặc biệt đại diện cho “không có giá trị”Nonelà singleton - chỉ có một instance duy nhất- Dùng
is Nonevàis not Noneđể kiểm tra (KHÔNG dùng==) Nonelà falsy value nhưng khác với0,False,"",[]- Sử dụng
Nonecho:- Giá trị mặc định của tham số
- Khởi tạo biến chưa có giá trị
- Đánh dấu không tìm thấy kết quả
- KHÔNG dùng mutable objects (list, dict) làm default argument - dùng
Nonethay thế - Type hint: Dùng
Optional[Type]để chỉ ra giá trị có thể là None
Last updated on
Python