Kiểu dữ liệu Function trong Python - Biến locals và globals

Lập trình Python cơ bản

5.0 (12 đánh giá)
Tạo bởi I Hate Python Team Cập nhật lần cuối 00:18 03-08-2020 56.859 lượt xem 10 bình luận
Tác giả/Dịch giả: I Hate Python Team
Học nhanh

Danh sách bài học

Kiểu dữ liệu Function trong Python - Biến locals và globals

Dẫn nhập

Trong bài trước, Kteam đã giới thiệu đến bạn KIỂU DỮ LIỆU FUNCTION TRONG PYTHON.

Và ở bài này Kteam sẽ lại tìm hiểu với các bạn KIỂU DỮ LIỆU FUNCTION TRONG PYTHON – Biến locals và globals.


Nội dung

Để đọc hiểu bài này tốt nhất bạn cần:

Bạn và Kteam sẽ cùng tìm hiểu những nội dung sau đây

  • Sự khác biệt giữa khai báo biến ở trong hàm và ngoài hàm
  • Thay đổi giá trị argument gián tiếp qua parameter
  • Sử dụng lệnh global
  • Giới thiệu hàm locals và globals

Khai báo biến ở trong hàm

Giả sử, bạn có một đoạn script như sau với việc khai báo một biến ngoài hàm và sử dụng ở trong hàm

kteam = 'How Kteam'


def say_slogan():
    print("We are", kteam)
say_slogan()

Ta dễ dàng biết được kết quả

Kiểu dữ liệu Function trong Python - Biến locals và globals

Thử một trường hợp tiếp theo là khai báo biến ở trong hàm và sử dụng ở trong hàm

Kết quả cũng không có gì ngoài dự đoán

Kiểu dữ liệu Function trong Python - Biến locals và globals

Giờ hãy thử khai báo một biến trong hàm mà sử dụng ngoài hàm xem nào

def make_slogan():
    kteam = 'How Kteam'


print(kteam)

Có ai đoán trật kết quả không nhỉ?

Kiểu dữ liệu Function trong Python - Biến locals và globals

Cụ thể, Python nói với chúng ta rằng biến kteam chưa được khai báo. Nhưng rõ ràng là chúng ta đã khai báo nó ở trong hàm rồi mà?

À, là do chưa chạy hàm. Giờ ta sẽ thử lại. Lần này, ta để một dòng lệnh trong hàm luôn để chắc chắn rằng hàm đã chạy

def make_slogan():
    kteam = 'How Kteam'
    print('Run successfully!')


make_slogan()
print(kteam)

Vẫn lỗi tương tự mặc dù hàm đã chạy

Kiểu dữ liệu Function trong Python - Biến locals và globals

Từ đó, chúng ta có thể kết luận rằng việc khai báo biến ở trong hàm là có vấn đề.

Và quả thực là như vậy. Việc bạn khai báo một biến ở một hàm nào đó thì biến đó chỉ có thể sử dụng trong hàm đó. Còn nếu đi ra ngoài hàm khai báo nó thì biến đó hoàn toàn vô danh > thông báo chưa được khởi tạo.

Hãy tưởng tự như thế này. Bạn sinh ra ở  Việt Nam thế nên ở nước Việt Nam người ta có thể biết bạn là ai (có thể là qua CMND hoặc Căn Cước Công Dân). Nhưng nếu bạn đi qua Úc, Nhật hoặc thậm chí là Lào, Campuchia thì không ai biết được bạn là ai, tên gì cả.

Và như ví dụ trên. Bạn đã khai báo biến kteam trong hàm thôi thì chỉ trong hàm đó mới biết bạn. Còn nếu quăng ra ngoài thì chương trình chẳng biết nó là thằng nào cả.

Một lần nữa lặp lại đó là biến khai báo ở hàm nào thì chỉ hàm đó mới biết biến đó còn thoát ra ngoài hàm đó thì coi như không có. Biến khai báo ở hàm cha có thể sử dụng trong hàm con nhưng biến ở hàm con không thể sử dụng ở hàm cha.

Giống như ví dụ mà bạn thấy, nếu bạn khai báo biến ở ngoài hàm thì bạn hoàn toàn có thể sử dụng biến đó ở trong hàm.

Lưu ý: Biến là đối tượng nên bị ràng buộc bởi điều này. Do đó các HÀM (FUNCTION), LỚP (CLASS) cũng chịu sự ràng buộc này tương tự. Khai báo ở hàm nào thì chỉ dùng ở hàm đó.


Thay đổi giá trị argument gián tiếp qua parameter

Nói về vấn đề này, bạn nên biết 2 thuật ngữ là pass by reference và pass by value.

Đầu tiên, thế nào là pass by reference. Giả sử bạn có một chiếc laptop. Thằng bạn nó muốn mượn dùng một ngày. Thế là bạn mang máy của mình cho nó mượn. Về nhà thằng bạn nó down phim, down game, cài virus. Sau một ngày, hắn đem trả lại bạn. Coi như chiếc laptop của bạn tan nát. Việc bạn đưa laptop của mình cho thằng bạn cũng giống như việc pass by reference. Có nghĩa là bạn đưa bản gốc.

Sang tuần sau. Thằng bạn lại đến mượn đồ tiếp và bây giờ là chiếc xe đạp. Bạn biết tỏng hắn kiểu gì cũng phá, liền lấy bảo bối là  “Gương nhân đôi”, sau đó bạn nhân bản chiếc xe đạp của bạn ra. Bạn lấy bản nhân bản đưa hắn mượn. Và bạn thấy đó, dù cho hắn có đạp nát chiếc xe kia thì xe của bạn cũng không sao.Đó  gọi là bạn pass by value, đưa giá trị hoặc là “đưa bản sao”.

Trong Python, việc bạn CHỈ CÓ THỂ pass by value

Ta sẽ đến với ví dụ để hiểu hơn. Ta có đoạn script sau

num = 69
st = 'How Kteam'
lst = [1, 2, 3]
tup = tuple('Education')

def change(parameter):
    parameter = 'New value'
    print('Changed successfully!')

change(num)
change(st)
change(lst)
change(tup)
print('*' * 10)
print('{}\n{}\n{}\n{}\n'.format(num, st, lst, tup))

Và đây là  kết quả

Kiểu dữ liệu Function trong Python - Biến locals và globals

Như bạn thấy, không một giá trị nào bị thay đổi vì đó là pass by value.

Tuy nhiên, chúng ta thử lật lại kiến thức một ít nào. Bạn nhớ phần “Vấn đề cần lưu tâm khi sử dụng List” Trong bài KIỂU DỮ LIỆU LIST TRONG PYTHON – Phần 1 chứ?

Việc bạn truyền giá trị cho parameter giống hệt như lúc bạn khởi tạo biến parameter và đưa giá trị cho nó vậy.

Xem ví dụ để hiểu nhé!

lst = ['How Kteam', 1, 2]


def change(parameter):
    parameter[1] = 'New value'
    print('Changed successfully!')


print(lst)
change(lst)
print(lst)

Kết quả(*)

Kiểu dữ liệu Function trong Python - Biến locals và globals

Bạn sẽ có một câu hỏi liên quan tới phần này ở cuối bài nhé!


Sử dụng lệnh global

Nếu như một biến nằm trong một hàm (như biến kteam trong ví dụ cuối ở phần đầu) thì người ta hay gọi đó là local variable (biến chỉ có hiệu lực trong một hàm nhỏ).

Đặt vấn đề là việc khai báo biến ở trong hàm trở nên cần thiết thì sao nhỉ?

Ta được Python hỗ trợ lệnh global.

Cú pháp:

global <variable>

Lệnh này như một phép màu mà bạn có thể tạo ra. Giống như bạn có thể  biến một người thành tổng thống Mỹ vậy. Ai trên thế giới này cũng biết. Và như biến, ở nơi nào trong chương trình cũng dùng được.

Hãy đến với ví dụ giống như ví dụ cuối phần đầu ban nãy như có khác biệt một chút

def make_slogan():
    # khởi tạo với global không có giá trị nhé
    global kteam
    # sau khi khởi tạo xong, ta mới gán giá trị
    kteam = 'How Kteam'



# nhớ là phải chạy hàm nữa
make_slogan()

print(kteam)

Và đây là kết quả khi ta có global

Kiểu dữ liệu Function trong Python - Biến locals và globals

Ở đây Kteam muốn bạn lưu ý một trường hợp là tên biến local trùng với tên biến global.

def make_global():
    global x
    x = 1

def local():
    x = 5
    print('x in local', x)


make_global()
print(x)
local()
print(x)

Kết quả

Kiểu dữ liệu Function trong Python - Biến locals và globals

Như bạn thấy ở ví dụ trên, biến x trong hàm local đã trùng với biến global x. Tuy nhiên hai biến x này là hoàn toàn khác nhau. Biến x dùng trong hàm local thì có một địa chỉ riêng và một giá trị riêng, còn biến x global thì cũng có một giá trị riêng và một địa chỉ riêng. Thêm nữa, nếu như ta sử dụng biến x ngoài hàm thì Python sẽ tìm tới biến x global chứ không phải là biến x local.

Lưu ý:

BẠN KHÔNG NÊN SỬ DỤNG GLOBAL trừ khi hết cách. Nó giống như hàm eval vậy. Việc sử dụng biến global làm cho chương trình rối, khó kiểm soát cho nên hạn hãy chế tối đa việc sử dụng.


Giới thiệu hàm locals và globals

Cái tên hàm nói lên tất cả. Hàm locals cho ta biết được những biến local (những biến được khai báo trong hàm) nằm trong chương trình của chúng ta. Còn globals là hàm giúp chúng ta biết được những  biến global trong chương trình.

Kết quả trả ra của hai hàm này là một Dict. Với key là tên biến và value là giá trị của biến.

Lưu ý: Với hàm globals() thì với biến globals có giá trị mới được trả về.

>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> 

>>> global x
>>> 
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> x = 'How Kteam'

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 'How Kteam'}
>>> globals()['x']
'How Kteam'

Kết luận

Qua bài viết này, Bạn đã biết thêm về hàm trong Python qua các khái niệm local và global trong hàm.

Ở bài viết sau. Kteam sẽ tiếp tục giới thiệu thêm với các bạn về KIỂU DỮ LIỆU FUNCTION TRONG PYTHON – Phần 5.

Cảm ơn bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Tải xuống

Tài liệu

Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Kiểu dữ liệu Function trong Python - Biến locals và globals dưới dạng file PDF trong link bên dưới.

Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com

Đừng quên likeshare để ủng hộ Kteam và tác giả nhé!


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Chúng tôi là những người có niềm yêu thích Python và muốn Python được nhiều người biết đến hơn ở Việt Nam.

Khóa học

Lập trình Python cơ bản

Lập trình Python cơ bản

Đánh giá

luan_an_tin đã đánh giá 09:32 16-07-2022

phungduongd đã đánh giá 14:57 05-06-2022

awlezy đã đánh giá 21:51 30-01-2022

hoanganh2597 đã đánh giá 22:33 05-12-2021

PhThao đã đánh giá 23:02 02-08-2021

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
ThanhTuanyeupythonvaAI đã bình luận 23:31 05-09-2022

ông nói buồn cười vãi =))

Vương đã bình luận 21:39 31-05-2022

hữu ích

Vương đã bình luận 21:38 31-05-2022

code gà mờ ạ :(

lst=[(-5, -20), (-4,-15), (-3,-4),(-2,9),(-1,7), (0,1),(1,-7),(2,-9),(4,81),(5,130)]
lstA=[]
lstB=[]
tongA,tongB=0,0
def hamsoy(x,y):
    fx=x*x*x+2*x*x-4*x+1
    if fx == y:
        lstA.append(lst[i])
        return fx
    else:
        lstB.append(lst[i])
        return y
for i in range(len(lst)):
    hamsoy(*lst[i])
def tong (a,b):
    return b
for i in range(len(lstA)):
    tongA=tongA +tong(*lstA[i])
for i in range(len(lstB)):
    tongB=tongB +tong(*lstB[i])
if tongA >=tongB:
    print(tongA-tongB)
else:
    print(tongB-tongA)
print(lstA)
print(lstB)

lordquantran đã bình luận 04:29 11-02-2021

của mình bị báo lỗi invalid character in identifier là sao ạ.

 

def make_slogan():
    global kteam
    kteam = 'How Kteam'

make_slogan()

print(kteam)

Khanaru020 đã bình luận 16:19 10-10-2020

Bài nhẹ dễ hiểu, nắm bài cũ list - Unhash object là tiếp thu được luôn. Thanks, Kteam

Không có video.