4 điều tôi ước nên biết sớm hơn về hàm trong Python

Sau blog lần trước được đón nhận rất tốt, tôi quyết định viết thêm phần 2

4 điều tôi ước nên biết sớm hơn về hàm trong Python, và tip số 7 sẽ khiến bạn vô cùng bất ngờ đấy

4. Hàm bậc cao hơn

Hàm bậc cao hơn là :

  1. Hàm lấy các hàm khác làm đối số
  2. Hàm trả về một hàm khác
  3. Cả 1 và 2

Ví dụ :

def apply(func, x):
  return func(x)

x = apply(lambda x:x+10, 7)
print(x)    # 17

^ từ ví dụ trước của chúng ta, hàm apply là hàm bậc cao hơn khi nó có trong một hàm khác func

Nếu nhìn lại code base của mình, bạn sẽ khá ngạc nhiên khi có thể chuyển rất nhiều hàm về loại hàm bậc cao đấy. Đây là một ý tưởng rất hay mà bạn nên áp dụng thử nhé !

5. Decorators

Decorator là một loại hàm bậc cao đặc biệt. Mục đích của người sử dụng decorator là thay đổi hành vi của một hàm khác mà không thay đổi source code của nó.

Lưu ý : Hàm Decorator nhận vào một hàm và trả về một hàm

Ví dụ :

def add_exclamation(func):
  def wrapper(name):
    return func(name) + '!'
  return wrapper

def hello(name):
  return 'hello ' + name

hello = add_exclamation(hello)

print(hello('Cat'))    # hello Cat!

Hãy thử sử dụng @add_exclamation thay vì hello = add_exclamation(hello) và bạn sẽ thấy nó hoạt động tương tự nhưng code sẽ ngắn gọn hơn rất nhiều

def add_exclamation(func):
  def wrapper(name):
    return func(name) + '!'
  return wrapper

@add_exclamation
def hello(name):
  return 'hello ' + name

print(hello('Cat'))    # hello Cat!

Vậy khi nào thì nên sử dụng Decorator ?

Những thứ chúng tôi sử dụng Decorator cho Code base như lưu log,  timer, handle exeptions, authen, rest api, v.v. Có lẽ cũng là một ý tưởng hay để làm quen với Decorator!

6. Generator function

Bạn đã bao giờ nhìn thấy thứ gì đó giống như <generator object x at 0x1029b4a90> chưa? Điều này xảy ra khi chúng ta có hàm tạo. Và tôi thấy điều này nhiều hơn trong code khi bạn đi làm thay vì đống code khi bạn đang đi học.

Một hàm sẽ trở thành hàm tạo khi chúng ta sử dụng yield. yield giống như từ khóa return ở chỗ nó xuất ra một giá trị từ một hàm, nhưng yield không dừng toàn bộ hàm giống như return.

#hàm bình thường
def test():
  return [1, 2, 3]

x = test()
print(x)    # [1, 2, 3]
# Hàm theo kiểu generator, nhưng gọi như hàm bình thường
def test():
  yield 1
  yield 2
  yield 3

x = test()
print(x)    # <generator object x at 0x1029b4a90>
# Hàm generator nhưng call bằng loop
def test():
  yield 1
  yield 2
  yield 3

for i in test():
  print(i, end=' ')

# 1 2 3

Một generator có thể hiểu là nó chỉ thực hiện công việc khi thực sự cần thiết (tức là khi chúng ta sử dụng một vòng lặp). Điều này thực sự có thể làm cho code của chúng ta hiệu quả hơn ở một vài trường hợp nhất định.

7. Các phương thức đặc biệt (Dunder)

Các phương thức đặc biệt (Dunder) được tạo ra để cung cấp một cách để tùy chỉnh hoặc mở rộng hành vi của các đối tượng trong Python.

Chúng cũng có ở khắp mọi nơi trong code Python khi bạn đi làm, đặc biệt là khi có liên quan đến OOP.

Một phương thức đặc biệt bắt đầu và kết thúc bằng 2 ký tự gạch dưới, ví dụ __init__ __str__ __getitem__ __add__, v.v. Và họ xác định hành vi đặc biệt trong các Class Python.

Đây là một số phương thức Dunder quan trọng:

  1. __init__: Khởi tạo một đối tượng khi nó được tạo ra.
  2. __str__: Trả về phiên bản chuỗi của một đối tượng khi nó được chuyển thành chuỗi.
  3. __repr__: Trả về biểu diễn của một đối tượng, thường là dùng để tái tạo đối tượng.
  4. __len__: Trả về độ dài của một đối tượng.
  5. __getitem__: Lấy một phần tử từ một đối tượng bằng cách sử dụng chỉ số hoặc khóa.
  6. __setitem__: Đặt một giá trị cho một phần tử trong đối tượng bằng cách sử dụng chỉ số hoặc khóa.
  7. __delitem__: Xóa một phần tử từ đối tượng bằng cách sử dụng chỉ số hoặc khóa.
  8. __iter__: Trả về một iterator cho đối tượng.
  9. __next__: Lấy phần tử tiếp theo trong iterator.
  10. __call__: Cho phép một đối tượng được gọi như một hàm.
  11. __add__, __sub__, __mul__, __truediv__: Định nghĩa các phép toán cộng, trừ, nhân, chia.
class Dog:
  # defines how attributes are assigned to dog
  def __init__(self, name, age):
    self.name, self.age = name, age

  # defines what is returned when we str(dog)
  def __str__(self):
    return 'Dog!'

  # defines what is returned when we dog + something
  def __add__(self, something):
    return 'Dog ' + str(something)

  # defines what is returned when we dog[something]
  def __getitem__(self, something):
    return 123

Yeah, hi vọng bạn thích những tip của tôi

Blog của hôm nay đã kết thúc rồi, hẹn gặp lại vào lần tới nhé

Tags:,

Add a Comment

Scroll Up