Мой ограниченный мозг не может понять, почему это происходит:
>>> print '' in 'lolsome'
True
В PHP эквивалентное сравнение возвращает false:
var_dump(strpos('', 'lolsome'));
Мой ограниченный мозг не может понять, почему это происходит:
>>> print '' in 'lolsome'
True
В PHP эквивалентное сравнение возвращает false:
var_dump(strpos('', 'lolsome'));
Для Unicode и типов строк
x in yявляется истинным тогда и только тогда, когда x является подстрокой y. Эквивалентный тестy.find(x) != -1. Обратите внимание: x и y не должны быть одного типа; следовательно,u'ab' in 'abc'вернетTrue. Пустые строки всегда считаются подстрокой любой другой строки, поэтому"" in "abc"вернетTrue.
От взгляда на ваш вызов print вы используете 2.x.
Чтобы углубиться, посмотрите на байт-код:
>>> def answer():
... '' in 'lolsome'
>>> dis.dis(answer)
2 0 LOAD_CONST 1 ('')
3 LOAD_CONST 2 ('lolsome')
6 COMPARE_OP 6 (in)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
COMPARE_OP - это то, где мы выполняем нашу булевскую операцию и смотрим на исходный код для in, где показано сравнение:
TARGET(COMPARE_OP)
{
w = POP();
v = TOP();
if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
/* INLINE: cmp(int, int) */
register long a, b;
register int res;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
switch (oparg) {
case PyCmp_LT: res = a < b; break;
case PyCmp_LE: res = a <= b; break;
case PyCmp_EQ: res = a == b; break;
case PyCmp_NE: res = a != b; break;
case PyCmp_GT: res = a > b; break;
case PyCmp_GE: res = a >= b; break;
case PyCmp_IS: res = v == w; break;
case PyCmp_IS_NOT: res = v != w; break;
default: goto slow_compare;
}
x = res ? Py_True : Py_False;
Py_INCREF(x);
}
else {
slow_compare:
x = cmp_outcome(oparg, v, w);
}
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x == NULL) break;
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
}
и где cmp_outcome находится в одном файле, легко найти наш следующий ключ:
res = PySequence_Contains(w, v);
который находится в abstract.c:
{
Py_ssize_t result;
if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
if (sqm != NULL && sqm->sq_contains != NULL)
return (*sqm->sq_contains)(seq, ob);
}
result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
}
и для выхода из источника из источника, мы находим следующую функцию в документации :
objobjproc PySequenceMethods.sq_containsЭта функция может использоваться
PySequence_Contains()и имеет ту же подпись. Этот слот может быть оставлен до NULL, в этом случаеPySequence_Contains()просто перемещает последовательность до тех пор, пока не найдет совпадение.
и далее в той же документации:
int PySequence_Contains(PyObject *o, PyObject *value)Определите, содержит ли o значение. Если элемент в o равен значению, верните
1, в противном случае верните0. При ошибке возвратите-1. Это эквивалентно выражению Pythonvalue in o.
Где '' не null, можно считать, что последовательность 'lolsome' содержит ее.
Цитата из PHP strpos документации,
mixed strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )Найти числовое положение первого вхождения
needleв строкеhaystack.
Итак, то, что вы на самом деле пытались, похоже на конструкцию Python, представленную ниже
>>> print 'lolsome' in ''
False
Итак, на самом деле вы должны написать, как показано ниже, чтобы иметь соответствующее сравнение в PHP
var_dump(strpos('lolsome', ''));
Даже тогда он выдает предупреждение и возвращает false.
Предупреждение PHP:
strpos(): пустая стрелка в /home/thefourtheye/Desktop/Test.php в строке 3
bool(false)
Я углубился и нашел исходный код, соответствующий функции strpos,
if (!Z_STRLEN_P(needle)) {
php_error_docref(NULL, E_WARNING, "Empty needle");
RETURN_FALSE;
}
Они рассматривают пустую строку, которую ищут как проблемный случай. Таким образом, они выдают предупреждение и возвращают false. Помимо этого, я не мог найти ни одного документа, в котором обсуждается, почему его рассматривают как проблему.
Что касается Python, это поведение хорошо определено в разделе Сравнения,
Пустые строки всегда считаются подстрокой любой другой строки, поэтому
"" in "abc"вернетTrue.
В принципе, из математики:
Пустое множество является подмножеством каждого множества
Здесь же работает такая же логика. Вы можете рассмотреть '' пустой набор. И поэтому это подмножество каждого набора строк, так как они должны быть одного и того же типа.
>>> a = ""
>>> b = "Python"
>>> a in b
True
>>> set(a).issubset(b)
True
>>> a = set() #empty set
>>> b = set([1,2,3])
>>> a.issubset(b)
True
>>>
Но будьте осторожны! Подмножество и членство разные вещи.
Пустая строка - это единственная строка нулевой длины.
Пустая строка - это элемент идентификации операции конкатенации.
Пустая строка предшествует любой другой строке в лексикографическом порядке, потому что она является самой короткой из всех строк.
Пустая строка - это законная строка, на которой должны работать большинство строковых операций.
Wikipedia
> strlen("");
=> 0
> "a" . "" == "a";
=> true
> "" . "a" == "a";
=> true
> "" < "\0";
=> true
Сверху кажется, что PHP обрабатывает пустую строку как допустимую строку.
> strstr("lolsome", "");
strstr(): Empty needle :1
Но он не считает пустую строку полностью легитимной. Скорее всего, PHP является единственным языком, который не позволяет искать подстроку в строке как пустую строку.
Это защитный механизм? Очевидно, что программистам не нужно защищать иглу if. Если да, то почему другие языки позволяют пройти этот тест!!! Языковые дизайнеры должны отвечать
Какая строка Python состоит из?
>>> ''.count('')
1
Очевидно, что пустая строка имеет одну пустую строку.
>>> 'a'.count('')
2
Одна строка элемента имеет два пустых srings.
>>> 'ab'.count('')
3
Итак, кажется, что строка Python является конкатенацией одной строки элемента. Каждый элемент в строке зажат между двумя пустыми строками.
>>> "lolsome".split('')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: empty separator
Но здесь Python противоречит действительности пустой строки. Это ошибка?
Ruby и JavaScript проходят здесь тест.
> "lolsome".split("")
=> ["l", "o", "l", "s", "o", "m", "e"]
Я собрал несколько примеров из Rosetta code, интересно отметить, что все они разрешают пустую строку в поиске подстроки и возвращают true.
awk 'BEGIN { print index("lolsome", "") != 0 }'
int main() {
printf("%d\n", strstr("lolsome", "") != NULL);
return 0;
}
#include <iostream>
#include <string>
int main() {
std::string s = "lolsome";
std::cout << (s.find("") != -1) << "\n";
return 0;
}
using System;
class MainClass {
public static void Main (string[] args) {
string s = "lolsome";
Console.WriteLine(s.IndexOf("", 0, s.Length) != -1);
}
}
(println (.indexOf "lolsome" ""))
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Index("lolsome", "") != -1)
}
Groovy
println 'lolsome'.indexOf('')
возвращает 0, при ошибке возвращается -1
class Main {
public static void main(String[] args) {
System.out.println("lolsome".indexOf("") != -1);
}
}
"lolsome".indexOf("") != -1
s = "lolsome"
print(s:find "" ~= nil)
print index("lolsome", "") != -1;
"lolsome".find("") != -1
"lolsome".index("") != nil
Предположим, у вас есть две груды похожих предметов, например, лучшие строфы вашего любимого поэта, 5 и 2 соответственно. Большой набор содержит меньший набор? Как проверить: 1) для любой строфы в меньшей куче вы можете найти ее в более крупной. 2) меньшая куча не содержит чего-то, чего нет в более крупном.
Таким образом, мы можем использовать этот псевдокод для проверки:
for object in smaller:
if object not in bigger:
return 'we found object from smaller absent in bigger'
else:
go to next object
return 'all is ok - all objects from smaller are in bigger'
Если вы не нашли такого объекта, вы подходите к концу algo и считаете, что меньше - это подмножество большего размера.
Теперь представьте меньшую кучу 0 строф. Применяя те же правила выше, мы выполняем 0 проверок, а также не находим объект меньшего размера, который больше отсутствует.
Итак, правильно и удобно считать пустую строку как подмножество любой другой строки. Даже сам. И это реализовано в python.
>>> '' in 'adfsf'
True
>>> '' in ''
True