Di bawah tenda, Python akan menggunakan __contains__(self, item),, __iter__(self)dan __getitem__(self, key)dalam urutan itu untuk menentukan apakah suatu item terletak pada suatu konten. Terapkan setidaknya satu dari metode itu untuk membuat intersedia untuk jenis kustom Anda.
BallpointBen
27
Pastikan saja bahwa somestring tidak akan menjadi None. Jika tidak, Anda akan mendapatkanTypeError: argument of type 'NoneType' is not iterable
Labu Besar
5
FWIW, ini adalah cara idiomatis untuk mencapai tujuan tersebut.
Trenton
6
Untuk string, apakah inoperator Python menggunakan algoritma Rabin-Carp?
Sam Chats
3
@ SamChats, lihat stackoverflow.com/questions/18139660/... untuk detail implementasi (dalam CPython; afaik spesifikasi bahasa tidak mengharuskan algoritma tertentu di sini).
Christoph Burschka
667
Jika itu hanya pencarian substring yang dapat Anda gunakan string.find("substring").
Anda harus sedikit berhati-hati dengan find, index, dan inmeskipun, seperti yang substring pencarian. Dengan kata lain, ini:
s ="This be a string"if s.find("is")==-1:print("No 'is' here!")else:print("Found 'is' in the string.")
Itu akan mencetak sama Found 'is' in the string., if "is" in s:akan mengevaluasi True. Ini mungkin atau mungkin bukan yang Anda inginkan.
+1 untuk menyorot gotcha yang terlibat dalam pencarian substring. solusi yang jelas adalah if ' is ' in s:yang akan kembali Falseseperti yang diharapkan (mungkin).
aaronasterling
95
@ aaronasterling Jelas itu mungkin, tetapi tidak sepenuhnya benar. Bagaimana jika Anda memiliki tanda baca atau itu pada awal atau akhir? Bagaimana dengan kapitalisasi? Lebih baik akan menjadi kasus pencarian regex tidak sensitif untuk \bis\b(batas kata).
Bob
2
@JamieBull Sekali lagi, Anda harus mempertimbangkan jika Anda ingin memasukkan tanda baca sebagai pembatas untuk sebuah kata. Pemisahan sebagian besar akan memiliki efek yang sama dengan solusi naif untuk memeriksa ' is ', terutama, itu tidak akan menangkap This is, a comma'atau 'It is.'.
Bob
7
@ JamieBull: Saya sangat meragukan setiap input split nyata dengan s.split(string.punctuation + string.whitespace)akan membagi bahkan sekali; splittidak seperti strip/ rstrip/ lstripkeluarga fungsi, itu hanya membagi ketika melihat semua karakter pembatas, contiguously, dalam urutan yang tepat. Jika Anda ingin membagi pada kelas karakter, Anda kembali ke ekspresi reguler (pada titik itu, mencari r'\bis\b'tanpa pemisahan adalah cara yang lebih sederhana, lebih cepat untuk pergi).
ShadowRanger
8
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()- ok, poin diambil. Ini sekarang konyol ...
Jamie Bull
190
Apakah Python memiliki string yang berisi metode substring?
Ya, tetapi Python memiliki operator pembanding yang harus Anda gunakan sebagai gantinya, karena bahasa tersebut bermaksud penggunaannya, dan programmer lain akan mengharapkan Anda untuk menggunakannya. Kata kunci itu in, yang digunakan sebagai operator perbandingan:
>>>'foo'in'**foo**'True
Sebaliknya (komplemen), yang ditanyakan oleh pertanyaan asli, adalah not in:
>>>'foo'notin'**foo**'# returns FalseFalse
Ini semantik sama dengan not 'foo' in '**foo**'tetapi jauh lebih mudah dibaca dan secara eksplisit disediakan dalam bahasa sebagai peningkatan keterbacaan.
Hindari menggunakan __contains__, finddanindex
Seperti yang dijanjikan, inilah containscaranya:
str.__contains__('**foo**','foo')
kembali True. Anda juga dapat memanggil fungsi ini dari instance superstring:
'**foo**'.__contains__('foo')
Tapi jangan. Metode yang dimulai dengan garis bawah dianggap semantik pribadi. Satu-satunya alasan untuk menggunakan ini adalah ketika memperluas indan not infungsionalitas (mis. Jika subclassing str):
classNoisyString(str):def __contains__(self, other):print('testing if "{0}" in "{1}"'.format(other, self))return super(NoisyString, self).__contains__(other)
ns =NoisyString('a string with a substring inside')
dan sekarang:
>>>'substring'in ns
testing if"substring"in"a string with a substring inside"True
Selain itu, hindari metode string berikut:
>>>'**foo**'.index('foo')2>>>'**foo**'.find('foo')2>>>'**oo**'.find('foo')-1>>>'**oo**'.index('foo')Traceback(most recent call last):File"<pyshell#40>", line 1,in<module>'**oo**'.index('foo')ValueError: substring not found
Bahasa lain mungkin tidak memiliki metode untuk menguji langsung untuk substring, dan Anda harus menggunakan jenis metode ini, tetapi dengan Python, jauh lebih efisien untuk menggunakan inoperator pembanding.
Perbandingan kinerja
Kita dapat membandingkan berbagai cara untuk mencapai tujuan yang sama.
Mengapa orang harus menghindari str.indexdan str.find? Bagaimana lagi Anda menyarankan seseorang menemukan indeks substring alih-alih hanya apakah itu ada atau tidak? (Atau maksud Anda menghindari menggunakannya di tempat mengandung - jadi jangan gunakan s.find(ss) != -1bukan ss in s?)
coderforlife
3
Tepatnya, meskipun maksud di balik penggunaan metode-metode itu mungkin lebih baik diatasi dengan penggunaan remodul yang elegan . Saya belum menemukan penggunaan untuk str.index atau str.find sendiri dalam kode apa pun yang saya tulis.
Aaron Hall
Harap rentangkan jawaban Anda ke saran yang menentang penggunaan str.countjuga ( string.count(something) != 0). gemetar
if needle in haystack:adalah penggunaan normal, seperti yang dikatakan @Michael - ini bergantung pada inoperator, lebih mudah dibaca dan lebih cepat daripada pemanggilan metode.
Jika Anda benar-benar membutuhkan metode alih-alih operator (mis. Untuk melakukan sesuatu yang aneh key=untuk jenis yang sangat aneh ...?), Itu mungkin 'haystack'.__contains__. Tapi karena contoh Anda adalah untuk digunakan dalam if, saya kira Anda tidak benar-benar bermaksud apa yang Anda katakan ;-). Ini bukan bentuk yang baik (atau dapat dibaca, atau efisien) untuk menggunakan metode khusus secara langsung - mereka seharusnya digunakan, sebagai gantinya, melalui operator dan builtin yang mendelegasikan kepada mereka.
Berikut adalah beberapa contoh berguna yang berbicara sendiri tentang inmetode ini:
"foo"in"foobar"True"foo"in"Foobar"False"foo"in"Foobar".lower()True"foo".capitalize()in"Foobar"True"foo"in["bar","foo","foobar"]True"foo"in["fo","o","foobar"]False["foo"in a for a in["fo","o","foobar"]][False,False,True]
Peringatan. Daftar adalah iterables, dan inmetode ini bekerja pada iterables, bukan hanya string.
Mungkinkah daftar itu diubah untuk mencari daftar dalam satu string? Mis .: ["bar", "foo", "foobar"] in "foof"?
CaffeinatedCoder
1
@CaffeinatedCoder, tidak, ini membutuhkan iterasi bersarang. Paling baik dilakukan dengan bergabung dengan daftar dengan pipa "|" .join (["bar", "foo", "foobar"]) dan menyusun regex, lalu mencocokkannya dengan "foof"
firelynx
2
any ([x dalam "foof" untuk x di ["bar", "foo", "foobar"]])
Izaak Weiss
1
@IzaakWeiss Satu liner Anda berfungsi, tetapi tidak terlalu mudah dibaca, dan iterasi bersarang. Saya akan menyarankan untuk tidak melakukan ini
firelynx
1
@ PiyushS.Wanare apa yang Anda maksud dengan kompleksitas? "WTF / mnt" jauh lebih tinggi dengan regex.
firelynx
42
Jika Anda senang "blah" in somestringtetapi menginginkannya menjadi panggilan fungsi / metode, Anda mungkin dapat melakukan ini
Itu karena ada bajillion cara menciptakan Produk dari variabel atom. Anda dapat memasukkannya dalam tuple, daftar (yang merupakan bentuk Produk Cartesian dan disertai pesanan tersirat), atau mereka dapat dinamai properti kelas (tanpa urutan apriori) atau nilai kamus, atau dapat berupa file dalam direktori, atau apa pun. Setiap kali Anda dapat secara unik mengidentifikasi (iter atau getitem) sesuatu dalam 'wadah' atau 'konteks', Anda dapat melihat 'wadah' itu sebagai semacam vektor dan mendefinisikan operasi biner di atasnya. en.wikipedia.org/wiki/…
Niriel
Layak apa-apa yang intidak boleh digunakan dengan daftar karena melakukan pemindaian linear elemen dan lambat dibandingkan. Gunakan set sebagai gantinya, terutama jika tes keanggotaan harus dilakukan berulang kali.
cs95
22
Anda bisa menggunakannya y.count().
Ini akan mengembalikan nilai integer dari berapa kali sebuah sub string muncul dalam sebuah string.
kemudian Jika Anda memiliki wewenang untuk menghapusnya kemudian menghapusnya, lakukan apa yang harus Anda lakukan dan lanjutkan. IMO jawaban ini menambah nilai, yang dicerminkan oleh suara terbanyak dari pengguna.
__contains__(self, item)
,,__iter__(self)
dan__getitem__(self, key)
dalam urutan itu untuk menentukan apakah suatu item terletak pada suatu konten. Terapkan setidaknya satu dari metode itu untuk membuatin
tersedia untuk jenis kustom Anda.TypeError: argument of type 'NoneType' is not iterable
in
operator Python menggunakan algoritma Rabin-Carp?Jika itu hanya pencarian substring yang dapat Anda gunakan
string.find("substring")
.Anda harus sedikit berhati-hati dengan
find
,index
, danin
meskipun, seperti yang substring pencarian. Dengan kata lain, ini:Itu akan mencetak sama
Found 'is' in the string.
,if "is" in s:
akan mengevaluasiTrue
. Ini mungkin atau mungkin bukan yang Anda inginkan.sumber
if ' is ' in s:
yang akan kembaliFalse
seperti yang diharapkan (mungkin).\bis\b
(batas kata).' is '
, terutama, itu tidak akan menangkapThis is, a comma'
atau'It is.'
.s.split(string.punctuation + string.whitespace)
akan membagi bahkan sekali;split
tidak sepertistrip
/rstrip
/lstrip
keluarga fungsi, itu hanya membagi ketika melihat semua karakter pembatas, contiguously, dalam urutan yang tepat. Jika Anda ingin membagi pada kelas karakter, Anda kembali ke ekspresi reguler (pada titik itu, mencarir'\bis\b'
tanpa pemisahan adalah cara yang lebih sederhana, lebih cepat untuk pergi).'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- ok, poin diambil. Ini sekarang konyol ...Ya, tetapi Python memiliki operator pembanding yang harus Anda gunakan sebagai gantinya, karena bahasa tersebut bermaksud penggunaannya, dan programmer lain akan mengharapkan Anda untuk menggunakannya. Kata kunci itu
in
, yang digunakan sebagai operator perbandingan:Sebaliknya (komplemen), yang ditanyakan oleh pertanyaan asli, adalah
not in
:Ini semantik sama dengan
not 'foo' in '**foo**'
tetapi jauh lebih mudah dibaca dan secara eksplisit disediakan dalam bahasa sebagai peningkatan keterbacaan.Hindari menggunakan
__contains__
,find
danindex
Seperti yang dijanjikan, inilah
contains
caranya:kembali
True
. Anda juga dapat memanggil fungsi ini dari instance superstring:Tapi jangan. Metode yang dimulai dengan garis bawah dianggap semantik pribadi. Satu-satunya alasan untuk menggunakan ini adalah ketika memperluas
in
dannot in
fungsionalitas (mis. Jika subclassingstr
):dan sekarang:
Selain itu, hindari metode string berikut:
Bahasa lain mungkin tidak memiliki metode untuk menguji langsung untuk substring, dan Anda harus menggunakan jenis metode ini, tetapi dengan Python, jauh lebih efisien untuk menggunakan
in
operator pembanding.Perbandingan kinerja
Kita dapat membandingkan berbagai cara untuk mencapai tujuan yang sama.
Dan sekarang kita melihat bahwa menggunakan
in
jauh lebih cepat daripada yang lain. Lebih sedikit waktu untuk melakukan operasi yang setara lebih baik:sumber
str.index
danstr.find
? Bagaimana lagi Anda menyarankan seseorang menemukan indeks substring alih-alih hanya apakah itu ada atau tidak? (Atau maksud Anda menghindari menggunakannya di tempat mengandung - jadi jangan gunakans.find(ss) != -1
bukanss in s
?)re
modul yang elegan . Saya belum menemukan penggunaan untuk str.index atau str.find sendiri dalam kode apa pun yang saya tulis.str.count
juga (string.count(something) != 0
). gemetaroperator
versi modul ?in_
atas - tetapi dengan susunan bingkai di sekitarnya, jadi lebih lambat dari itu: github.com/python/cpython/blob/3.7/Lib/operator.py#L153if needle in haystack:
adalah penggunaan normal, seperti yang dikatakan @Michael - ini bergantung padain
operator, lebih mudah dibaca dan lebih cepat daripada pemanggilan metode.Jika Anda benar-benar membutuhkan metode alih-alih operator (mis. Untuk melakukan sesuatu yang aneh
key=
untuk jenis yang sangat aneh ...?), Itu mungkin'haystack'.__contains__
. Tapi karena contoh Anda adalah untuk digunakan dalamif
, saya kira Anda tidak benar-benar bermaksud apa yang Anda katakan ;-). Ini bukan bentuk yang baik (atau dapat dibaca, atau efisien) untuk menggunakan metode khusus secara langsung - mereka seharusnya digunakan, sebagai gantinya, melalui operator dan builtin yang mendelegasikan kepada mereka.sumber
in
String dan daftar PythonBerikut adalah beberapa contoh berguna yang berbicara sendiri tentang
in
metode ini:Peringatan. Daftar adalah iterables, dan
in
metode ini bekerja pada iterables, bukan hanya string.sumber
["bar", "foo", "foobar"] in "foof"
?Jika Anda senang
"blah" in somestring
tetapi menginginkannya menjadi panggilan fungsi / metode, Anda mungkin dapat melakukan iniSemua operator di Python dapat lebih atau kurang ditemukan dalam modul operator termasuk
in
.sumber
Jadi rupanya tidak ada yang serupa untuk perbandingan bijaksana. Cara Python yang jelas untuk melakukannya adalah:
sumber
in
tidak boleh digunakan dengan daftar karena melakukan pemindaian linear elemen dan lambat dibandingkan. Gunakan set sebagai gantinya, terutama jika tes keanggotaan harus dilakukan berulang kali.Anda bisa menggunakannya
y.count()
.Ini akan mengembalikan nilai integer dari berapa kali sebuah sub string muncul dalam sebuah string.
Sebagai contoh:
sumber
Inilah jawaban Anda:
Untuk memeriksa apakah itu salah:
ATAU:
sumber
Anda dapat menggunakan ekspresi reguler untuk mendapatkan kemunculan:
sumber