2009-03-18 21 views
7

Câu hỏi gốcPython: là nó ok trả lại cả boolean và chuỗi?

Tôi đã thực hiện một chức năng đang chờ một chuỗi cụ thể xuất hiện trên cổng nối tiếp và trả về tất cả ký tự đọc cho đến khi chuỗi được tìm thấy hoặc false nếu không. Điều này là khá thuận tiện, nhưng tôi đã tự hỏi nếu nó được coi là thực hành xấu hay không?

Làm rõ:

Mục đích chính là để chờ một đặc biệt chuỗi xuất hiện trong một khoảng thời gian nhất định. Ngoại trừ lỗi IO, kết quả có thể là True (chuỗi đã xuất hiện) hoặc False Mục tiêu thứ hai là lấy toàn bộ đầu ra, vì có thể có thông tin mà tôi muốn phân tích trước câu trả lời thực tế được tìm kiếm. Tôi nghĩ có thể tôi có thể kết hợp mục tiêu chính và phụ trong một giá trị trả lại.

def MyFunc(s, timeout) : 
    test = get_some_input(timeout) 
    if test.endswith(s) 
     return test 
    else 
     return False 

Chỉnh sửa: Một câu trả lời được đề xuất khác là đưa ra ngoại lệ. Tôi không nghĩ rằng đó là một ý tưởng tốt, bởi vì thời gian chờ là một hành vi mong đợi. Tôi có nghĩa là, nếu có một tham số để xác định một thời gian chờ, sau đó một thời gian chờ là một kết quả có thể, và không phải là một ngoại lệ.

Chỉnh sửa 2: Vì tôi cần lưu trữ đầu vào, có thể sử dụng một lớp là giải pháp phù hợp. Việc đợi hàm có giá trị trả về rõ ràng, nhưng toàn bộ chuỗi đã được đọc cho đến khi hết thời gian chờ.

class Parser : 
     def __init__(self, sport_name): 
       self.currentMsg = '' 
       self.ser = serial.Serial(sport_name, 115200) 
     def WaitFor(self, s, timeOut=None): 
       self.ser.timeout = timeOut 
       self.currentMsg = '' 
       while self.currentMsg.endswith(s) != True : 
         # should add a try catch here 
         c=self.ser.read() 
         if c != '' : 
           self.currentMsg += c 
         else : 
           print 'timeout waiting for ' + s 
           return False 
       return True 

Trả lời

6

Sẽ tốt hơn nếu trả về chuỗi và boolean (như trong tiêu đề) thay vì trả về chuỗi HOẶC boolean. Bạn không cần phải tìm ra ý nghĩa của giá trị trả về. Nó nên được hoàn toàn rõ ràng và các vấn đề trực giao nên được tách ra thành các biến khác nhau.

(okay,value) = get_some_input(blah); 
if (okay): print value 

Tôi có xu hướng không trả lại nhiều dữ liệu vì nó cảm thấy buồn cười. Nhưng nó hoàn toàn hợp lệ để làm như vậy.

Trả về "Không" là giải pháp hợp lệ, đã được đề cập ở đây.

+0

Điều trực giao đó là hoàn toàn đúng. Vì vậy, trả về một tuple sẽ là một giải pháp tốt, tuy nhiên tôi chưa rất thoải mái với điều này, cộng với việc sử dụng một lớp cho phép tôi nhúng một cổng nối tiếp vào nó, và cho phép mở rộng thêm. – shodanex

+0

vì vậy, giá trị sẽ là gì nếu được chấp nhận là sai? – SilentGhost

+0

@SilentGhost: giá trị luôn là đầu vào được đọc cho đến nay (cho đến khi tìm thấy chuỗi hoặc hết thời gian chờ). – jfs

25

Sẽ không phù hợp hơn để trả lại None thay vì False?

+0

có, Không có cách nào phù hợp hơn –

+0

nhưng như được mô tả trong các câu trả lời khác, ngoại lệ thậm chí còn hơn Pythonic. –

+0

Một ngoại lệ không phải là Pythonic trong trường hợp này. Nhìn vào hành vi của thư viện chuẩn - cụ thể select.select và re.match. –

5

Điều thuận tiện là trả về một chuỗi rỗng trong trường hợp này.

Bên cạnh một chuỗi rỗng trong Python sẽ đánh giá là False. Vì vậy, bạn có thể gọi nó là:

if Myfunc(s, timeout): 
    print "success" 

Bổ sung: Như được chỉ ra bởi S.Lott đúng cách Pythonic là trả về Không. Mặc dù tôi chọn trả về chuỗi trong chuỗi có liên quan đến chuỗi. Một vấn đề ưu tiên thực sự.

Ngoài ra tôi giả định người gọi Myfunc chỉ quan tâm đến việc nhận một chuỗi để thao tác trên - trống hay không. Nếu người gọi cần kiểm tra về các vấn đề thời gian chờ, vv .. tốt hơn là sử dụng ngoại lệ hoặc trả lại Không.

+0

Sự cố với thiết kế này là nó không phân biệt giữa thời gian chờ trong một trường hợp, và s và kiểm tra bằng "". –

+0

-1: Không hẳn là Pythonic. Chuỗi rỗng vẫn là chuỗi. Không có gì tốt hơn. Một ngoại lệ vẫn tốt hơn. –

+0

Cả hai điểm hợp lệ, đã chỉnh sửa câu trả lời. –

3

Có thể nếu bạn trả về một tuple như (False, None) và (True, test) nó sẽ tốt hơn, vì bạn có thể đánh giá chúng một cách tách biệt và không thêm độ phức tạp không cần thiết.

CHỈNH SỬA: Có lẽ chuỗi xuất hiện trên cổng nối tiếp là "" (có thể được mong đợi), vì vậy việc trả về True có thể nói rằng nó đã đến theo cách đó.

+0

Tôi muốn đi theo cách @jelovirt: thử nghiệm cho Không rõ ràng và không thực sự thêm sự phức tạp. –

+0

Tôi đã luôn luôn giống như các tuples python để trả về nhiều giá trị. +1. – paxdiablo

+0

Tôi thích ý tưởng này, việc trả lại cờ điều khiển trong cùng trường giá trị không đúng với tôi. Trong trường hợp đó, bạn có nguy cơ trong tương lai các giá trị hợp lệ thay đổi (như bạn đã nói, cho phép null) và cờ điều khiển không hợp lệ. – Sam

5

Bạn có thể trả lại chuỗi nếu đến đúng giờ hoặc tăng ngoại lệ phù hợp cho biết thời gian chờ.

+0

Thậm chí nếu tăng ngoại lệ trong Python là không tốn kém so với các ngôn ngữ khác, tôi không nghĩ rằng việc cung cấp chức năng sử dụng chúng là một ý tưởng tuyệt vời. – Martin

+0

+1: Ngoại lệ có ý nghĩa hơn trong trường hợp này - bạn đã có điều kiện "ngoại lệ" - thời gian chờ. –

+0

Trong thực tế, tôi đã sử dụng mô hình này rất nhiều và rất thành công trong một dự án sử dụng giao tiếp thông qua cổng nối tiếp vv Thời gian ra ngoại lệ xử lý retries, gửi lại các điều kiện khá tốt. – Ber

10

Tôi tin rằng thiết kế Python chính thống sẽ trả về Không. Các manual nói:

Không

loại này có giá trị duy nhất. Có một đối tượng duy nhất có giá trị này.Đối tượng này được truy cập thông qua tên được tích hợp Không có. Nó được sử dụng để biểu thị sự vắng mặt của một giá trị trong nhiều trường hợp , ví dụ: nó được trả lại từ các hàm không trả lại rõ ràng bất kỳ điều gì. Giá trị thật của nó là sai.

2

Để thêm vào điểm của Ber, bạn có thể muốn tính đến điều gì đó khác. Nếu bạn sử dụng một chuỗi rỗng hoặc Không có gì, bạn để cửa mở cho các lỗi của loại "câm". Mặt khác, nếu bạn đưa ra một ngoại lệ, bạn buộc phải thực thi bất kỳ hoạt động nào đang chạy để bị hủy bỏ.

Ví dụ, hãy xem xét đoạn mã sau:

result = MyFunc(s, timeout) 
if result[0] == 'a': 
    do_something() 

này sẽ nâng cao một ngoại lệ nếu các hoạt động timed out và có hoặc là một chuỗi rỗng hoặc Không. Vì vậy, bạn phải thay đổi điều đó thành:

result = MyFunc(s, timeout) 
if result and result[0] == 'a': 
    do_something() 

Những loại thay đổi này có xu hướng tăng lên và làm cho mã của bạn khó hiểu hơn.

Tất nhiên, tôi chắc chắn rằng câu trả lời của bạn cho điều này sẽ là một cái gì đó dọc theo dòng "Tôi sẽ không làm điều đó" hoặc "điều đó sẽ không xảy ra" mà câu trả lời của tôi là "Ngay cả khi bạn không ' T chạy vào nó với chức năng này, bạn sẽ cuối cùng nếu bạn thực hiện một thói quen làm điều này. " Các loại lỗi này hầu như luôn là kết quả của các trường hợp góc mà bạn thường không nghĩ đến.

1

Đây là trường hợp sử dụng cổ điển cho máy phát Python. Từ khóa yield cung cấp một cách đơn giản để lặp qua tập hợp rời rạc mà không trả lại toàn bộ sự việc cùng một lúc:

def MyFunc(s, timeout) : 
    test = get_some_input(timeout) 
    while test.endswith(s) 
     yield test 
     test = get_some_input(timeout) 

for input in MyFunc(s, timeout): 
    print input 

Mấu chốt ở đây là không có giá trị trả về để xác định khi kết thúc đầu vào; thay vào đó, bạn chỉ cần đến cuối trình lặp. Thông tin thêm về máy phát điện here.

Các vấn đề liên quan