2

由于缺乏更好的词,我用这个标题。

我想要的是能够做这样的事情:

>>> from random import randint
>>> fruits = [
...     "Orange",
...     "Banana",
...     f"{randint(2,5)} Cherries",
... ]

>>> fruits[2]
'3 Cherries'

>>> fruits[2]
'5 Cherries'

>>> fruits[2]
'2 Cherries'

但相反,字符串中的文字表达式在创建列表时被评估一次,并且每次访问它时都会给出相同的结果。

我想知道除了编写一些复杂的边缘案例处理之外是否有更简单/更智能的方法来解决这个问题(毕竟我们是程序员;谁不喜欢编写漂亮的代码并且优雅而花哨?)。我说的是边缘情况处理,因为我的 49 个字符串中只有 6 个需要这种“特殊”行为。

到目前为止,我尝试的是从 randint 调用中创建一个 lambda 函数,但这无济于事;同样的结果。也许这是惰性评估的一个案例,但我需要一些关于如何(或是否?)将它与列表一起使用的指导。

4

4 回答 4

7

如果您希望您的某些项目是文字的,但有些是可调用的,您可以创建自己的版本list

from random import randint

class LazyList(list):
    'Like a list, but invokes callables'
    def __getitem__(self, key):
        item = super().__getitem__(key)
        if callable(item):
            item = item()
        return item

fruits = LazyList([
    "Orange",
    "Banana",
    lambda: f"{randint(2,5)} Cherries",
])

print(fruits[2])
print(fruits[2])
于 2018-11-05T23:11:08.017 回答
3

你在正确的轨道上,想要一个 lambda:

from random import randint

fruits = [
        lambda: "Orange",
        lambda: "Banana",
        lambda: f"{randint(2, 5)} Cherries",
]

print(fruits[2]())
print(fruits[2]())
print(fruits[2]())

有一些方法可以避免,()但这可能不值得。

于 2018-11-05T23:05:18.087 回答
0

免责声明:我是图书馆的作者

你可以使用seqtools做惰性映射,它支持迭代和切片:

>>> fruits = seqtools.smap(lambda x: x if isinstance(x, str) else x(), 
...                        fruits)
>>> fruits[0]
'Orange'
>>> fruits[-1]
'3 Cherries'

如果您不想在每次调用时重新评估函数元素,您可以添加一些缓存:

fruits = seqtools.add_cache(fruits)

显然,项目分配不能通过映射起作用,因此您将不得不为此欺骗自己。

排序最终将评估列表中的所有项目,因此您最好提前执行此操作并调用常规 list.sort() 方法。

于 2019-07-11T10:48:56.507 回答
0

一开始将 lambda 放入列表中听起来不错,但随后您必须调用列表的特殊(或所有)索引。你不能迭代列表,你不能对列表进行排序,......

恕我直言,创建一个为您提供列表的函数更容易:

from random import randint

def gimme_fruits ():
    return [ "Orange", "Banana", f"{randint(2,5)} Cherries",]

print(gimme_fruits())

输出:

['Orange', 'Banana', '3 Cherries']

['Orange', 'Banana', '4 Cherries']

['Orange', 'Banana', '2 Cherries']

每个列表的樱桃数量都是“固定的”——但你可以这样做:

for f in gimme_fruits() + gimme_fruits() + gimme_fruits():
    print(f)

获取维生素:

Orange
Banana
3 Cherries
Orange
Banana
3 Cherries
Orange
Banana
3 Cherries
于 2018-11-05T23:13:24.770 回答