3

是否有任何非显式for方法可以在对象上调用成员n时间?

我正在考虑一些map/reduce/lambda方法,但我想不出一种方法来做到这一点——如果可能的话。

只是为了添加上下文,我正在使用BeautifulSoup,并且我正在从 html 表中提取一些元素;我提取了一些元素,然后是最后一个。

因为我有:

# First value
print value.text

# Second value
value = value.nextSibling
print value.text

# Ninth value
for i in xrange(1, 7):
    value = value.nextSibling
print value.text

我想知道是否有任何lambda方法(或其他方法)可以让我这样做:

# Ninth value
((value = value.nextSibling) for i in xrange(1, 7))
print value.text

PS:不,这种方法没有任何问题for,除了我真的很喜欢单线解决方案,这非常适合我的代码。

4

6 回答 6

7

我对循环有强烈的偏好,但你可以使用reduce

>>> class Foo(object):
...     def __init__(self):
...        self.count = 0
...     def callme(self):
...        self.count += 1
...        return self
... 
>>> a = Foo()
>>> reduce(lambda x,y:x.callme(),range(7),a)
<__main__.Foo object at 0xec390>
>>> a.count
7
于 2013-01-31T22:02:43.127 回答
4

你想要一个相当于这个的单行:

for i in xrange(1, 7):
    value = value.nextSibling

这是一行:

for i in xrange(1, 7): value = value.nextSibling

如果您正在寻找更实用的东西,那么您真正想要的是一个compose功能,因此您可以编写callme()(或attrgetter('my_prop'),或其他)7 次。

于 2013-01-31T22:07:09.847 回答
2

如果BS您可以使用nextSiblingGenerator()withitertools.islice来获取第 n 个兄弟姐妹。它还可以处理没有第 n 个元素的情况。

from itertools import islice

nth = 7
next(islice(elem.nextSiblingGenerator(), nth, None), None)
于 2013-01-31T22:18:31.117 回答
2

免责声明:eval是邪恶的。

value = eval('value' + ('.nextSibling' * 7))
于 2013-01-31T22:49:14.410 回答
1

啊! 但reduce在 Python3 中不可用,至少不是作为内置的。

所以这是我的尝试,可移植到 Python2/3 并基于 OP 失败的尝试:

[globals().update(value=value.nextSibling) for i in range(7)]

假设这value是一个全局变量。如果 value 恰好是成员变量,则改为:

[self.__dict__.update(value=value.nextSibling) for i in range(7)]

您不能使用locals(),因为列表推导创建了一个嵌套的本地范围,因此 reallocals()不能直接使用。但是,您可以通过一些工作来捕获它:

(lambda loc : [loc.update(x=x.nextSibling) for i in range(7)])(locals())

如果您不介意复制行数,或者更容易:

loc = locals()
[loc.update(value=value.nextSibling) for i in range(7)]

或者,如果您真的喜欢单线:

loc = locals() ; [loc.update(value=value.nextSibling) for i in range(7)]

是的,Python 也可以使用;8-)

更新

另一个奇特的变体,现在用map列表理解代替:

list(map(lambda d : d.update(value=value.nextSibling), 7 * [locals()]))

请注意巧妙地使用列表乘法来捕获当前locals() 并同时创建初始迭代。

于 2013-01-31T22:35:22.073 回答
1

最直接的写法是:

value = reduce(lambda x, _: x.nextSibling, xrange(1,7), value)
于 2013-02-01T09:27:08.120 回答