没有内置的 reverse
Python的功能 str
目的。实现此方法的最佳方法是什么?
如果提供非常简洁的答案,请详细说明其效率。例如,是否 str
对象被转换为不同的对象等。
没有内置的 reverse
Python的功能 str
目的。实现此方法的最佳方法是什么?
如果提供非常简洁的答案,请详细说明其效率。例如,是否 str
对象被转换为不同的对象等。
怎么样:
>>> 'hello world'[::-1]
'dlrow olleh'
这是 扩展切片 句法。它的工作原理 [begin:end:step]
- 通过离开开始和结束并指定步长为-1,它会反转一个字符串。
@保罗的 s[::-1]
是最快的;一种较慢的方法(可能更具可读性,但这是有争议的) ''.join(reversed(s))
。
为字符串实现反向函数的最佳方法是什么?
我对这个问题的经验是学术性的。但是,如果您是专业人士正在寻找快速答案,请使用逐步处理的切片 -1
:
>>> 'a string'[::-1]
'gnirts a'
或者更可读(但由于方法名称查找速度较慢,并且在给定迭代器时连接形成列表的事实), str.join
:
>>> ''.join(reversed('a string'))
'gnirts a'
或者为了可读性和可重用性,将切片放在一个函数中
def reversed_string(a_string):
return a_string[::-1]
接着:
>>> reversed_string('a_string')
'gnirts_a'
如果您对学术博览会感兴趣,请继续阅读。
Python的str对象中没有内置的反向函数。
这里有一些你应该知道的Python字符串:
在Python中, 字符串是不可变的。更改字符串不会修改字符串。它创造了一个新的。
字符串是可切片的。切片字符串会以给定的增量从字符串中的一个点(向后或向前)向另一个点提供一个新字符串。它们在下标中采用切片表示法或切片对象:
string[subscript]
下标通过在大括号中包含冒号来创建切片:
string[start:stop:step]
要在大括号外创建切片,您需要创建切片对象:
slice_obj = slice(start, stop, step)
string[slice_obj]
而 ''.join(reversed('foo'))
是可读的,它需要调用一个字符串方法, str.join
,在另一个被称为函数,可能相对较慢。让我们把它放在一个函数中 - 我们将回到它:
def reverse_string_readable_answer(string):
return ''.join(reversed(string))
使用反向切片要快得多:
'foo'[::-1]
但是,对于不太熟悉切片或原作者意图的人,我们怎样才能使其更具可读性和易懂性?让我们在下标表示法之外创建一个切片对象,给它一个描述性名称,并将其传递给下标符号。
start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]
要将其实际实现为一个函数,我认为它在语义上足够清晰,只需使用描述性名称:
def reversed_string(a_string):
return a_string[::-1]
用法很简单:
reversed_string('foo')
如果你有一个教师,他们可能希望你从空字符串开始,并从旧字符串中构建一个新字符串。您可以使用while循环使用纯语法和文字来执行此操作:
def reverse_a_string_slowly(a_string):
new_string = ''
index = len(a_string)
while index:
index -= 1 # index = index - 1
new_string += a_string[index] # new_string = new_string + character
return new_string
这在理论上是不好的,因为,请记住, 字符串是不可变的 - 所以每次看起来你都要在你的角色上添加一个角色 new_string
,理论上每次都会创建一个新的字符串!但是,CPython知道如何在某些情况下优化它,其中这个简单的案例就是一个。
从理论上讲,更好的方法是在列表中收集子字符串,然后再加入它们:
def reverse_a_string_more_slowly(a_string):
new_strings = []
index = len(a_string)
while index:
index -= 1
new_strings.append(a_string[index])
return ''.join(new_strings)
但是,正如我们将在下面的CPython时序中看到的,这实际上需要更长的时间,因为CPython可以优化字符串连接。
以下是时间安排:
>>> a_string = 'amanaplanacanalpanama' * 10
>>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string)))
10.38789987564087
>>> min(timeit.repeat(lambda: reversed_string(a_string)))
0.6622700691223145
>>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string)))
25.756799936294556
>>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string)))
38.73570013046265
CPython优化字符串连接,而其他实现 不得:
...不要依赖CPython为a + = b或a = a + b形式的语句高效实现就地字符串连接。即使在CPython中,这种优化也很脆弱(它只适用于某些类型),并且在不使用引用计数的实现中根本不存在。在库的性能敏感部分中,应使用'.join()形式。这将确保在各种实现中以线性时间进行连接。
### example01 -------------------
mystring = 'coup_ate_grouping'
backwards = mystring[::-1]
print backwards
### ... or even ...
mystring = 'coup_ate_grouping'[::-1]
print mystring
### result01 -------------------
'''
gnipuorg_eta_puoc
'''
提供此答案是为了解决@odigity的以下问题:
哇。起初Paolo提出的解决方案让我感到震惊,但那 我在阅读第一篇文章后感到恐惧,退居二线 评论:“这是非常pythonic。干得好!”我很不安 一个聪明的社区认为使用这种神秘的方法 基本是个好主意。为什么不是s.reverse()?
string.reverse()
string.reverse()
避免切片表示法。print 'coup_ate_grouping'[-4:] ## => 'ping'
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-1] ## => 'g'
[-1]
可能会让一些开发者失望Python有一个特殊的环境需要注意:字符串是一个 迭代 类型。
排除a的一个理由 string.reverse()
方法是让python开发人员激励利用这种特殊情况的力量。
简而言之,这仅仅意味着字符串中的每个单独字符都可以作为元素顺序排列的一部分轻松操作,就像其他编程语言中的数组一样。
要了解其工作原理,查看example02可以提供良好的概述。
### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0] ## => 'c'
print 'coup_ate_grouping'[1] ## => 'o'
print 'coup_ate_grouping'[2] ## => 'u'
## start (with negative integers)
print 'coup_ate_grouping'[-1] ## => 'g'
print 'coup_ate_grouping'[-2] ## => 'n'
print 'coup_ate_grouping'[-3] ## => 'i'
## start:end
print 'coup_ate_grouping'[0:4] ## => 'coup'
print 'coup_ate_grouping'[4:8] ## => '_ate'
print 'coup_ate_grouping'[8:12] ## => '_gro'
## start:end
print 'coup_ate_grouping'[-4:] ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-4:-2] ## => 'pi'
print 'coup_ate_grouping'[-4:-3] ## => 'p'
print 'coup_ate_grouping'[-4:-4] ## => ''
print 'coup_ate_grouping'[0:-1] ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:] ## => 'coup_ate_grouping' (counter-intuitive)
## start:end:step (or start:end:stride)
print 'coup_ate_grouping'[-1::1] ## => 'g'
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'
## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'puoc'
该 认知负荷 与理解切片符号在python中如何工作相关联对于那些不希望花费大量时间学习语言的采用者和开发者来说确实太过分了。
然而,一旦理解了基本原理,这种方法相对于固定字符串操作方法的能力就会非常有利。
对于那些不这么认为的人,有其他方法,例如lambda函数,迭代器或简单的一次性函数声明。
如果需要,开发人员可以实现自己的string.reverse()方法,但是理解python这方面的基本原理是很好的。
看待它的一个较小的令人困惑的方式是:
string = 'happy'
print(string)
'快乐'
string_reversed = string[-1::-1]
print(string_reversed)
“帕”
英文[-1 :: - 1]读作:
“从-1开始,一路走,步长为-1”
在不使用reverse()或[:: - 1]的情况下在python中反转字符串
def reverse(test):
n = len(test)
x=""
for i in range(n-1,-1,-1):
x += test[i]
return x
def reverse(input):
return reduce(lambda x,y : y+x, input)
def rev_string(s):
return s[::-1]
def rev_string(s):
return ''.join(reversed(s))
def rev_string(s):
if len(s) == 1:
return s
return s[-1] + rev_string(s[:-1])
这是一个不花哨的:
def reverse(text):
r_text = ''
index = len(text) - 1
while index >= 0:
r_text += text[index] #string canbe concatenated
index -= 1
return r_text
print reverse("hello, world!")
另一种选择,(效率不高!只是为了展示Python的多样性以及许多可能的解决方案!):使用list()函数将字符串转换为列表。列表值是可变数据类型。因此,我们可以使用reverse()方法来反转列表中的对象。然后我们使用带有空分隔符的列表连接方法将列表转换回字符串:
>>> s = 'hello world'
>>> s
'hello world'
>>> t = list(s) # convert to list
>>> t
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
>>> t.reverse() # reverse method of list
>>> t
['d', 'l', 'r', 'o', 'w', ' ', 'o', 'l', 'l', 'e', 'h']
>>> s = ''.join(t) # convert to string
>>> s
'dlrow olleh'
这是一个没有 [::-1]
要么 reversed
(用于学习目的):
def reverse(text):
new_string = []
n = len(text)
while (n > 0):
new_string.append(text[n-1])
n -= 1
return ''.join(new_string)
print reverse("abcd")
您可以使用 +=
连接字符串但是 join()
是比较快的。