从列表中创建实例名称(Python)

3
我有一个函数,可以构建随机数量的对象实例。为了演示一般思想,我们假装这是一个构建类似nethack房间的算法。 要求是我事先不知道会有多少个实例;这些实例是随机和即时生成的。 简要说明:我完全意识到以下代码是无效的,但它应该(希望如此!)展示了我的目标。
import random

class Levelbuild(object):

    def __init__(self):
        self.l1 = dict({0:'a',1:'b',2:'c',3:'d',4:'e',5:'f',6:'g',7:'h',8:'i'})
        # Pick a random number between 4 and 9.
        for i in range(random.randint(4,9)):
            self.l1[i] = Roombuilder()
如果我们假设所选的随机整数是5,则理想结果将是5个Roombuilder()实例,分别标记为a、b、c、d和e。 有没有简单的方法来做到这一点?有没有办法做到这一点? --编辑-- 感谢Nick ODell的答案。这不是完全的复制/粘贴,但它是一个适用于我所需的变体。
import random

class Room(object):
    def __init__(self):
        self.size = (5,5)

class Level(object):

    def __init__(self):
        roomnames = ['a','b','c','d','e','f','g','h','i']
        self.rooms = {}
        for i in range(random.randint(4, 9)):
            self.rooms[roomnames[i]] = Room()
不必手工构建每个“房间”,现在我可以...
test = Level()
print test.rooms['a'].size
>>> (5,5)

这里的问题是什么?生成与数字相对应的字母?将标签分配给类别?我不太确定你在这里遇到了什么问题。 - Gareth Latty
你想要将n级对象作为Levelbuild类的命名成员吗?你可能需要重新考虑你的设计,因为你可能希望将它们存储为更易于迭代的有序数据集,比如列表或有序字典,并存储在levelmanager或levelstore下,而不是直接存储在构建器下面。 - Silas Ray
说实话,生成这些名称最简单的方法是使用“dict(enumerate(string.ascii_lowercase))”——假设您知道您始终只有不到26个项目(考虑到您当前的解决方案,这应该没问题)。 - Gareth Latty
@sr2222:发布的语法旨在尽可能地使其“基本”;我最初发布的代码行可以被视为Level对象中的“generate_rooms()方法。在调试时,我将该代码置于__init __()下,以简化测试部分,这样我只需创建Level类并查看所做的任何更改是否符合我的要求。从某种意义上说,我正在尝试形成一个容器,其中包含我需要引用的对象;在desert.Level()`上,我可以轻松访问单个沙漠房间以及“沙漠全局变量”(缺乏更好的术语)。 - Kay Dee
@Lattyware:没有什么好的理由。我还在自学中摸索;我会尝试相应地调整我的方法,并养成更好的习惯。 - Kay Dee
显示剩余5条评论
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3
import string
import random

class Levelbuild(object):

  def __init__(self,min_room_count,max_room_count):

    rooms_temp = [new RoomBuilder() for i in range(random.randint(min_room_count,max_room_count))]
    self.l1 = dict(zip(string.ascii_lowercase, rooms_temp))
注意:如果超过 26 个房间,则此操作将默默失败。

一个简洁而简单的Pythonic方法。 - Christian Groleau
这不完全是我正在使用的东西,但它给了我所需的信息,谢谢! :) - Kay Dee

0
你其实已经很接近了。你不需要一个字典,只需要使用一个列表即可。(顺便说一下,{...} 已经是一个字典了,所以用 dict() 包装它并没有什么作用。)
roomnames = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
self.rooms = []
for i in range(random.randint(4, 9)):
    self.rooms.append(Roombuilder(roomnames[i]))
说实话,在类名中放置builder有点奇怪。这些对象是房间,对吧?所以类型应该只是Room

根据实现方式,在类名中加入builder是完全合适的。然而,如果你将其称为builder,将构建的项存储为类成员并没有真正意义。 - Silas Ray
最好使用类似于for nameint, i in enumerate(...): self.rooms.append(Roombuilder(chr(ord('a') + nameint)))的方式,这样你就不需要一个名称列表。 - agf
@agf 我希望他不总是打算使用升序字母来命名房间,否则ASCII技巧就不值得麻烦了。 - Eevee
@Eevee:仅使用字母作为房间名称的危险在哪里?我同样可以使用其他单词——但在完整代码的上下文中,我将主要使用dict.keys()作为一种同时检查所有房间信息的方式;除了特殊情况(区分“特殊”房间与随机生成的房间之间),我不会经常按名称引用各个房间。对于“特殊”房间,我可以手动调用Room类。 - Kay Dee
@KayDee:如果你不是用名字来指代房间,那么它们为什么需要名字呢?忘掉字母,只需将它们列成列表(或集合,或其他)。 - Eevee
显示剩余6条评论

0
作为对于更一般解决方案的另一个答案(主要是作为Nick ODell's answer的补充),如果你想处理任意数量的名称,这是一个非常简单的解决方案,使用无限生成器即可:
import string
import itertools

def generate_names(characters):
    for i in itertools.count(1):
        for name in itertools.product(characters, repeat=i):
            yield "".join(name)

然后,您可以像使用其他生成器一样使用它:

>>>print(dict(zip(generate_names(string.ascii_lowercase), range(30))))
{'aa': 26, 'ac': 28, 'ab': 27, 'ad': 29, 'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18, 'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}

如果您需要生成实际的 名称,那么您有几个选择。如果您需要一个真实的单词,请从字典文件中选择(大多数 Linux 用户在 /usr/share/dict 中都有一个)。如果您需要类似于单词的东西,那么我实际上编写了使用马尔可夫链生成这样的“单词”的 Python 脚本,该脚本在 GPL 下可用。当然,您需要检查这些是否唯一。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,