Chuyển đến nội dung chính

Vai trò của Dấu gạch dưới (_) trong Hướng dẫn Python

Trong hướng dẫn này, bạn sẽ học về các cách dùng dấu gạch dưới (_) trong Python.
Đã cập nhật 5 thg 10, 2026  · 8 phút đọc

Khám phá cùng AI

ChatGPTClaudePerplexity

Chạy và chỉnh sửa mã từ hướng dẫn trực tuyến này

Chạy mã

Nhiều lập trình viên Python không biết về các chức năng của dấu gạch dưới (_) trong Python. Nó giúp bạn viết mã Python hiệu quả hơn.

Dấu gạch dưới (_) là một ký tự đặc biệt trong Python.

Nếu bạn là lập trình viên Python, có lẽ bạn đã quen với cú pháp sau:

  • for _ in range(100)

  • __init__(self)

  • _ = 2

Nó có một số ý nghĩa đặc biệt trong những ngữ cảnh khác nhau. Hãy cùng xem tất cả.

Bạn sẽ thấy tối đa sáu cách dùng khác nhau của dấu gạch dưới (_). Khi đã nắm rõ, bạn có thể dùng nó cho nhiều mục đích khác nhau.

1. Dùng trong Bộ thông dịch (Interpreter)

Python tự động lưu giá trị của biểu thức cuối cùng trong bộ thông dịch vào một biến đặc biệt gọi là "_". Bạn cũng có thể gán giá trị này cho biến khác nếu muốn.

Bạn có thể dùng nó như một biến bình thường. Xem ví dụ

>>> 5 + 4
9
>>> _     # stores the result of the above expression
9
>>> _ + 6
15
>>> _
15
>>> a = _  # assigning the value of _ to another variable
>>> a
15

2. Bỏ qua giá trị

Dấu gạch dưới (_) cũng được dùng để bỏ qua giá trị. Nếu bạn không muốn dùng một số giá trị khi giải nén (unpack), chỉ cần gán giá trị đó cho dấu gạch dưới (_).

Bỏ qua ở đây nghĩa là gán giá trị vào biến đặc biệt dấu gạch dưới (_). Ta gán các giá trị vào dấu gạch dưới (_) với chủ đích sẽ không dùng chúng trong mã về sau.

Xem ví dụ

## ignoring a value
a, _, b = (1, 2, 3) # a = 1, b = 3
print(a, b)

## ignoring multiple values
## *(variable) used to assign multiple value to a variable as list while unpacking
## it's called "Extended Unpacking", only available in Python 3.x
a, *_, b = (7, 6, 5, 4, 3, 2, 1)
print(a, b)
1 3
7 1

3. Dùng trong vòng lặp

Bạn có thể dùng dấu gạch dưới (_) làm biến trong vòng lặp. Xem các ví dụ dưới đây để hình dung.

## lopping ten times using _
for _ in range(5):
    print(_)

## iterating over a list using _
## you can use _ same as a variable
languages = ["Python", "JS", "PHP", "Java"]
for _ in languages:
    print(_)

_ = 5
while _ < 10:
    print(_, end = ' ') # default value of 'end' id '\n' in python. we're changing it to space
    _ += 1
0
1
2
3
4
Python
JS
PHP
Java
5 6 7 8 9

4. Phân tách chữ số của số

Nếu bạn có một số có nhiều chữ số, bạn có thể tách nhóm chữ số theo ý để dễ đọc hơn.

Ví dụ: million = 1_000_000

Tiếp theo, bạn cũng có thể dùng dấu gạch dưới (_) để phân tách phần nhị phân, bát phân hoặc thập lục phân của số.

Ví dụ: binary = 0b_0010, octa = 0o_64, hexa = 0x_23_ab

Hãy chạy tất cả ví dụ trên để xem kết quả.

## different number systems
## you can also check whether they are correct or not by coverting them into integer using "int" method
million = 1_000_000
binary = 0b_0010
octa = 0o_64
hexa = 0x_23_ab

print(million)
print(binary)
print(octa)
print(hexa)
1000000
2
52
9131

5. Đặt tên với Dấu gạch dưới (_)

Dấu gạch dưới (_) có thể dùng để đặt tên biến, hàm, lớp, v.v.

  • Một gạch dưới ở đầu: _variable
  • Một gạch dưới ở cuối: variable_
  • Hai gạch dưới ở đầu: __variable
  • Hai gạch dưới ở cả đầu và cuối: __variable__

5.1. _single_pre_underscore

_name

Một gạch dưới ở đầu dùng cho mục đích nội bộ. Phần lớn chúng ta không dùng vì lý do đó.

Xem ví dụ sau.

class Test:

    def __init__(self):
        self.name = "datacamp"
        self._num = 7

obj = Test()
print(obj.name)
print(obj._num)
datacamp
7

Một gạch dưới ở đầu không ngăn bạn truy cập vào biến có một gạch dưới ở đầu.

Nhưng một gạch dưới ở đầu ảnh hưởng đến các tên được import từ mô-đun.

Hãy viết đoạn mã sau trong tệp my_funtions.

## filename:- my_functions.py

def func():
    return "datacamp"

def _private_func():
    return 7

Bây giờ, nếu bạn import tất cả phương thức và tên từ my_functions.py, Python sẽ không import các tên bắt đầu bằng một gạch dưới ở đầu.

>>> from my_functions import *
>>> func()
'datacamp'
>>> _private_func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_private_func' is not defined

Bạn có thể tránh lỗi trên bằng cách import mô-đun theo cách thông thường.

>>> import my_functions
>>> my_functions.func()
'datacamp'
>>> my_functions._private_func()
7

Một gạch dưới ở đầu chỉ nên dùng cho mục đích nội bộ.

5.2 single_postunderscore

name_

Đôi khi nếu bạn muốn dùng từ khóa Python làm tên biến, hàm hoặc lớp, bạn có thể dùng quy ước này.

Bạn có thể tránh xung đột với từ khóa Python bằng cách thêm một dấu gạch dưới ở cuối tên bạn muốn dùng.

Hãy xem ví dụ.

>>> def function(class):
  File "<stdin>", line 1
    def function(class):
                 ^
SyntaxError: invalid syntax
>>> def function(class_):
...     pass
...
>>>

Một gạch dưới ở cuối được dùng để đặt tên biến trùng với từ khóa Python và tránh xung đột bằng cách thêm dấu gạch dưới ở cuối tên biến.

5.3. Hai gạch dưới ở đầu

__name

Hai gạch dưới ở đầu được dùng cho name mangling (xáo trộn tên).

Hai gạch dưới ở đầu báo cho bộ thông dịch Python viết lại tên thuộc tính trong các lớp dẫn xuất để tránh xung đột tên.

  • Name Mangling: bộ thông dịch Python thay đổi tên biến theo cách khó bị trùng khi lớp được kế thừa.

Hãy xem ví dụ.

class Sample():

    def __init__(self):
        self.a = 1
        self._b = 2
        self.__c = 3
obj1 = Sample()
dir(obj1)
['_Sample__c',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_b',
 'a']

Đoạn mã trên trả về tất cả thuộc tính của đối tượng class. Hãy xem các biến của ta trong danh sách thuộc tính.

Biến self.a xuất hiện trong danh sách mà không thay đổi gì.

Biến self._b cũng xuất hiện trong danh sách mà không thay đổi gì. Như đã nói, nó chỉ dùng nội bộ.

  • Có biến self.__c trong danh sách không?

    • Nếu bạn nhìn kỹ danh sách thuộc tính, bạn sẽ thấy một thuộc tính tên _Sample__c. Đây là name mangling. Nó dùng để tránh ghi đè biến trong các lớp con.

Hãy tạo một class khác bằng cách kế thừa Sample để xem việc ghi đè hoạt động thế nào.

class SecondClass(Sample):

    def __init__(self):
        super().__init__()
        self.a = "overridden"
        self._b = "overridden"
        self.__c = "overridden"
obj2 = SecondClass()
print(obj2.a)
print(obj2._b)
print(obj2.__c)
overridden
overridden



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-2-4bf6884fbd34> in <module>()
      9 print(obj2.a)
     10 print(obj2._b)
---> 11 print(obj2.__c)


AttributeError: 'SecondClass' object has no attribute '__c'

Ở đây, name mangling lại hoạt động. Nó đổi obj2.__c thành _SecondClass__c. Giờ hãy in phần tử đó bằng thuộc tính đã đổi tên.

print(obj2._SecondClass__c)
overridden

Thấy không, nó hoạt động. Bạn cũng có thể truy cập biến đã tạo trước đó bằng _Sample__c. Xem nhé

print(obj1._Sample__c)
3

Bạn có thể truy cập các biến hai gạch dưới ở đầu thông qua các phương thức trong lớp. Xem ví dụ.

class SimpleClass:

    def __init__(self):
        self.__datacamp = "Excellent"

    def get_datacamp(self):
        return self.__datacamp

obj = SimpleClass()
print(obj.get_datacamp()) ## it prints the "Excellent" which is a __var
print(obj.__datacamp)     ## here, we get an error as mentioned before. It changes the name of the variable
Excellent



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-5-8006c0a9b061> in <module>()
      9 obj = SimpleClass()
     10 print(obj.get_datacamp()) ## it prints the "Excellent" which is a __var
---> 11 print(obj.__datacamp)     ## here, we get an error as mentioned before. It changes the name of the variable


AttributeError: 'SimpleClass' object has no attribute '__datacamp'

Bạn cũng có thể dùng hai gạch dưới ở đầu cho tên phương thức. Xem ví dụ.

class SimpleClass:

    def __datacamp(self):
        return "datacamp"

    def call_datacamp(self):
        return self.__datacamp()

obj = SimpleClass()
print(obj.call_datacamp()) ## same as above it returns the Dobule pre underscore method
print(obj.__datacamp())    ## we get an error here
datacamp



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-1-cd8ce2e83589> in <module>()
      9 obj = SimpleClass()
     10 print(obj.call_datacamp()) ## same as above it returns the Dobule pre underscore method
---> 11 print(obj.__datacamp())    ## we get an error here


AttributeError: 'SimpleClass' object has no attribute '__datacamp'

Hãy nhìn việc name mangling theo một cách khác. Trước tiên, ta sẽ tạo một biến tên _SimpleClass__name, rồi thử truy cập biến đó bằng tên dạng hai gạch dưới ở đầu.

Xem ví dụ.

_SimpleClass__name = "datacamp"

class SimpleClass:

    def return_name(self):
        return __name

obj = SimpleClass()
print(obj.return_name()) ## it prints the __name variable
datacamp

Bạn đã hiểu khái niệm chưa? Nếu chưa, hãy đọc lại.

5.4. Hai gạch dưới ở cả đầu và cuối

__name__

Trong Python, bạn sẽ thấy nhiều tên bắt đầu và kết thúc bằng hai gạch dưới. Chúng được gọi là magic methods hoặc dunder methods.

class Sample():

    def __init__(self):
        self.__num__ = 7

obj = Sample()
obj.__num__
7

Nếu bạn dùng những tên này làm tên biến của mình thì sẽ dễ gây xung đột. Vì vậy, tốt nhất là tránh dùng chúng.

Kết luận

Chúc mừng bạn! Bạn đã hoàn thành. Bạn vừa hoàn thành một khái niệm khá khô khan trong Python. Nhưng nó rất hữu ích khi bạn làm việc với mã nâng cao.

Đa số mọi người như tôi không hiểu khái niệm này ngay ở lần đọc đầu tiên. Vì vậy, đừng nản—hãy đọc lại nếu lần đầu chưa nắm được. Nếu bạn có bất kỳ thắc mắc nào về bài viết, đừng ngần ngại để lại trong phần bình luận.

Nếu bạn là người mới học Python, tôi khuyên bạn nên học khóa học này rồi đọc lại bài viết để hiểu trọn vẹn.

Tài liệu tham khảo:

Chủ đề
Python
Khoa học Dữ liệu

Khóa học Python

Khóa học

Nhập môn Python

4 giờ
7.1M
Nắm vững phân tích dữ liệu với Python chỉ trong 4 giờ. Khóa học online này giúp bạn làm quen với giao diện Python và các thư viện phổ biến.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Liên quan

blog

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm