paint-brush
Viết một bài luận dài vô tận bằng cách sử dụng mẫu trạng thái trong Pythontừ tác giả@aayn
2,385 lượt đọc
2,385 lượt đọc

Viết một bài luận dài vô tận bằng cách sử dụng mẫu trạng thái trong Python

từ tác giả Aayush10m2023/12/27
Read on Terminal Reader

dài quá đọc không nổi

Mẫu thiết kế trạng thái là các máy trạng thái trong mã hướng đối tượng. Chúng tôi sử dụng mẫu này để tạo một trình tạo bài luận/câu.
featured image - Viết một bài luận dài vô tận bằng cách sử dụng mẫu trạng thái trong Python
Aayush HackerNoon profile picture
0-item

Hãy viết một bài luận dài vô tận ! Nhưng đó là một nhiệm vụ bất khả thi. Tuy nhiên, chúng ta có thể tạo một quy trình mà nếu chạy mãi mãi sẽ tạo ra một bài luận dài vô tận. Đủ gần .


Bây giờ, rõ ràng bạn có thể tạo một bài luận dài và lặp đi lặp lại chỉ bằng một dòng mã Python:


 >>> "This is water. " * 20 'This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. '


Yaawn … la ó! Thay vào đó, chúng ta sẽ tạo ra một bài luận thú vị hơn nhiều bằng cách sử dụng mẫu thiết kế State trong bài viết này.


Đầu tiên, chúng ta sẽ hiểu máy trạng thái là gì và chúng liên quan như thế nào đến mẫu thiết kế Trạng thái. Tiếp theo, chúng ta sẽ tạo một cỗ máy trạng thái có thể tạo ra một bài luận vô tận và thú vị (hợp lý). Sau đó, chúng ta sẽ xem xét ngắn gọn về mẫu thiết kế trạng thái. Cuối cùng, chúng ta sẽ dịch máy trạng thái đó thành mã hướng đối tượng bằng cách sử dụng mẫu thiết kế trạng thái.


Các mẫu thiết kế phần mềm là những cách hiệu quả để giải quyết các vấn đề thường xảy ra. Khi được áp dụng phù hợp, các mẫu thiết kế phần mềm như mẫu trạng thái có thể giúp bạn viết phần mềm có khả năng mở rộng, bảo trì và kiểm thử tốt hơn.

Máy trạng thái

Về bản chất, mẫu thiết kế Trạng thái chuyển Máy trạng thái thành mã hướng đối tượng.


Nếu bạn không quen với máy trạng thái thì đó là một khái niệm khá đơn giản. Một máy trạng thái có các trạng tháichuyển tiếp . Các trạng thái là những thuộc tính nhất định trong hệ thống mà chúng ta quan tâm và việc chuyển đổi trạng thái là những hành động làm thay đổi những thuộc tính này và do đó cũng gây ra sự thay đổi trạng thái.


Vì tôi có nền tảng về Robot học (trong số những thứ khác) và vì máy trạng thái được sử dụng rộng rãi trong Robotics nên tôi sẽ sử dụng một ví dụ đơn giản về máy hút bụi robot để minh họa cách hoạt động của máy trạng thái.


Máy trạng thái để lái robot hút bụi.


Sơ đồ máy trạng thái vẽ nên một bức tranh trực quan về cách robot hoạt động, ngay cả khi bạn chưa từng gặp phải máy trạng thái. Chúng ta hãy đi qua hoạt động này từng bước một.


  1. Robot khởi động ở trạng thái Docked (chấm đen biểu thị trạng thái bắt đầu).
  2. Nếu robot phát hiện pin yếu, robot sẽ bắt đầu tự sạc ( Trạng thái sạc ) cho đến khi pin đầy. Khi pin đầy, nó sẽ trở về trạng thái Docked .
  3. Ở trạng thái Docked , nếu robot phát hiện sàn bị bẩn (và pin không yếu) thì robot sẽ bắt đầu lau sàn (Trạng thái làm sạch ).
  4. Ở trạng thái Vệ sinh , nếu robot sắp hết pin thì nó sẽ tự sạc. Và nếu sàn nhà sạch sẽ, robot sẽ quay trở lại bến của nó (trạng thái Docked ).


Do đó, máy hút bụi rô-bốt của chúng tôi có ba trạng thái — Đã gắn , Đang làm sạchĐang sạc — và có các chuyển đổi dựa trên khả năng phát hiện cảm giác của sàn nhà và pin của sàn.


Máy trạng thái đơn giản cho bài luận vô hạn

Bây giờ chúng ta đã hiểu về máy trạng thái ở mức cơ bản, hãy tạo một máy trạng thái có khả năng viết một bài luận vô hạn.


Máy trạng thái tạo bài luận vô hạn - phiên bản 1


Trên đây là một máy trạng thái sử dụng ngữ pháp tiếng Anh để tạo ra một bài luận gồm các câu ngắn, đơn giản. Tôi hứa rằng chúng ta sẽ sớm có phiên bản thú vị hơn, nhưng đây sẽ là điểm khởi đầu tốt để hiểu biết. Chúng ta hãy xem xét nó hoạt động như thế nào.


  1. Bắt đầu ở trạng thái Danh từ , chúng ta tạo ra một danh từ bằng cách chọn từ một số danh sách danh từ được xác định trước. Giả sử danh từ của chúng ta là “The World”. (câu cho đến nay: “Thế giới”)
  2. Sau đó, chúng ta kết thúc ở trạng thái Động từ , tạo ra một động từ tiếp theo (ví dụ: “sủa”). (câu cho đến nay: “Thế giới sủa”)
  3. Chúng ta tạo ra một tính từ (ví dụ: “red”) ở trạng thái Tính từ . (câu cho đến nay: “Thế giới sủa màu đỏ”)
  4. Sau đó, ở trạng thái Endmark , chúng tôi tạo ra một trong các dấu chấm câu kết thúc, chẳng hạn như “!”. (câu: “Thế giới sủa màu đỏ!”)
  5. Cuối cùng, chúng ta quay lại trạng thái Danh từ để tạo câu tiếp theo trong bài luận.


Máy trạng thái này có thể tạo ra một bài luận (vô nghĩa) trông như thế này.


Thế giới sủa màu đỏ! Anh họ Harry mưa hôi? Những chú hổ lung linh vui vẻ. …


Máy trạng thái không xác định cho bài luận vô hạn

Mặc dù “không xác định” nghe có vẻ phức tạp nhưng với mục đích của chúng tôi, nó chỉ có nghĩa là thêm vào một số tính ngẫu nhiên. Về cơ bản, chúng tôi đang thêm một kiểu tung đồng xu trước khi chuyển sang một số tiểu bang. Bạn sẽ hiểu ý tôi là gì.

Máy trạng thái không xác định để tạo bài luận vô hạn - phiên bản 2


Máy trạng thái không xác định ở trên rất giống với máy trước đó. Sự khác biệt duy nhất là:

  • Phủ định là những từ như “không” hoặc “không” và liên từ là những từ như “và” và “nhưng”.
  • Ở trạng thái Động từ , chúng ta tạo ra một động từ và sau đó tung đồng xu. Nếu nó chạm mặt ngửa (xác suất 50%), chúng ta chuyển sang trạng thái Phủ định ; nếu không chúng ta sẽ chuyển sang trạng thái Tính từ .
  • Tương tự, ở trạng thái Tính từ , chúng ta tạo ra một tính từ rồi tung đồng xu. Nếu đứng đầu thì chúng ta chuyển sang trạng thái Kết hợp ; nếu là sấp thì chúng ta chuyển sang trạng thái Endmark .


Với việc giới thiệu tính ngẫu nhiên, phủ định và liên từ, giờ đây chúng ta có thể tạo ra các câu có độ dài thay đổi và thú vị hơn.


Mẫu thiết kế trạng thái

Bây giờ, hãy hiểu cách hoạt động của mẫu thiết kế trạng thái. Một lần nữa, hãy nhớ rằng chúng ta đang cố gắng chuyển một máy trạng thái sang mã hướng đối tượng.


Trong máy trạng thái tạo bài luận, hãy quan sát rằng mọi trạng thái đều cần thực hiện hai việc.

  1. Thực hiện một số hành động. Trong trường hợp này, tạo ra một từ (danh từ, tính từ, v.v.).
  2. Chuyển sang trạng thái tiếp theo. Từ Danh từ đến Động từ , v.v.


Từ quan điểm của một quốc gia cụ thể, không có gì khác mà nó cần biết hoặc làm. Thay vì bị sa lầy bởi sự phức tạp của toàn bộ hệ thống - tất cả các trạng thái và chuyển đổi của nó - chúng ta chỉ có thể tập trung vào một trạng thái tại một thời điểm. Theo quan điểm của tôi, kiểu cô lậptách rời này là điểm hấp dẫn nhất của mô hình Bang.


Dưới đây, chúng ta có sơ đồ UML cho mẫu thiết kế Trạng thái. Có một số bối cảnh trong đó mỗi trạng thái hoạt động, được minh họa bởi lớp Context . Đối tượng bối cảnh có một thuộc tính trạng thái riêng, nó sử dụng để gọi trạng thái hiện tại để thực hiện hành động của nó. Mỗi trạng thái triển khai một giao diện State với các phương thức để thực hiện hành động hoặc thao tác của nó và trả về trạng thái tiếp theo.


Sơ đồ UML mẫu thiết kế trạng thái


Nếu chúng ta ánh xạ điều này vào ví dụ tạo bài luận, sơ đồ UML sẽ trông như thế này.


Mẫu trạng thái được triển khai để tạo bài luận


WordState bây giờ là một lớp trừu tượng (được biểu thị bằng chữ in nghiêng) thay vì một giao diện. Các lớp trừu tượng có thể có một số phương thức và thuộc tính trừu tượng (không được triển khai), trong khi các lớp khác có thể được định nghĩa. Các giao diện hoàn toàn trừu tượng: tất cả các phương thức của chúng đều trừu tượng. Tôi đã thực hiện thay đổi này vì việc triển khai generateWord giống nhau ở tất cả các trạng thái và việc tránh mã trùng lặp là điều tốt.


Hãy chia nhỏ từng thuộc tính và phương thức ở trên. Trong lớp EssayContext , chúng ta có:

  • state : Tham chiếu đến đối tượng WordState hiện tại.
  • essayBody : Danh sách tất cả các từ được tạo cho đến nay.
  • setState() : Setter để thay đổi thuộc tính state .
  • addWord() : Phương thức thêm từ tiếp theo vào nội dung bài viết.
  • generateEssay() : Chúng tôi gọi phương thức này để tạo bài luận của mình; chúng tôi dừng lại khi essayBody có chiều dài lớn hơn length .
  • printEssay() : Trả về một chuỗi bài luận được tạo.


Trong lớp trừu tượng WordState , chúng ta có:

  • wordList : Thuộc tính trừu tượng (được biểu thị bằng chữ in nghiêng) cho danh sách các từ mà chúng tôi chọn từ để tạo.
  • generateWord() : Phương thức thêm từ được tạo vào ngữ cảnh bài luận.
  • nextState() : Phương thức trừu tượng để trả về trạng thái tiếp theo.


Chúng tôi sẽ sử dụng NounState làm ví dụ đại diện cho tất cả các trạng thái cụ thể khác được kế thừa từ WordState .

  • wordList : Danh sách các danh từ mà chúng ta chọn từ để tạo.
  • nextState() : Trả về trạng thái tiếp theo.


Bây giờ, chúng ta đã có mọi thứ cần thiết để thực sự triển khai điều này trong mã. Hãy tiếp tục và làm điều đó!


Mã Python

Trước tiên chúng ta hãy viết lớp EssayContext trong một tệp có tên là essay_context.py . Chúng ta sẽ bỏ trường hợp lạc đà và chuyển sang trường hợp rắn bởi vì Python là một... con rắn (xin lỗi).


 from word_state import WordState class EssayContext: def __init__(self, state: WordState): self.state = state self.essay_body: list[str] = [] def set_state(self, state: WordState): self.state = state def add_word(self, word: str): self.essay_body.append(word) def generate_essay(self, length: int): while len(self.essay_body) < length: self.state.generate_word(self) def print_essay(self) -> str: return " ".join(self.essay_body)


Sau đó, hãy thêm các trạng thái vào một tệp có tên word_state.py .


 import abc import numpy as np class WordState(abc.ABC): word_list: list[str] @classmethod def generate_word(cls, context: "EssayContext"): word = np.random.choice(cls.word_list) context.add_word(word) context.set_state(cls.next_state()) @classmethod @abc.abstractmethod def next_state(cls) -> "WordState": pass class NounState(WordState): word_list: list[str] = ["everything", "nothing"] @classmethod def next_state(cls): return VerbState class VerbState(WordState): word_list: list[str] = ["is", "was", "will be"] @classmethod def next_state(cls): heads = np.random.rand() < 0.5 if heads: return NegationState return AdjectiveState class NegationState(WordState): word_list: list[str] = ["not"] @classmethod def next_state(cls): return AdjectiveState class AdjectiveState(WordState): word_list: list[str] = ["fantastic", "terrible"] @classmethod def next_state(cls): heads = np.random.rand() < 0.5 if heads: return ConjunctionState return EndmarkState class ConjunctionState(WordState): word_list: list[str] = ["and", "but"] @classmethod def next_state(cls): return NounState class EndmarkState(WordState): word_list: list[str] = [".", "!"] @classmethod def next_state(cls): return NounState


Cuối cùng, hãy thêm mã để chạy mọi thứ trong main.py .


 from essay_context import EssayContext from word_state import NounState if __name__ == '__main__': ctx = EssayContext(NounState) ctx.generate_essay(100) print(ctx.print_essay())


Chạy python main.py cho chúng ta kết quả đầu ra sau (mỗi lần khác nhau do tính không xác định):


 'everything is not terrible and nothing was terrible ! everything will be not fantastic but everything is fantastic . everything will be fantastic . nothing will be fantastic and nothing will be terrible ! everything was not fantastic and everything will be not terrible . everything was terrible . nothing was terrible but nothing will be fantastic ! nothing is not terrible . nothing was not fantastic but everything was not fantastic ! everything will be not fantastic but everything will be terrible ! everything will be not fantastic . everything is fantastic but nothing will be not terrible ! everything will be not fantastic but nothing was not fantastic !'


Không tệ cho một hệ thống đơn giản như vậy! Chúng ta cũng có thể mở rộng các danh sách từ khác nhau hoặc thêm nhiều trạng thái hơn để làm cho việc tạo bài luận trở nên phức tạp hơn. Chúng tôi thậm chí có thể giới thiệu một số API LLM để đưa bài luận của mình lên một tầm cao mới.


Suy nghĩ cuối cùng

Máy trạng thái và mẫu Trạng thái rất phù hợp để mô hình hóa và tạo ra các hệ thống có khái niệm được xác định rõ ràng về “trạng thái”. Nghĩa là, có những hành vi và thuộc tính cụ thể gắn liền với từng trạng thái. Robot hút bụi đang làm sạch, được gắn đế hoặc đang sạc. TV của bạn có thể BẬT hoặc TẮT và các nút trên điều khiển từ xa của TV sẽ hoạt động khác nhau tùy theo trạng thái của TV.


Nó cũng phù hợp để tạo hoặc xác định các chuỗi có mẫu được xác định rõ. Điều này áp dụng cho ví dụ tạo bài luận của chúng tôi.


Cuối cùng, bạn có thể hỏi, “Tất cả những điều này có ý nghĩa gì?” Tại sao chúng ta lại phải tốn nhiều công sức để xác định các trạng thái và giai cấp khác nhau để tạo ra bài luận “vô hạn” này? Chúng ta có thể viết 20 (hoặc ít hơn) dòng mã Python để đạt được hành vi tương tự.


Câu trả lời ngắn gọn là để có khả năng mở rộng tốt hơn.


Hãy tưởng tượng nếu thay vì chỉ ba hoặc năm tiểu bang, chúng ta có 50 hoặc 500 tiểu bang. Đây không phải là cường điệu; hệ thống doanh nghiệp thực sự có mức độ phức tạp đó. Đột nhiên, mẫu Trạng thái có vẻ hấp dẫn hơn nhiều vì tính tách rời và cô lập của nó. Chúng ta chỉ có thể tập trung vào một trạng thái tại một thời điểm mà không cần phải ghi nhớ toàn bộ hệ thống trong đầu. Việc đưa ra các thay đổi sẽ dễ dàng hơn vì một trạng thái sẽ không ảnh hưởng đến các trạng thái khác. Nó cũng cho phép kiểm tra đơn vị dễ dàng hơn, một phần quan trọng của hệ thống có thể mở rộng và bảo trì.


Cuối cùng, mô hình Bang không chỉ là quản lý các bang; giống như tất cả các mẫu thiết kế, nó là một kế hoạch chi tiết để xây dựng các hệ thống có khả năng mở rộng và bảo trì cũng như độ phức tạp của chúng.