Bagaimana cara meningkatkan ValueError?

115

Saya memiliki kode ini yang menemukan indeks terbesar dari karakter tertentu dalam sebuah string, namun saya ingin menaikkannya ValueError ketika karakter yang ditentukan tidak muncul dalam string.

Jadi seperti ini:

contains('bababa', 'k')

akan menghasilkan:

ValueError: could not find k in bababa

Bagaimana saya bisa melakukan ini?

Inilah kode saat ini untuk fungsi saya:

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

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

  return list[-1]
pengguna531225
sumber
5
Sama seperti itu, naikkan ValueError () hahaha
slezica
@ user531225: Dapatkah Anda menerima beberapa jawaban lain sehingga saya dapat menghapus jawaban saya. Terima kasih :)
pyfunc
@ THC4k: Sangat aneh sehingga mengembalikan posisi kejadian paling kanan alih-alih hitungan.
John Machin
@ErikAllik: Jelas, dia melakukannya — dia memposting ke StackOverflow. Apa yang salah dengan itu?
Michael Scheper

Jawaban:

178

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

NPE
sumber
2
Tahukah Anda bahwa, jika Anda tidak ingin menggunakan pesan tersebut, Anda dapat raise ValueErrormelakukannya raise ValueError()?
Tomasz Gandor
27

Berikut adalah versi revisi dari kode Anda yang masih berfungsi ditambah itu menggambarkan cara menaikkan ValueErrorseperti yang Anda inginkan. By-the-way, saya pikir find_last(), find_last_index(), atau sesuatu simlar akan menjadi nama yang lebih deskriptif untuk fungsi ini. Menambah kebingungan yang mungkin terjadi adalah fakta bahwa Python sudah memiliki metode objek kontainer bernama __contains__()yang melakukan sesuatu yang sedikit berbeda, berdasarkan pengujian keanggotaan.

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'

Perbarui - Cara yang jauh lebih sederhana

Wow! Ini adalah versi yang jauh lebih ringkas — pada dasarnya satu baris — yang juga cenderung lebih cepat karena membalik (melalui [::-1]) string sebelum melakukan penelusuran maju melaluinya untuk karakter pertama yang cocok dan melakukannya menggunakan index()metode string built-in cepat . Sehubungan dengan pertanyaan Anda yang sebenarnya, sedikit bonus kenyamanan yang datang dengan penggunaan index()adalah bahwa hal itu sudah memunculkan ValueErrorsaat substring karakter tidak ditemukan, jadi tidak ada tambahan yang diperlukan untuk mewujudkannya.

Ini dia bersama dengan unit test cepat:

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
martineau.dll
sumber
Fungsi kedua: OP membutuhkan / menginginkan forloop. Fungsi pertama: FAIL for contains('foo', 'f').
John Machin
1
@ John Machin: Bug yang Anda temukan di fungsi pertama telah diperbaiki, terima kasih telah menyampaikannya kepada saya. Saya tidak melihat apa pun dalam pertanyaan OP atau komentar di bawahnya yang menunjukkan bahwa mereka membutuhkan atau menginginkan forloop dalam sebuah jawaban meskipun ada yang muncul dalam kode mereka sendiri. Bagaimanapun saya fungsi menunjukkan 1 mereka bagaimana raisesebuah ValueErrorketika karakter tidak ditemukan yang merupakan apa yang mereka minta. dan saya telah mengilustrasikan bagaimana melakukannya dalam konteks a for. Bahkan jika mereka menginginkan forkarena alasan tertentu, saya pikir orang lain mungkin menemukan versi ke-2 tanpa setidaknya agak menarik.
martineau
"Saya ingin menggunakan for loop :-)" adalah komentar awal untuk jawaban yang sekarang dihapus oleh @pyfunc
John Machin
1
@ John Machin: Jangan berpikir saya dapat dimintai pertanggungjawaban karena tidak memenuhi permintaan dalam komentar dari jawaban yang dihapus yang tidak saya dan tidak dapat lihat. Namun, meskipun fungsi 2 saya tidak menggunakan forlingkaran, itu tidak dengan cara menjawab pertanyaan yang sebenarnya tentang bagaimana raisesebuah ValueErrorketika karakter tidak ditemukan dalam string - yaitu dengan memanggil sesuatu yang lain yang melakukannya untuk Anda. Ada juga kemungkinan bahwa OP mungkin akan melupakan for-fixation mereka atau apapun itu setelah melihat forsolusi sans- atau menjadi lebih akrab dengan Python nanti.
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
>>>
John Machin
sumber
4
>>> response='bababa'
...  if "K" in response.text:
...     raise ValueError("Not found")
Kaushik Dey
sumber
1
Meskipun kode ini mungkin menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa kode ini memecahkan masalah akan meningkatkan nilai jawaban jangka panjang.
Donald Duck