如何使python类支持项目分配?

如何使python类支持项目分配?,python,inheritance,built-in-types,object-composition,Python,Inheritance,Built In Types,Object Composition,在查看中的一些代码时,我注意到它们的图形类为自身赋值。我从该类中复制了一些重要的行,并编写了一个示例类,ObjectChild,该类在这种行为下失败 class Graph(dict): def __init__(self, vs=[], es=[]): for v in vs: self.add_vertex(v) for e in es: self.add_edge(e) def add_ed

在查看中的一些代码时,我注意到它们的
图形
类为自身赋值。我从该类中复制了一些重要的行,并编写了一个示例类,
ObjectChild
,该类在这种行为下失败

class Graph(dict):
    def __init__(self, vs=[], es=[]):
        for v in vs:
            self.add_vertex(v)

        for e in es:
            self.add_edge(e)

    def add_edge(self, e):
        v, w = e
        self[v][w] = e
        self[w][v] = e

    def add_vertex(self, v):
        self[v] = {}

class ObjectChild(object):
    def __init__(self, name):
        self['name'] = name
我确信不同的内置类型都有自己的使用方法,但我不确定这是否是我应该尝试在类中构建的东西。有可能吗?怎么可能?这是不是我不应该为之烦恼,而是依赖于简单的组合,例如
self.l=[1,2,3]
?是否应避免在内置类型之外

我这样问是因为有人告诉我“你几乎不应该继承内置python集合”;我不太愿意限制自己接受的建议


为了澄清,我知道
ObjectChild
不会“起作用”,我可以很容易地让它“起作用”,但我很好奇这些内置类型的内部工作原理,它们使它们的接口不同于
object

的子类。它们通过继承
dict
实现了这一魔力。更好的方法是继承或更新

通过执行相同的操作,您可以获得类似的结果:

import collections

class ObjectChild(collections.MutableMapping):
    def __init__(self, name):
        self['name'] = name

您还可以定义两个特殊函数,使类字典类似于:
\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuu(self,key)
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您可以在中看到这样一个示例。

您的ObjectChild不工作,因为它不是dict的子类。以下两种方法都可以工作:

class ObjectChild(dict):
    def __init__(self, name):
        self['name'] = name


免责声明:我可能错了

符号:

self[something]
在Graph类中是合法的,因为它继承了fro dict。此符号来自dictionnaries ssyntax,而不是来自类属性声明语法

尽管与类关联的所有名称空间都是词汇表,但在类ChildObject中,self不是词汇表。因此,您不能使用该语法


Otoh,在你的类Graph中,self是一个词汇表,因为它是一个图,所有的图都是词汇表,因为它们是从dict继承的。

是否使用类似的东西,好吗

def mk_opts_dict(d):
    ''' mk_options_dict(dict) -> an instance of OptionsDict '''
    class OptionsDict(object):
        def __init__(self, d):
            self.__dict__ = d

        def __setitem__(self, key, value):
            self.__dict__[key] = value

        def __getitem__(self, key):
            return self.__dict__[key]

    return OptionsDict(d)

您不需要从dict继承。如果您提供setitemgetitem方法,我相信您也可以获得所需的行为

class a(object):
    def __setitem__(self, k, v):
        self._data[k] = v
    def __getitem__(self, k):
        return self._data[k]
    _data = {}

我意识到这是一篇老文章,但我在寻找关于项目分配的一些细节,并在这里偶然发现了答案。这并不是完全错误的。为了避免从dict继承,您可以使类从继承,然后为
\uuuuu setitem\uuuuuuu
\uuuuuu getitem\uuuuuuu
提供方法

此外,该类还需要支持
\u delitem\u
\u iter\u
\u len\u
,以及(可选)其他继承的混合方法,如
pop
。文档中有关于详细信息的更多信息

from collections.abc import MutableMapping
class ItemAssign(MutableMapping):
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __setitem__(self, k, v):
        setattr(self, k, v)
    def __getitem__(self, k):
        getattr(self, k)
    def __len__(self):
        return 2
    def __delitem__(self, k):
        self[k] = None
    def __iter__(self):
        yield self.a
        yield self.b
示例用法:

>>> x = ItemAssign("banana","apple")
>>> x["a"] = "orange"
>>> x.a
'orange'
>>> del x["a"]
>>> print(x.a)
None
>>> x.pop("b")
'apple'
>>> print(x.b)
None
希望这有助于澄清如何正确地为其他在这篇文章中遇到障碍的人执行项目分配:)

关于继承的小备忘录 对于那些想继承王位的人。 在这种情况下,MyDict将包含原始dict的浅拷贝

class MyDict(dict):
    ...

d = {'a': 1}
md = MyDict(d)

print(d['a'])   # 1
print(md['a'])  # 1

md['a'] = 'new'

print(d['a'])   # 1
print(md['a'])  # new
当您有一个嵌套目录树,并且希望将其中的一部分转换为对象时,这可能会导致问题。更改此对象不会影响其父对象

root = {
    'obj': {
        'a': 1,
        'd': {'x': True}
    }
}
obj = MyDict(root['obj'])

obj['a'] = 2
print(root)   # {'obj': {'a': 1, 'd': {'x': True}}} # 'a' is the same

obj['d']['x'] = False
print(root)   # {'obj': {'a': 1, 'd': {'x': True}}} # 'x' chanded

2020年,只需将以下简单函数添加到类中:

class some_class(object):
    def __setitem__(self, key, value):
        setattr(self, key, value)

    def __getitem__(self, key):
        return getattr(self, key)

这与您的问题无关,但使用
[]
作为默认参数值可能会引起意外。看,我从你们那里得到了一个想法,继承dict、list或tuple是Python中所期望的样式。看起来它们的一些行为可能不同,需要继承,因为它们是用c语言编写的,而不是用Python编写的。如果我错了,请告诉我!我会调查这些。谢谢。我认为
UserDict
已经过时了(从
dict
继承是非法的)
MutableMapping
也不是提供项目访问的东西(它是一种功能)。如果要实现字典式或列表式的项分配和访问,则需要编写(或继承)
\u getitem\u
\u setitem\u
方法。不起作用。投票被否决,因为这是一件很容易检查的事情。
class some_class(object):
    def __setitem__(self, key, value):
        setattr(self, key, value)

    def __getitem__(self, key):
        return getattr(self, key)