Почему True возвращается при проверке, есть ли пустая строка в другой?


Дамп вашей базы данных: pg_dump database_name_name > backup.sql


Импортировать свою базу данных назад: psql db_name < backup.sql

29
задан martineau 20 January 2018 в 01:38
поделиться

5 ответов

Из документации :

Для Unicode и строковых типов x in y истинно тогда и только тогда, когда x является подстрокой [ +1134] у [+1134]. Эквивалентный тест - 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. Это эквивалентно выражению Python value in o.

Если '' не является null, можно считать, что последовательность 'lolsome' содержит ее.

55
ответ дан 20 January 2018 в 01:38
поделиться

Цитирование из 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.

20
ответ дан thefourtheye 20 January 2018 в 01:38
поделиться

В основном из математики:

Пустое множество является подмножеством каждого множества

Та же логика работает здесь. Вы можете считать '' пустым множеством. И, следовательно, это подмножество каждого набора строк , так как они должны быть одного типа.

>>> 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
>>> 

Но будьте осторожны! Подмножество и членство - это разные вещи .

enter image description here

9
ответ дан GLHF 20 January 2018 в 01:38
поделиться

Пустая строка - это уникальная строка нулевой длины.
Пустая строка является элементом идентификации операции конкатенации.
Пустая строка предшествует любой другой строке в лексикографическом порядке, поскольку она является самой короткой из всех строк.
Пустая строка является допустимой строкой, с которой должно работать большинство строковых операций.
Википедия

 > 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

Одна строка элементов имеет две пустые строки.

>>> '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"]

Я собрал несколько языковых примеров из кода Розетты , интересно отметить, что все они допускают пустую строку в поиск подстроки и возврат истины.

AWK

awk 'BEGIN { print index("lolsome", "") != 0 }'

C

int main() {
    printf("%d\n", strstr("lolsome", "") != NULL);
    return 0;
}

C ++

#include <iostream>
#include <string>

int main() {
    std::string s = "lolsome";
    std::cout << (s.find("") != -1) << "\n";
    return 0;
}

C #

using System;
class MainClass {
  public static void Main (string[] args) {
    string s = "lolsome";
    Console.WriteLine(s.IndexOf("", 0, s.Length) != -1);
  }
}

Clojure

(println (.indexOf "lolsome" ""))

Go

package main

import (
    "fmt"
    "strings"
)
func main() {
    fmt.Println(strings.Index("lolsome", "") != -1)
}

Groovy

println 'lolsome'.indexOf('')

возвращает 0, при ошибке возвращает -1

Java

class Main {
  public static void main(String[] args) {
    System.out.println("lolsome".indexOf("") != -1);
  }
}

JavaScript

"lolsome".indexOf("") != -1

Lua

s = "lolsome"
print(s:find "" ~= nil)

Perl

print index("lolsome", "") != -1;

Python [1167]
"lolsome".find("") != -1

Рубин

"lolsome".index("") != nil
3
ответ дан Nizam Mohamed 20 January 2018 в 01:38
поделиться

Предположим, у вас есть 2 кучи похожих объектов, скажем, лучших строф вашего любимого поэта, по 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'

Если вы не нашли такой объект, вы подходите к концу алгоритма и думаете, что меньше - это подмножество большего.

Теперь представьте, что маленькая куча имеет 0 строф. Применяя те же правила выше, мы выполняем 0 проверок, а также не находим объект от меньшего, который отсутствует в большем.

Так что правильно и удобно считать пустую строку подмножеством любой другой строки. Даже сама. И это реализовано в python.

    >>> '' in 'adfsf'
    True
    >>> '' in ''
    True
1
ответ дан Eugene Lisitsky 20 January 2018 в 01:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: