Hàm classmethod() trong Python

Trong Python, hàm classmethod() trả về một phương thức class cho hàm. Cú pháp của hàm classmethod() như thế nào, nó có những tham số gì và cách sử dụng ra sao? Mời bạn đọc theo dõi.

Cú pháp hàm classmethod() trong Python

classmethod(function)

classmethod() được coi là un-Pythonic (ngôn ngữ không chính thống của Python), vì vậy trong các phiên bản mới hơn của Python, bạn nên sử dụng decorator @classmethod để xác định phương thức

Cú pháp như sau:

@classmethod
def func(cls, args...)

Các tham số của hàm classmethod()

  • classmethod() chỉ có một tham số duy nhất là function - hàm cần được truyền vào classmethod

Giá trị trả về từ classmethod()

Theo định nghĩa, classmethod() trả về một class method cho hàm đã cho.

Vậy class method ở đây là gì?

Class method là phương thức thuộc về cả class. Khi thực thi, nó không dùng đến bất cứ một instance nào của class đó, khá giống với staticmethod.

Tuy nhiên có một vài khác biệt giữa static methodclass method như:

  • static method không sử dụng bất cứ thứ gì liên quan đến class hay instance của class đó mà chỉ làm việc với các tham số.
  • Với class method thì cả class sẽ được truyền thành tham số thứ nhất (cls) của phương thức này.
  • Class method thì có thể được gọi từ cả class và object của nó.
Class.classmethod()
Or even
Class().classmethod()

Class method luôn gắn liền với class vì ngầm gán class cho tham số thứ nhất (cls) khi gọi hàm.

def classMethod(cls, args...)

Ví dụ 1: Tạo phương thức class (class method) sử dụng classmethod()

class Nhanvien:
tuoi = 25

def printTuoi(cls):
print('Số tuổi là:', cls.tuoi)

# tạo phương thức class printTuoi
Nhanvien.printTuoi = classmethod(Nhanvien.printTuoi)

Nhanvien.printTuoi()

Ở đây, chúng ta có một class Nhanvien, với biến độ tuổi thành viên (tuoi) được gán cho 25.

Chúng ta cũng có một hàm printTuoi lấy một tham số cls không thường dùng.

cls chấp nhận class Nhanvien như một tham số thay vì object/instance của Nhanvien.

Bây giờ, ta truyền phương thức Nhanvien.printTuoi làm đối số cho hàm classmethod. Điều này chuyển đổi phương thức (method) thành một phương thức lớp (class method) để nó chấp nhận tham số đầu tiên là một class (tức là Nhanvien).

Trong dòng cuối cùng, chúng ta gọi printTuoi mà không tạo đối tượng Nhanvien như trong static method.

Chạy đoạn mã trên, chương trình sẽ trả về kết quả là:

Số tuổi là: 25

Khi nào thì sử dụng class method?

1. Factory method

Factory method là những phương pháp trả về một đối tượng của class theo các cách khác nhau.

Giống như nạp chồng hàm trong C++, nhưng Python thì không có nên ở đây ta sử dụng class method và static method.

Ví dụ 2: Tạo factory method sử dụng class method

from datetime import date

# random Nhanvien
class Nhanvien:
def __init__(self, ten, tuoi):
self.ten = ten
self.tuoi = tuoi

@classmethod
def fromBirthYear(cls, ten, birthYear):
return cls(ten, date.today().year - birthYear)

def ketqua(self):
print("Tuổi của " + self.ten + " là: " + str(self.tuoi))

nhanvien = Nhanvien('Alice', 23)
nhanvien.ketqua()

nhanvien1 = Nhanvien.fromBirthYear('Simon', 1990)
nhanvien1.ketqua()

Chương trình trả về kết quả là:

Tuổi của Alice là: 23
Tuổi của Simon là: 28

Ở đây chúng ta có hai instance class, một được tạo ra, một là class method fromBirthYear.

Instance được tạo ra lấy tham số tên (ten) và tuổi (tuoi), fromBirthYear lấy thông tin từ class, tenbirthYear rồi tính toán độ tuổi hiện tại bằng cách sử dụng năm hiện tại trừ đi birthYear và trả về kết quả class instance.

Phương thức fromBirthYear nhận thông tin từ class Nhanvien (Không phải object Nhanvien) dưới dạng tham số cls và trả về một hàm là cls(ten, date.today().year - birthYear) tương đương với Nhanvien(ten, date.today().year - birthYear).
Điều này có được nhờ decorator @classmethod. Chính decorator này đã biến đổi phương thức fromBirthYear của class method bằng classmethod().

2. Tạo đối tượng chính xác (correct instance) trong Kế thừa (inheritance).

Kế thừa (inheritance) là sử dụng lại thuộc tính và hàm của một class để định nghĩa một class mới. Class mới được tạo ra gọi là class con (child class hoặc derived class), class được kế thừa gọi là class cha (base class hoặc parent class).

Nếu bạn dẫn xuất được một class từ việc tạo factory method sử dụng classmethod thì nó chắc chắn tạo ra đối tượng chính xác trong class con.

Bạn cũng có thể làm tương tự nhưng sử dụng staticmethod, đối tượng tạo ra chắc chắn nằm trong lớp cha.

Ví dụ 3: Cách class method hoạt động trong inheritance

from datetime import date

# random Person
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

@staticmethod
def fromFathersAge(name, fatherAge, fatherPersonAgeDiff):
return Person(name, date.today().year - fatherAge + fatherPersonAgeDiff)

@classmethod
def fromBirthYear(cls, name, birthYear):
return cls(name, date.today().year - birthYear)

def display(self):
print(self.name + "'s age is: " + str(self.age))

class Man(Person):
sex = 'Male'

man = Man.fromBirthYear('John', 1985)
print(isinstance(man, Man))

man1 = Man.fromFathersAge('John', 1965, 20)
print(isinstance(man1, Man))

Chương trình trả về kết quả là:

True
False

Ví dụ này sử dụng một static method để tạo một lớp có kiểu dữ liệu được fix cứng trong khi tạo.

Điều này gây ra một vấn đề khi kế thừa Man từ Person.

Phương thức fromFathersAge không trả về đối tượng ở Man mà trả về đối tượng ở lớp Person - lớp cha.

Điều này vi phạm mô hình OOP. Sử dụng class method fromBirthYear có thể đảm bảo mô hình OOP của code vì nó lấy tham số đầu tiên là chính class được truyền vào cùng factory method của nó.

Xem thêm:

Bài trước: Hàm chr() trong Python

 Bài tiếp: Hàm complex() trong Python

Thứ Tư, 12/12/2018 17:42
31 👨 77