99%的用例將使用關鍵字,in,回傳True或False:
<span style="background-color:var(--highlight-bg)"><span style="color:var(--highlight-color)"><code>'substring' in any_string
</code></span></span>
對于獲取索引的用例,請使用str.find(失敗時回傳 -1,并具有可選的位置引數):
<span style="background-color:var(--highlight-bg)"><span style="color:var(--highlight-color)"><code>start = 0
stop = len(any_string)
any_string.find('substring', start, stop)
</code></span></span>
或str.index(就像find但在失敗時引發 ValueError ):
<span style="background-color:var(--highlight-bg)"><span style="color:var(--highlight-color)"><code>start = 100
end = 1000
any_string.index('substring', start, end)
</code></span></span>
解釋
使用in比較運算子,因為
- 該語言打算使用它,并且
- 其他 Python 程式員會希望您使用它,
<span style="background-color:var(--highlight-bg)"><span style="color:var(--highlight-color)"><code>>>> 'foo' in '**foo**'
True
</code></span></span>
原始問題要求的相反(補充)是not in:
<span style="background-color:var(--highlight-bg)"><span style="color:var(--highlight-color)"><code>>>> 'foo' not in '**foo**' # returns False
False
</code></span></span>
這在語意上是相同的,not 'foo' in '**foo**'但它更具可讀性,并且作為可讀性改進在語言中明確提供,
避免使用 __contains__
“包含”方法實作了 的行為in,這個例子,
str.__contains__('**foo**', 'foo')
回傳True,您還可以從超字串的實體中呼叫此函式:
'**foo**'.__contains__('foo')
但是不要,以下劃線開頭的方法在語意上被認為是非公開的,使用它的唯一原因是在實作或擴展in和not in功能時(例如,如果子類化str):
class NoisyString(str):
def __contains__(self, other):
print(f'testing if "{other}" in "{self}"')
return super(NoisyString, self).__contains__(other)
ns = NoisyString('a string with a substring inside')
現在:
>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True
不要使用find和index測驗“包含”
不要使用以下字串方法來測驗“包含”:
>>> '**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
其他語言可能沒有直接測驗子字串的方法,因此您必須使用這些型別的方法,但是對于 Python,使用in比較運算子會更有效率,
此外,這些不是in. 您可能必須處理例外或-1情況,如果它們回傳0(因為它們在開頭找到了子字串),則布爾解釋是False而不是True.
如果你真的是not any_string.startswith(substring)這個意思,那就說出來,
性能比較
我們可以比較實作同一目標的各種方法,
import timeit
def in_(s, other):
return other in s
def contains(s, other):
return s.__contains__(other)
def find(s, other):
return s.find(other) != -1
def index(s, other):
try:
s.index(other)
except ValueError:
return False
else:
return True
perf_dict = {
'in:True': min(timeit.repeat(lambda: in_('superstring', 'str'))),
'in:False': min(timeit.repeat(lambda: in_('superstring', 'not'))),
'__contains__:True': min(timeit.repeat(lambda: contains('superstring', 'str'))),
'__contains__:False': min(timeit.repeat(lambda: contains('superstring', 'not'))),
'find:True': min(timeit.repeat(lambda: find('superstring', 'str'))),
'find:False': min(timeit.repeat(lambda: find('superstring', 'not'))),
'index:True': min(timeit.repeat(lambda: index('superstring', 'str'))),
'index:False': min(timeit.repeat(lambda: index('superstring', 'not'))),
}
現在我們看到使用in比其他的快得多,做等效操作的時間越少越好:
>>> perf_dict
{'in:True': 0.16450627865128808,
'in:False': 0.1609668098178645,
'__contains__:True': 0.24355481654697542,
'__contains__:False': 0.24382793854783813,
'find:True': 0.3067379407923454,
'find:False': 0.29860888058124146,
'index:True': 0.29647137792585454,
'index:False': 0.5502287584545229}
如何in比__contains__ifin使用更快__contains__?
這是一個很好的后續問題,
讓我們用感興趣的方法反匯編函式:
>>> from dis import dis
>>> dis(lambda: 'a' in 'b')
1 0 LOAD_CONST 1 ('a')
2 LOAD_CONST 2 ('b')
4 COMPARE_OP 6 (in)
6 RETURN_VALUE
>>> dis(lambda: 'b'.__contains__('a'))
1 0 LOAD_CONST 1 ('b')
2 LOAD_METHOD 0 (__contains__)
4 LOAD_CONST 2 ('a')
6 CALL_METHOD 1
8 RETURN_VALUE
所以我們看到.__contains__必須單獨查找該方法,然后從 Python 虛擬機呼叫 - 這應該足以解釋差異,
感謝各位大佬的觀看,小編這邊準備了一個學習交流的qq群聊 :924403856【代碼也準備好了】 歡迎加入《廣告勿加,不然你做啥啥不賺錢》最后祝大家技術能力能越來越好收入越來越多
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286924.html
標籤:其他

