【问题标题】:Initialize an object built from a class with a specific dictionary使用特定字典初始化从类构建的对象
【发布时间】:2023-04-01 19:47:01
【问题描述】:

目标是使用__init__ 方法构建一个类,该方法将允许创建将使用特定字典初始化的对象。

详情:

文件mydicts.py 是各种字典的集合。 从我打算创建的类构建的对象将被初始化为来自mydicts.py 的字典之一。

mydicts.py 示例:

dict1 = {k1:v1, k2:v2,...,kn:vn}
dict2 = {k1:v1, k2:v2,...,km:vm}
etc.

我的尝试:

class Example(dict):
    def __init__(self, dictx):
        self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx)

结果:

e = Example('dict1')
print e
{}        # <- got empty dictionary. Want {k1:v1, k2:v2,...,kn:vn}

目标是创建这样的对象:

a = Example(dict1)
print a
# {k1:v1, k2:v2,...,kn:vn}

b = Example(dict2)
print b
# {k1:v1, k2:v2,...,km:vm}

【问题讨论】:

  • 打印关于任何对象的信息,您需要在类中定义__str__ 方法。尝试在该方法中打印 self.dictx,当您打印该类的实例时,它将被隐式调用
  • 我必须接受@iCodez 的解决方案,因为他更详细,但与您建议的想法大致相同。

标签: python class inheritance dictionary python-2.x


【解决方案1】:

由于您没有为您的类定义自定义__str__ methodprint 正在调用父类dict__str__ 方法。此外,这会导致 Python 打印由 dict.__new__ 中的父类创建的空字典,而不是您存储在 self.dictx 中的字典。

因为您的类继承自dict,您应该将getattr 返回的字典传递给父类的__init__ 方法。您可以为此使用super

class Example(dict):
    def __init__(self, dictx):
        dct = getattr(__import__("__main__", fromlist=['m']), dictx)
        super(Example, self).__init__(dct)

这将使用来自dct 的数据初始化父类。换句话说,空字典已被getattr 返回的字典替换。所以,当print调用父级的__str__方法时,会给出正确的输出:

>>> dict1 = {'k1':'v1', 'k2':'v2', 'kn':'vn'}
>>> class Example(dict):
...     def __init__(self, dictx):
...         dct = getattr(__import__("__main__", fromlist=['m']), dictx)
...         super(Example, self).__init__(dct)
...
>>> e = Example('dict1')
>>> print e
{'k2': 'v2', 'k1': 'v1', 'kn': 'vn'}
>>>

另一种解决方案是为您的类定义一个自定义的__str__ 方法,该方法将self.dictx 作为字符串返回:

class Example(dict):
    def __init__(self, dictx):
        self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx)
    def __str__(self):
        return str(self.dictx)

但是请注意,如果您使用这种方法,则没有真正的理由从dict 继承,因为您的类不是新类型的字典;它只是有一个存储为属性的字典。

【讨论】:

    【解决方案2】:

    我认为你让这件事变得比需要的复杂得多。注意到the manual says

    直接使用__import__() 的情况很少见,除非您要导入名称仅在运行时知道的模块。

    但是您在加载时确实知道模块名称,您的数据定义只是有太多变量名称。 my_dicts.py 会更清楚:

    my_dicts = [
        {k1:v1, k2:v2,...,kn:vn},
        {k1:v1, k2:v2,...,km:vm},
        …
    ]
    

    example.py:

    import my_dicts
    
    class Example(dict):
        def __init__(self, n):
            """Returns an Example instance loaded with the nth element
               of my_dict."""
            super(Example, self).__init__(my_dicts.my_dicts[n])
    

    【讨论】:

    • 其实名字就是字典在运行时是已知的,字典是被命名的。不过,不错的解决方案!
    • 然后我回到 CS101 格言,只要你有一组 {d1, d2, ... d10000} 形式的变量,你实际上有一个伪装的列表(数组)。使用伪列表严重限制了数据的灵活性和可扩展性,因为如果您需要 d10001,则需要更改代码以支持它,而不仅仅是数据。此外,__import__ 方法很神秘,下一位读者将继续阅读手册,但仍然想知道fromlist= 在上下文中的含义。
    猜你喜欢
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 2013-06-27
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多