Sự khác nhau giữa Return và Print trong Python?

Hiện tại em vừa học qua bài về hàm . Đây là bài tập của em để tính ax^2 +bx +c = 0

def quadSolver():
    import math
    nNum1 = int(input("Enter number a: "))
    nNum2 = int(input("Enter number b: "))
    nNum3 = int(input("Enter number c: "))
    nNumDelta = (nNum2 * nNum2) - 4 * nNum1 * nNum3
    if nNumDelta > 0:
        nRoot1 = (- nNum2 + math.sqrt(nNum2 * nNum2 - 4 * nNum1 * nNum3)) / ( 2 * nNum1)
        nRoot2 = (- nNum2 - math.sqrt(nNum2 * nNum2 - 4 * nNum1 * nNum3)) / ( 2 * nNum1)
        print("The function has 2 real roots:", nRoot1, ",", nRoot2)
    elif nNumDelta == 0:
        nRoot3 = - nNum2 / (2 * nNum1)
        print("The function has 1 real root:", nRoot3)
    else:
        print("The function has no real roots")

quadSolver()

Vấn đề em thắc mắc là khi đã quen dần rồi thì có nên lưu ý khi nào dùng return hay là print không?
Vì như bài ở trên nếu em dùng return thì nó cũng không khác nhau. Nếu khác thì khi dùng return thì em phải thêm print() vào quadSolver()…
Hoặc các a.c học trước có thể cho em lưu ý thêm khi dùng hai cái này trong hàm với.
Em cảm ơn.

2 Likes

Programming is the art of doing one thing at a time
Michael Feathers -


Cậu tìm ra điểm khác biệt rồi đó! :smile: Điểm khác biệt lớn nhất là khi cậu return về giá trị, cậu cần print ở chỗ gọi hàm quadSolver().

Thường thì cậu nên return giá trị về để caller in ra kết quả, hơn là dùng print() trong chính hàm đó để in ra kết quả. Lý do ở đây là Single-responsibility principle (nguyên lý đơn nhiệm).
Trong hàm quadSolver mà cậu viết, nó thực hiện các nhiệm vụ dưới đây:

  1. Lấy giá trị a, b, c từ bàn phím.
  2. Tính toán nghiệm.
  3. Viết ra màn hình kết quả các nghiệm.

Với tên hàm quadSolver, lẽ ra nó chỉ có duy nhất 1 nhiệm vụ là tính toán nghiệm từ 3 giá trị a, b, c cậu đưa cho. Nó không nên quan tâm tới 3 giá trị a, b, c cậu lấy được như thế nào (nơi gọi nó nên lo việc này), cũng không quan tâm cậu làm gì với kết quả (nơi gọi nó cũng nên lo việc này).

Câu hỏi đặt ra bây giờ là tại sao mỗi hàm lại nên đơn nhiệm - chỉ làm duy nhất 1 nhiệm vụ?
Lý do là hàm đơn nhiệm chỉ có duy nhất 1 lý do để thay đổi thôi :smile:
Thử xét các kịch bản dưới đây:

  • Nếu chương trình của cậu thay vì đọc từ bàn phím, mà đọc từ file. Hàm quadSolver của cậu giờ đây phải sửa lại đoạn đọc a, b, c từ file.
    Lúc này cậu phải test lại toàn bộ hàm ở cả 3 thao tác.
  • Nếu chương trình của cậu thay vì ghi ra stdout, mà cần ghi kết quả ra database, cậu cần sửa lại phần print.
    Lúc này cậu phải test lại toàn bộ hàm ở cả 3 thao tác.
  • Nếu cậu phải phát triển một chương trình có giao diện đồ họa để giải phương trình bậc 2, cậu không thể sử dụng lại hàm quadSolver do nó in ra stdout, mà phải viết lại hàm này.

Đó là điểm khác biệt lớn nhất giữa hàm quadSolver, sử dụng print để in ra kết quả ngay trong hàm, và hàm quadSolver nào khác return kết quả, và để caller sử dụng kết quả đó vào việc mình cần. Việc tuân thủ Single-responsibility principle cũng sẽ giúp cậu chia nhỏ bài toán to thành các bài toán nhỏ, cài đặt một cách dễ dàng, dễ để test, và dễ dàng tái sử dụng các cài đặt đó, như cách cậu lắp Lego vậy :smile:

5 Likes

do em mới học nên chưa hiểu lắm, có gì để em search đọc thêm rồi em hỏi riêng anh được không?

Về phần code anh nói vậy thì em thay thành như này là hợp lí chưa anh

def quadSolver(a_nNum1, a_nNum2,a_nNum3):
import math
nNumDelta = (a_nNum2 * a_nNum2) - 4 * a_nNum1 * a_nNum3
if nNumDelta > 0:
    nRoot1 = (- a_nNum2 + math.sqrt(a_nNum2 * a_nNum2 - 4 * a_nNum1 * a_nNum3)) / ( 2 * a_nNum1)
    nRoot2 = (- a_nNum2 - math.sqrt(a_nNum2 * a_nNum2 - 4 * a_nNum1 * a_nNum3)) / ( 2 * a_nNum1)
    return nRoot1, nRoot2
elif nNumDelta == 0:
    nRoot3 = - a_nNum2 / (2 * a_nNum1)
    return nRoot3
else:
    return 

...

a_nNum1 = int(input("Enter number a: "))
a_nNum2 = int(input("Enter number b: "))
a_nNum3 = int(input("Enter number c: "))
print(quadSolver(a_nNum1, a_nNum2,a_nNum3))

Tuy nhiên đối với code này thì em lại gặp vấn đề khi nếu là 2 nghiệm, chẳng hạn 2 và -3
thì nó sẽ in ra là (2, -3)
nên kiểu có cách nào để em xét sao để có thể kèm print đi kèm không anh?

Ohm, câu hỏi hay đấy cậu :smile:

Disclaimer: Tớ không phải chuyên gia về python.
Implement trên của cậu trông ổn đấy. Ở ngoài chỗ gọi, có lẽ cậu nên cân nhắc viết thêm if-else để print giá trị, dựa trên kích thước của kết quả trả về, nếu cậu cần các thông điệp khác nhau cho các TH khác nhau.
1 thông điệp tổng quát có lẽ lẽ giúp cậu hạn chế if-else:

print("Roots: ", quadSolver(a_nNum1, a_nNum2,a_nNum3))

Cậu có thể return luôn câu mà cậu muốn in (tớ không recommend cách này, vì quadSolver không nên quan tâm tới việc cậu làm gì với kết quả).
Tớ không rõ có cách implement nào elegant hơn sử dụng trong python không, thế nên có lẽ cậu nên chờ các bạn khác giúp nếu như cậu không thỏa mãn với câu trả lời trên :smile:

5 Likes

Em cảm ơn anh nhiều ạ.
Cá nhân anh thì anh thích cách 2 em làm hơn cách 1 ạ, dù kiểu cá nhân em thì thấy cách 1 nó chi tiết và kiểu đầy đủ hơn.
Như anh nói thì em có thể thêm vào string ở chỗ in là

print("Roots: ", quadSolver(a_nNum1, a_nNum2,a_nNum3))

Với lại như anh đã học programming lâu rồi thì sau này nếu em làm các project thì tuy không ai ép là em không được print, không được cho input trong function nhưng em nên tự hiểu là chỉ để hàm def tính toán và return, hạn chế print luôn tốt hơn dù nhiều khi output nhìn không được bằng?
Lúc nãy ngồi học chung nó cũng hỏi là sao không dùng print, thì em cũng chỉ biết giải thích print thì khi gọi hàm không cần print nữa, chắc lí do chủ yếu như anh đề cập đó là đơn nhiệm.
Còn về các ý trong kịch bản anh nói thì có gì em từ từ đọc rồi hỏi anh thêm ha.
Em cảm ơn nhiều ạ.

2 Likes

Giá trị “null” trong Python là None có thể dùng cho trường hợp vô nghiệm.
Nếu có nghiệm thì dùng tuple cũng được vì tuple cũng có len(). Nhưng cú pháp tuple phù hợp với format string hơn là f-string (hay print).

4 Likes

Hàm print dùng để in kết quả ra màn hình, trong khi lệnh return dùng để trả về giá trị từ một hàm nha.

Return trong python là một từ khóa (keyword) dùng để trả về giá trị từ hàm. Return có tác dụng kết thúc hàm và trả lại điều khiển cũng như kết quả xử lý hàm cho người gọi. Chúng ta có thể sử dụng hoặc lược bỏ return khi khai báo hàm trong python, và một hàm có chứa return trong python được gọi là hàm trả về giá trị trong python .
Nguồn :Return trong python và giá trị trả về | Lập trình căn bản - học lập trình theo phong cách Nhật Bản

Em có thể dùng hàm print để in trực tiếp kết quả trong hàm, hoặc là dùng lệnh return để lấy kết quả trả về từ hàm, sau đó dùng print để in kết quả này.
Ví dụ em có thể viết lại chương trình trên với lệnh return như sau:

def quadSolver():
    import math
    nRoot1 = nRoot2 = nRoot3 = ""
    nNum1 = int(input("Enter number a: "))
    nNum2 = int(input("Enter number b: "))
    nNum3 = int(input("Enter number c: "))
    nNumDelta = (nNum2 * nNum2) - 4 * nNum1 * nNum3
    if nNumDelta > 0:
        nRoot1 = (- nNum2 + math.sqrt(nNum2 * nNum2 - 4 * nNum1 * nNum3)) / ( 2 * nNum1)
        nRoot2 = (- nNum2 - math.sqrt(nNum2 * nNum2 - 4 * nNum1 * nNum3)) / ( 2 * nNum1)
        print(nRoot1,nRoot2)
    elif nNumDelta == 0:
        nRoot1 = - nNum2 / (2 * nNum1)
    else:
        pass

    return nRoot1, nRoot2

nRoot1,nRoot2 = quadSolver()

if nRoot1 != "" and nRoot2 != "":
    print("The function has 2 real roots:", nRoot1, ",", nRoot2)
else:
     print("The function has no real roots")
1 Like

Anh da đen mãi mãi là người đến sau :sob:

3 Likes

Phương trình bậc 2 chỉ có tối đa 2 nghiệm thôi, tại sao phải khai báo thêm nghiệm thứ 3?

Bạn khai báo nNumDelta, sao không dùng tiếp ở trong if?

Code của bạn thớt đã đưa 3 dòng input() ra ngoài hàm, bạn cũng nên làm như vậy (theo quy tắc SOLID):

def quadSolver(nNum1, nNum2, nNum3):
    nNumDelta = ...
    # tiếp tục code tiếp ở đây
    return ...


if __name__ == '__main__':
    num1, num2, num3 = map(int, [input(), input(), input()])
    print(quadSolver(num1, num2, num3))
3 Likes

Cảm ơn bạn @noname00 đã góp ý nhé.
Đúng là ở phần lệnh trong khối elif và else mình chưa xem kỹ và đã bỏ sót. Xin ghi nhận ạ.
Mình quá tập trung vào giải thích sự khác nhau giữa việc dùng hàm print ở bên trong hàm, và ở bên ngoài hàm, cũng như khác nhau giữa print và lệnh return nên đã ghi thiếu điều kiện trong khối elif và khối else trong chương trình của chủ thớt, xin lỗi nhá :sweat_smile:

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?