Ruby代码的惯用Python版本,带有测试语句的while循环



以下代码Ruby代码将迭代源字符串,并生成一个由"分隔的累积单词列表字符,而不是最后一个"."之后的字符。

例如,给定一个源字符串"Company.Dept.Group.Team",结果将是。。。["公司部门集团"、"公司部门"、"企业"]

假设Python中的while循环(我相信)只测试一个表达式,而不是下面所示的语句,那么如何最好地用惯用Python编写呢?

#ruby
source = 'Company.Dept.Group.Team'
results = []
temp = source.clone
while (i = temp.rindex('.'))  # test statement not supported in Python?
  temp = temp[0...i]
  results << temp
end
p results   # >> ["Company.Dept.Group", "Company.Dept", "Company"]

Python的习惯用法是这样的:

while True:
    i = temp.rindex('.')
    if not i:
        break
    ...
>>> source = 'Company.Dept.Group.Team'
>>> last = []
>>> [last.append(s) or '.'.join(last) for s in source.split('.')[:-1]]
['Company', 'Company.Dept', 'Company.Dept.Group']

为了实现这一点,我可能会做:

source = 'Company.Dept.Group.Team'
split_source = source.split('.')
results = ['.'.join(split_source[0:x]) for x in xrange(len(split_source) - 1, 0, -1)]
print results

直译更像:

source = 'Company.Dept.Group.Team'
temp = source
results = []
while True:
    i = temp.rfind('.')
    if i < 0:
        break
    temp = temp[0:i]
    results.append(temp)
print results

或者,如果你喜欢:

source = 'Company.Dept.Group.Team'
temp = source
results = []
try:
    while True:
        temp = temp[0:temp.rindex('.')]
        results.append(temp)
except ValueError:
    pass
print results

或者:

source = 'Company.Dept.Group.Team'
temp = source
results = []
i = temp.rfind('.')
while i > 0:
    temp = temp[0:i]
    results.append(temp)
    i = temp.rfind('.')
print results

正如您所指出的,您不能将赋值视为一个表达式,这使得这些情况有点不雅。我认为前一种情况——即"while True"——比上一种更常见。

关于更多背景,这篇文章看起来不错:http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm

如果你习惯了Python,你会看到到处都是列表理解和迭代器/生成器!

Python可能是

source = 'Company.Dept.Group.Team'
# generate substrings
temp = source.split(".")
results = [".".join(temp[:i+1]) for i,s in enumerate(temp)]
# pop the team (alternatively slice the team out above)
results.pop()
# reverse results
result.reverse()
print result # should yield ["Company.Dept.Group", "Company.Dept", "Company"]

但很可能还有更惯用的解决方案。。。

我会做

>>> import re
>>> source = 'Company.Dept.Group.Team'
>>> results = [source[:m.start()] for m in re.finditer(r".", source)]
>>> results
['Company', 'Company.Dept', 'Company.Dept.Group']

(如果希望反转顺序,请使用reversed(results))。

将代码或多或少地直译成Python的方法是

source = 'Company.Dept.Group.Team'
results = []
temp = source
while True:
    try:
        i = temp.rindex('.')
        temp = temp[:i]    
        results.append(temp)
    except ValueError:
        break
print(results)

最新更新