万万没想到, Python 的字符串裁切函数居然还能有 bug

2022-12-21 19:54:53 +08:00
 WordTian

吐个槽,大家猜猜 python3 执行这 2 句话都会出现什么?

print('test.py'.rstrip(".py"))
print('testy.py'.rstrip(".py"))

这 2 句呢

print('test6y'.rstrip("6y"))
print('testy6y'.rstrip("6y"))
8083 次点击
所在节点    Python
51 条回复
wxf666
2022-12-21 20:00:22 +08:00
你可能想用的是 `removesuffix`

上一个犯过类似错误的帖子:/t/880251
likelylee
2022-12-21 20:02:41 +08:00
The chars argument is a string specifying the set of characters to be removed. If omitted or None, the chars argument defaults to removing whitespace. The chars argument is not a suffix; rather, all combinations of its values are stripped.

https://stackoverflow.com/questions/6479676/bug-in-pythons-str-rstrip-function-or-my-own-stupidity
drizztdu
2022-12-21 20:03:41 +08:00
zooo
2022-12-21 20:03:46 +08:00
都是 test
WordTian
2022-12-21 20:32:26 +08:00
看了楼上的信息,确实是我用错了,我的锅!

白白为 UC 震惊部打了一回工!
ClericPy
2022-12-21 21:08:00 +08:00
好容易有个新帖子 ... https://docs.python.org/zh-cn/3/library/stdtypes.html#str.rstrip

入参是 chars 是字符集不是字符串... 这跟 strip 入参不是一致的么, 没有区别. 遇事不决官方文档
lambdaq
2022-12-21 21:42:44 +08:00
这个的确是个很经典的坑。我觉得的确算 py 的设计缺陷!
weyou
2022-12-21 21:48:49 +08:00
@lambdaq 文档写的明明白白的,怎么能算设计缺陷?自己学艺不精罢了
maggch97
2022-12-21 22:41:43 +08:00
简单想一下也知道这个方法一定要设计成这样, 这个函数一般是用来去首尾空的, 空格字符有 n 种. 显然需要传入的是 set 而不是一个固定的 string

不要动不动就觉得别人的设计有问题. 虽然 python 很屎, 但是还不至于屎在这么简单的地方
lambdaq
2022-12-21 22:46:38 +08:00
@weyou 反过来,那么只要不是 undefined behavoir ,都怪用户自己笨 or 懒? 语言设计一点责任都没有嘛。

有没有可能,比如这个方法被叫做 rstripchar() 就不会有这么多误会而且意义更明确?
lambdaq
2022-12-21 22:51:28 +08:00
@maggch97 这个设计既然是有问题的。首先入参并不是一个 set ,而就是一个 str 。不信你自己去试 TypeError: rstrip arg must be None or str 。其次谁说的空格都必须是「一个」 char ? 比如我只想去掉末尾的 \r\n 但是保留 \n\r 呢?
geeglo
2022-12-21 22:53:12 +08:00
别争啦。PHP 也这样。
Jirajine
2022-12-21 22:53:56 +08:00
@weyou 设计缺陷就是设计缺陷。character set 和 string 就不该共用一个类型。把这个函数接受的类型改成 char set ,使用的时候 ratrip(set("abcda"))就不会被误解了。
Trim21
2022-12-21 23:04:15 +08:00
@lambdaq #11 你描述的这种行为已经不再是 python 的 rstrip 或者 js 的 trimEnd 这一类函数的行为了,而是前面提到的新 api removesuffix 了


@Jirajine #13 字符串的 strip 函数添加的时候 python 还没有内置的 set 类型。
maggch97
2022-12-21 23:08:57 +08:00
@lambdaq char[] as char set 这种用法不常见吗?
一个 array 就能表达的结构必须要一个 hash 表或者树?
https://learn.microsoft.com/en-us/dotnet/api/system.string.trim?view=net-7.0#system-string-trim(system-char()) 要不要看看其他语言是怎么设计的?
全天下的语言都有设计缺陷?
xuyang2
2022-12-22 08:24:42 +08:00
@maggch97
这就是编程语言的"后发优势"啊

https://docs.python.org/2.7/library/stdtypes.html#str.rstrip
Changed in version 2.2.2: Support for the chars argument.

https://www.python.org/downloads/release/python-222/
Python 2.2.2
Release Date: Oct. 14, 2002
krixaar
2022-12-22 09:08:10 +08:00
@lambdaq #10 你可以给 str 类加个 remove_all_these_characters_and_their_combinations_from_the_right_side_of_the_string()方法然后提个 PEP 啊,Python 开源的你可以直接去提意见修改对不对,在这里跟我们对线干啥呢?
snw
2022-12-22 09:26:23 +08:00
在我看来这函数取名和文档示例都不好,你看人家 PHP 就很好(虽然我更喜欢巨硬家的文档):
https://www.php.net/manual/en/function.rtrim.php

这个函数就该叫 rtrim(),主要使用场景是移除字符串末尾多余的非显示字符。PHP 的文档看一眼语法例子就能明白,Python 的文档读一遍一头雾水:我为什么要把 mississippi 变成 mississ ?为什么是从倒数第 2 个 i 开始截而不是从倒数第 1/4 个 i 开始截?
pepesii
2022-12-22 09:36:42 +08:00
哈哈哈,曾经我也在这儿掉过坑,学艺不精啊
NoAnyLove
2022-12-22 09:38:59 +08:00
@snw 这文档哪儿有问题了,文字和例子都给得清清楚楚啊。都说了是任意 combination 了,所以右边的`ippi`被移除了,因为用任意数量的 i 、p 、z 可以组成`ippz`,再之后的`s`就不行了,因为`s`不在`ipz`里面,所以就停止了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/903994

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX