【问题标题】:Using exec() function to make a string the name of a class使用 exec() 函数使字符串成为类的名称
【发布时间】:2021-06-29 18:29:31
【问题描述】:

我想创建一个类的一些实例,并且我希望它们的名称来自存储在列表中的一堆字符串,我使用exec 函数来指定名称:

class Person:
    def __init__(self,fname):
        self.fname = fname

    def get_fname(self):
        return(self.fname)


people = ["Paul","Steve","Martin","Jack"]
for item in people:
    exec("%s = %s" %(item,Person(item)))

但我收到此错误:

File "<ipython-input-18-a79ddedb8e1d>", line 10, in <module>
exec("%s = %s" %(item,Person(item)))

File "<string>", line 1
    Paul = <__main__.Person object at 0x000001A31E1BA0D0>
           ^
SyntaxError: invalid syntax

【问题讨论】:

  • 为什么为此您需要(或选择使用)exec()?哪些特定约束控制哪些(如果有)非exec()-使用答案适用或可接受?
  • 顺便说一句,如果您的目标是能够将您的Person 序列化为字符串,然后将其反序列化回一个对象,(1)repr(),而不是str(),是合适的使用这种方式;但是 (2) 使用专门为此目的构建的 pickle 模块会更好。
  • 我猜应该是exec("%s = Person(%s)" %(item,repr(item)))

标签: python string class


【解决方案1】:

您的Person 类需要__str__ method 才能很好地打印!

    ...
    def __str__(self):
        return self.fname  # or self.get_fname()

此外,没有必要 exec() 这些,它们可以(几乎肯定应该)被放入字典或列表等集合中

my_dict = {}
for name in names:
    my_dict[name] = Person(name)

这将使名称成为字典的键,因此以后可以通过索引my_dict.get(some_name) 引用它们,这可能是您想要的,并且比尝试将每个名称都保留为新变量更易于维护(可能浪费资源,如果有人的名字是你需要的内置函数怎么办?..)


如果您真的想使用exec() 来创建对象的实例(尽管您根本不需要这样做,实际上也不需要两次尝试!),这就是您想要定义@987654329 的地方@ - 应该由您编写,以便它可以用于创建父对象

Exceptions 就是一个很好的例子

>>> ex = ValueError("something went wrong")
>>> print(ex)
something went wrong
>>> print(repr(ex))
ValueError('something went wrong')

注意如何使用 representation 来创建原始对象的新实例

【讨论】:

  • 这是对的,但它假定 OP 的代码应该工作。我不确定情况是否如此——最好以完全不依赖于exec() 的方式完成作业。
  • 你是对的;他们不需要exec();让我做一个更完整的答案
  • ...如果他们的目标是创建一个可以作为 Python 代码运行以取回原始对象的表示,那是 repr() 的工作,而不是 str()。也许是一个模糊的像def __repr__(self): return r'{self.__class__}(fname={self.name.repr()})' 之类的实现?)
猜你喜欢
  • 2019-11-23
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
  • 2018-04-24
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
相关资源
最近更新 更多