如何使用setItem设置类对象参数的值,就像它是一个dict一样__

2024-04-25 23:21:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我实现了一个示例类PointLocation

import collections as _collections

Point = _collections.namedtuple("Point", ("x", "y", "z"))

class PointLocation(object):
    def __init__(self, x, y, z):
        self._x = x
        self._y = y
        self._z = z
        self._location = Point(x, y, z)
        print "First Item: %s " % self._location[0]

    def __repr__(self):
        return "%s(%r, %r, %r)" % (
            self.__class__.__name__,
            self._x,
            self._y,
            self._z,
            )


    def __getitem__(self, key):
        """
            to make the object to be used in a manner similar to a tuple or list
        """
        return self._location.__getitem__(key)

    def __setitem__(self, key, value):
        if key == 0:
            self._location = Point(self._location.x, value)
        else:
            self._location = Point(value, self._location.y)

我试图设置一个参数的值,使用:

pointLocationObj[0] = 1

但我总是犯错

Traceback (most recent call last):
  File "/usr/san/Desktop/testScripts/classObject_returnsList.py", line 40, in <module>
    pointLocationObj[0] = 7
  File "/usr/san/Desktop/testScripts/classObject_returnsList.py", line 32, in __setitem__
    self._location = Point(self._location.x, value)
TypeError: __new__() takes exactly 4 arguments (3 given)

Tags: tokeyinselfreturnobjectvaluedef
2条回答

您的Point命名元组需要xyz参数:

Point = _collections.namedtuple("Point", ("x", "y", "z"))

虽然您只提供了其中的两个;但您可能也想传入self._location.z

def __setitem__(self, key, value):
    if key == 0:
        self._location = Point(self._location.x, value, self._location.y)
    else:
        self._location = Point(value, self._location.y, self._location.z)

还可以使用^{} method替换特定属性(返回新实例):

def __setitem__(self, key, value):
    if key == 0:
        self._location = self._location._replace(y=value)
    else:
        self._location = self._location._replace(x=value)

如果要使用索引引用xyz,请创建一个字典作为namedtuple._replace()的关键字参数:

def __setitem__(self, key, value):
    coordinate = self._location._fields[key]   # can raise IndexError, we want to propagate that
    self._location = self._location._replace(**{coordinate: value})

这里我假设你的意思是0x,而不是1。你知道吗

只需更新下面的方法,就可以按预期工作。谢谢@Martijin帮我睁开眼睛。你知道吗

def __setitem__(self, key, value):
    if key == 0:
        self._location = Point(value, self._location.y, self._location.z)
    elif key == 1:
        self._location = Point(self._location.x, value, self._location.z)
    elif key == 2:
        self._location = Point(self._location.x, self._location.y, value)
    else:
        raise IndexError("%s takes %s has arguments. You are trying to update %s argument." % (
            self.__class__.__name__, 
            len(self._location), key+1)
            )

第二次更新:

def __setitem__(self, key, value):
    """ update the value of argument like a dictionary
    """
    try:
        self._location = self._location._replace(**{'xyz'[key]: value})
    except IndexError:
        raise IndexError("%s takes %s has arguments. You are trying to update %s argument." % (
            self.__class__.__name__, 
            len(self._location), key)
            )

相关问题 更多 >

    热门问题