我有限的大脑无法理解为什么会这样:
>>> print '' in 'lolsome'
True
在PHP中,等效比较返回false:
var_dump(strpos('', 'lolsome'));
答案 0 :(得分:55)
对于Unicode和字符串类型,当且仅当 x 是 y 的子字符串时,
x in 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();
}
显示比较发生的位置:
res = PySequence_Contains(w, v);
以及source code,我们可以轻松找到下一条线索:
{
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);
}
位于cmp_outcome is in the same file:
objobjproc PySequenceMethods.sq_contains
并从源头获取空气,我们在abstract.c中找到了下一个功能:
PySequence_Contains()
此功能可由
PySequence_Contains()
使用,并具有相同的签名。此插槽可以留给 NULL ,在这种情况下,int PySequence_Contains(PyObject *o, PyObject *value)
只是遍历序列,直到找到匹配为止。
1
确定 o 是否包含值。如果 o 中的项目等于值,则返回
0
,否则返回-1
。出错时,请返回value in o
。这相当于Python表达式''
。
如果null
不是'lolsome'
,则可以认为序列{{1}}包含它。
答案 1 :(得分:20)
mixed strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
在
needle
字符串中查找第一次出现haystack
的数字位置。
所以你实际尝试的内容类似于下面的Python构造
>>> print 'lolsome' in ''
False
所以,你应该实际编写如下所示的在PHP中进行相应的比较
var_dump(strpos('lolsome', ''));
即使这样,它也会发出警告并返回false
。
PHP警告:
strpos()
:第3行/home/thefourtheye/Desktop/Test.php中的空针
bool(false)
我挖得更深,发现the source code corresponding to the strpos
function,
if (!Z_STRLEN_P(needle)) {
php_error_docref(NULL, E_WARNING, "Empty needle");
RETURN_FALSE;
}
他们认为搜索的空字符串是一个有问题的案例。因此,他们发出警告并返回false
。除此之外,我找不到任何文件,讨论为什么它被视为一个问题。
就Python而言,这种行为在Comparisons section,
中得到了很好的定义空字符串始终被视为任何其他字符串的子字符串,因此
"" in "abc"
将返回True
。
答案 2 :(得分:9)
基本上,从数学:
空集是每个集合的子集
这里的逻辑相同。您可以将''
视为空集。因此,它是每个字符串集的子集,因为它们必须是相同的类型。
>>> 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
>>>
但要小心!子集和成员资格为different things。
答案 3 :(得分:3)
空字符串是长度为零的唯一字符串 空字符串是连接操作的标识元素 空字符串位于字典顺序下的任何其他字符串之前,因为它是所有字符串中最短的 空字符串是一个合法的字符串,大多数字符串操作都应该在该字符串上工作 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
答案 4 :(得分:1)
假设你有两堆相似的物品,比如你最喜欢的诗人的最佳诗节,分别为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