Làm thế nào để nâng cao một ValueError?


115

Tôi có mã này tìm chỉ mục lớn nhất của một ký tự cụ thể trong một chuỗi, tuy nhiên tôi muốn nó nâng lên một ValueErrorkhi ký tự được chỉ định không xuất hiện trong một chuỗi.

Vì vậy, một cái gì đó như thế này:

contains('bababa', 'k')

sẽ dẫn đến:

ValueError: could not find k in bababa

Tôi có thể làm cái này như thế nào?

Đây là mã hiện tại cho chức năng của tôi:

def contains(string,char):
  list = []

  for i in range(0,len(string)):
      if string[i] == char:
           list = list + [i]

  return list[-1]

5
Cứ như vậy, tăng ValueError () hahaha
slzica

@ user531225: Bạn có thể chấp nhận một số câu trả lời khác để tôi có thể xóa của tôi. Cảm ơn :)
pyfunc

@ THC4k: Kỳ lạ đến mức nó trả về vị trí của lần xuất hiện ngoài cùng bên phải thay vì số lượng.
John Machin

@ErikAllik: Rõ ràng là anh ấy đã làm vậy - anh ấy đã đăng lên StackOverflow. Có gì sai với điều đó?
Michael Scheper

Câu trả lời:


178

raise ValueError('could not find %c in %s' % (ch,str))


2
Bạn có biết rằng, nếu bạn không muốn sử dụng tin nhắn, bạn có thể chỉ cần raise ValueErrorthay vì raise ValueError()?
Tomasz Gandor

27

Đây là phiên bản sửa đổi của mã của bạn vẫn hoạt động cộng với nó minh họa cách nâng cao một ValueErrorcách bạn muốn. By-the-way, tôi nghĩ find_last(), find_last_index()hoặc một cái gì đó simlar sẽ là một tên mô tả hơn cho chức năng này. Thêm vào sự nhầm lẫn có thể xảy ra là thực tế Python đã có một phương thức đối tượng vùng chứa được đặt tên __contains__()để thực hiện điều gì đó hơi khác một chút, kiểm tra tư cách thành viên.

def contains(char_string, char):
    largest_index = -1
    for i, ch in enumerate(char_string):
        if ch == char:
            largest_index = i
    if largest_index > -1:  # any found?
        return largest_index  # return index of last one
    else:
        raise ValueError('could not find {!r} in {!r}'.format(char, char_string))

print(contains('mississippi', 's'))  # -> 6
print(contains('bababa', 'k'))  # ->
Traceback (most recent call last):
  File "how-to-raise-a-valueerror.py", line 15, in <module>
    print(contains('bababa', 'k'))
  File "how-to-raise-a-valueerror.py", line 12, in contains
    raise ValueError('could not find {} in {}'.format(char, char_string))
ValueError: could not find 'k' in 'bababa'

Cập nhật - Một cách đơn giản hơn đáng kể

Chà! Đây là một phiên bản ngắn gọn hơn nhiều — về cơ bản là một lớp lót — cũng có khả năng nhanh hơn vì nó đảo ngược (qua [::-1]) chuỗi trước khi thực hiện tìm kiếm chuyển tiếp qua nó cho ký tự khớp đầu tiên và nó làm như vậy bằng cách sử dụng index()phương thức chuỗi tích hợp nhanh . Đối với câu hỏi thực tế của bạn, một phần thưởng tiện lợi nhỏ đi kèm với việc sử dụng index()là nó đã tăng ValueErrorkhi không tìm thấy chuỗi ký tự con, vì vậy không cần bổ sung gì để điều đó xảy ra.

Đây là nó cùng với một bài kiểm tra nhanh đơn vị:

def contains(char_string, char):
    #  Ending - 1 adjusts returned index to account for searching in reverse.
    return len(char_string) - char_string[::-1].index(char) - 1

print(contains('mississippi', 's'))  # -> 6
print(contains('bababa', 'k'))  # ->
Traceback (most recent call last):
  File "better-way-to-raise-a-valueerror.py", line 9, in <module>
    print(contains('bababa', 'k'))
  File "better-way-to-raise-a-valueerror", line 6, in contains
    return len(char_string) - char_string[::-1].index(char) - 1
ValueError: substring not found

Chức năng thứ 2: OP cần / muốn một forvòng lặp. Chức năng thứ nhất: FAIL cho contains('foo', 'f').
John Machin

1
@John Machin: Đã sửa lỗi bạn tìm thấy ở chức năng thứ nhất, cảm ơn vì đã lưu ý đến tôi. Tôi không thấy bất kỳ điều gì trong câu hỏi của OP hoặc các nhận xét bên dưới nó cho thấy họ cần hoặc muốn một forvòng lặp trong câu trả lời mặc dù một vòng lặp xuất hiện trong mã của riêng họ. Nhưng dù sao tôi chức năng hiển thị 1 họ làm thế nào để raisemột ValueErrorkhi nhân vật không được tìm thấy trong đó những gì họ yêu cầu. và tôi đã minh họa cách thực hiện trong bối cảnh của a for. Ngay cả khi họ muốn một forvì lý do nào đó, tôi nghĩ những người khác có thể tìm thấy phiên bản thứ 2 mà không có phiên bản nào ít nhất là hơi thú vị.
martineau

"Tôi muốn sử dụng vòng lặp for :-)" là nhận xét ban đầu cho câu trả lời hiện đã bị xóa bởi @pyfunc
John Machin

1
@John Machin: Đừng nghĩ rằng tôi có thể chịu trách nhiệm về việc không tôn trọng các yêu cầu trong nhận xét của các câu trả lời đã xóa mà tôi không và không thể thấy. Tuy nhiên, mặc dù chức năng thứ 2 của tôi không sử dụng một forvòng lặp, nó không theo một cách trả lời các câu hỏi thực tế về cách raisemột ValueErrorkhi nhân vật không được tìm thấy trong chuỗi - cụ thể là bằng cách gọi một cái gì đó khác nào đó cho bạn. Ngoài ra còn có triển vọng rằng OP có thể vượt qua for-fix của họ hoặc bất cứ điều gì đó sau khi thấy một forgiải pháp an toàn hoặc trở nên quen thuộc hơn với Python sau này.
martineau

12
>>> def contains(string, char):
...     for i in xrange(len(string) - 1, -1, -1):
...         if string[i] == char:
...             return i
...     raise ValueError("could not find %r in %r" % (char, string))
...
>>> contains('bababa', 'k')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in contains
ValueError: could not find 'k' in 'bababa'
>>> contains('bababa', 'a')
5
>>> contains('bababa', 'b')
4
>>> contains('xbababa', 'x')
0
>>>

4
>>> response='bababa'
...  if "K" in response.text:
...     raise ValueError("Not found")

1
Mặc dù mã này có thể trả lời câu hỏi, nhưng việc cung cấp thêm ngữ cảnh về cách thức và / hoặc lý do tại sao nó giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Donald Duck
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.