ADMIN: nhanguyen@hcmut.edu.vn

5. Hàm và module

1. Hàm – Function

  • Hàm là một khối code được tổ chức và có thể tái sử dụng, để thực hiện một tác vụ nào đó
  • Trong các chương trước, SV đã làm quen với một số hàm đã được xây dựng sẵn trong Python, điển hình như hàm print().
  • Tuy nhiên người dùng cũng có thể tạo riêng cho mình một hàm với cách định nghĩa và kiểu giá trị cho riêng bạn. Các hàm này được gọi là user-defined function

Cú pháp:

  • Định nghĩa hàm:
def tenHam(cacThamSo):
    "mô tả hàm"
    cacLenhThucThi
    return [giaTriTraVe]
  • Gọi hàm:
[giaTriTraVe] = tenHam(cacThamSo)

Ví dụ: Viết hàm tính trung bình cộng của 2 số

def meanOfTwo(x,y):
    mean = (x+y)/2
    return mean

hoặc

def meanOfTwo(x,y):
    return (x+y)/2

Gọi hàm:

a = meanOfTwo(3,4)
print(a)

Ví dụ: Viết hàm tính trung bình cộng của 1 list các số thực

def meanOfList(listA):
    s = 0
    for i in listA:
        s += i
    return s/len(listA)

b = meanOfList([1,3,5])
print(b)

Ví dụ: Hàm không trả về giá trị

def prt(listA):
    print(3*listA)
prt([1,2,3])
def prt(listA):
    print(3*listA)
    return
listX = [2,5,6]
prt(listX)
def print5Star():
    print("*****")
print5Star()

Phân biệt tham số và đối số

Tham số (parameter)

  • Tham số xuất hiện trong định nghĩa hàm
  • Parameter phải là biến để giữ các giá trị đang đến
def meanOfTwo(x,y):   # x, y  là các tham số
    mean = (x+y)/2
    return mean

Đối số (argument)

  • Đối số xuất hiện trong lời gọi hàm
  • Argument có thể là hằng, biến hoặc biểu thức
xx = 3
a = meanOfTwo(xx,4)  # xx, 4 là các đối số
print(a)

Phạm vi của biến

  • Các biến trong một chương trình không thể truy cập tại tất cả vị trí ở trong chương trình đó. Điều này phụ thuộc vào nơi biến đó được khai báo
  • Phạm vi biến quyết định nơi nào của chương trình bạn có thể truy cập một định danh cụ thể
  • Trong Python, có hai khái niệm về phạm vi biến: Biến toàn cục (global variable) và Biến cục bộ (local variable)

Biến toàn cục (global variable)

  • Biến toàn cục là biến được định nghĩa bên ngoài hàm
  • Biến toàn cục có thể được truy cập bởi tất cả các hàm ở khắp nơi trong chương trình. Phạm vi của biến toàn cục là rộng nhất
b = 20
def msg():
    a = 10
    print("Gia tri cua a la",a)
    print("Gia tri cua b la",b)
    return
msg()
print(b)
# a là biến cục bộ, b là biến toàn cục
# Gia tri cua a la 10 
# Gia tri cua b la 20 

Biến cục bộ (local variable)

  • Biến cục bộ là biến được khai báo bên trong hàm
  • Biến cục bộ chỉ có thể được truy xuất trong phạm vi của hàm đó. Không thể truy xuất biến cục bộ từ bên ngoài và từ các hàm khác
b = 20
def msg():
    a = 10
    print("Gia tri cua b la",b)
    return
msg()
print(a)
# NameError: name 'a' is not defined

Truyền giá trị trong hàm

def changeme(mylist):
   mylist.append([1, 2, 3, 4])
   print("Inside func: ", mylist)
   return

mylist = [10, 20, 30]
changeme([10, 20, 30])
print("Outside func: ", mylist)
Inside func:  [10, 20, 30, [1, 2, 3, 4]]
Outside func:  [10, 20, 30]

Truyền tham chiếu trong hàm

def changeme(mylist):
   mylist.append([1, 2, 3, 4])
   print("Inside func: ", mylist)
   return

mylist = [10, 20, 30]
changeme(mylist)
print(" Outside func: ", mylist)
Inside func:	[10, 20, 30, [1, 2, 3, 4]]
Outside func:[10, 20, 30, [1, 2, 3, 4]]

Truyền tham chiếu trong hàm

def changeme(mylist):
   mylist = [1, 2, 3, 4]
   print(“Inside func: ", mylist)
   return

mylist = [10, 20, 30]
changeme(mylist)
print(" Outside func: ", mylist)
Inside func:	[1, 2, 3, 4]
Outside func: [10, 20, 30]

Tham số hàm (dùng khi định nghĩa hàm)

 Python hỗ trợ các kiểu tham số chính thức sau

  • Tham số bắt buộc
  • Tham số mặc định
  • Tham số từ khóa (tham số được đặt tên)
  • Tham số với số lượng thay đổi

Tham số bắt buộc

  • Các tham số bắt buộc là các tham số được truyền tới một hàm theo một thứ tự chính xác
  • Ở đây, số tham số trong lời gọi hàm nên kết nối chính xác với phần định nghĩa hàm
def mean(a, b):   # Hàm mean(a, b) bắt buộc có 2 tham số
    c = (a + b)/2
    print(c)
mean(5, 10)
mean(5) # TypeError: mean() missing 1 required positional argument: 'b'

Tham số mặc định

  • Tham số mặc định là tham số cung cấp giá trị mặc định cho tham số được truyền trong phần định nghĩa hàm, trong trường hợp giá trị không được cung cấp trong lời gọi hàm
def mean3(a, b, c=0):
    m = (a + b + c)/3
    print(m)
mean3(5, 10, 3)   # -> 6.0
mean(5, 10) # -> 5.0 

Chú ý:

  • Có thể có nhiều tham số mặc định
  • Các tham số mặc định phải đặt sau cùng

Tham số từ khóa

  • Khi sử dụng tham số từ khóa, tham số được truyền trong lời gọi hàm được kết nối với phần định nghĩa hàm dựa trên tên của tham số
  • Vị trí của các tham số trong lời gọi hàm là tùy ý
def msg(id,name):
    print(id)
    print(name)
msg(18123456,"David")
msg(name=“David”,id=18123456)
name = "abc"
id = 16100
msg(name, id)

Giá trị trả về của hàm

  • Hàm có thể trả về bất kỳ kiểu dữ liệu gì hợp lệ trong Python
  • Hàm có thể trả về 1 hoặc nhiều giá trị hoặc không trả về bất cứ giá trị gì
def f1(n):
    f = n**2 + 1
    return f

f = f1(4)
print(f)
def f2(n):
    f = n**2 + 1
    g = n**3 + 1
    h = n + 1
    return f, g, h

f, g, h = f2(3)
print(f,g,h)

f = f2(3)
print(f[1])
def f2(n):
    f = n**2 + 1
    g = n**3 + 1
    h = n + 1
    return [f, g, h]

f = f2(3)
print(f)

[f, g, h] = f2(3)
print(f,g,h)

Hàm với số tham số thay đổi

  • Có thể cần xử lý một hàm mà có số tham số nhiều hơn khi định nghĩa hàm
  • Những tham số này được gọi là các tham số có số tham số thay đổi (variable-length args) và không được đặt tên trong định nghĩa hàm, không giống như các tham số bắt buộc và tham số mặc định

Cú pháp:

def tenHam([thamSoChinhThuc,] *thamSoDuPhong): 
	"function_docstring" 
	function_suite 
	return [bieuThuc] 
def myFun(*argv):
    for arg in argv:
        print (arg)

myFun('Hello', 'Welcome', 'to', 'Viet Nam')
def myFun(arg1, *argv):
print ("First argument :", arg1)     
for arg in argv:
        print ('Next in *argv is:', arg)

myFun('Hello', 'Welcome', 'to', 'Viet Nam')

Hàm nặc danh

  • Hàm nặc danh (hàm vô danh) là hàm không có tên và chúng không được khai báo theo cách chính thức bởi từ khóa def.
  • Để khai báo hàm này, sử dụng từ khóa lambda. Lambda nhận bất kỳ lượng tham số nào và chỉ trả về một giá trị trong dạng một biểu thức đã được ước lượng
  • Không thể gọi trực tiếp gọi hàm nặc danh để in bởi vì lamda cần một biểu thức. Ngoài ra, các hàm lambda có namespace cục bộ của chúng

Cú pháp:

lambda [arg1 [,arg2,.....argn]]:bieu_thuc

Ví dụ:

mean = lambda a,b,c: (a+b+c)/3
print(mean(1,2,3))
aList = lambda a: max(a)*min(a)+len(a)
print(aList([1,5,-3]))

Chú ý: Hàm lambda chỉ trả về duy nhất 1 biểu thức

2. Module

  • Module được sử dụng để phân loại code thành các phần nhỏ hơn liên quan với nhau. Nói cách khác, module giúp tổ chức Python code một cách logic, dễ hiểu và sử dụng hơn
  • Trong Python, module là đối tượng với các thuộc tính có thể đặt tên tùy ý và có thể được gắn kết và tham chiếu
  • Về cơ bản, một module là một file, trong đó các lớp, hàm và biến được định nghĩa. Một module cũng có thể bao gồm code thực thi tác vụ

Lợi thế của module:

  • Khả năng tái sử dụng: module có thể được sử dụng ở trong phần code Python khác, do đó làm tăng tính tái sử dụng code.
  • Khả năng phân loại: Các kiểu thuộc tính tương tự nhau có thể được đặt trong một module

Ví dụ tạo và dùng module mathEM:

  • Tạo một file mathEM.py chứa các hàm bên dưới
def sumEM(a, b):
    return a + b
def multEM(a, b):
    return a * b
def divEM(a, b):
    if b != 0:
        return a/b
    else:
        print('can not divide by 0')
  • Tạo một file mainEM.py gọi module mathEM
import mathEM
a, b = 5, 6
s = mathEM.sumEM(a, b)
print(s)

hoặc

from mathEM import *
a, b = 5, 6
s = multEM(a, b)
print(s)

hoặc

from mathEM import divEM
a, b = 5, 3
s = divEM(a, b)
print(s)