【问题标题】:Easy way of overriding default methods in custom Python classes?在自定义 Python 类中覆盖默认方法的简单方法?
【发布时间】:2011-04-12 20:27:45
【问题描述】:

我有一个名为 Cell 的类:

class Cell:

    def __init__(self, value, color, size):
        self._value = value
        self._color = color
        self._size = size

    # and other methods...

Cell._value 将存储字符串、整数等(无论我使用该对象做什么)。我希望所有通常使用对象“值”的默认方法都使用<Cell object>._value,以便我可以这样做:

>>> c1 = Cell(7, "blue", (5,10))
>>> c2 = Cell(8, "red", (10, 12))
>>> print c1 + c2
15

>>> c3 = Cell(["ab", "cd"], "yellow", (50, 50))
>>> print len(c3), c3
2 ['ab', 'cd']

# etc.

我可以覆盖所有默认方法:

class Cell:

    def __init__(self, value, color, size):
        # ...

    def __repr__(self):
        return repr(self._value)

    def __str__(self):
        return str(self._value)

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

    def __len__(self):
        return len(self._value)

    # etc.

...但是有更简单的方法吗?

【问题讨论】:

  • 为什么整数 self._value 能够通过键获得索引?你有没有试过取整数的长度?此外,这可能不应该是社区 wiki:没有人会因为这样回答而得到分数,我们喜欢我们在 SO 的一些分数。
  • -1:这不应该是维基。
  • @AaronMcSmooth self._value 可以保存任何数据类型,所以我希望所有可能的方法都可用。
  • 很抱歉设置了这个“社区维基”。我没有意识到残疾点是不可逆转的。现在我知道了。

标签: python class methods overriding


【解决方案1】:

如果我的理解正确,您正在寻找一种将对象的方法委托给该对象的属性的简单方法?

你可以通过定义一个装饰器来避免一些重复:

def delegate(method, prop):
    def decorate(cls):
        setattr(cls, method,
            lambda self, *args, **kwargs:
                getattr(getattr(self, prop), method)(*args, **kwargs))
        return cls
    return decorate

然后,您可以为要委托的每个方法应用装饰器:

@delegate('__len__', '_content')
@delegate('__getitem__', '_content')
class MyList(object):
    def __init__(self, content):
        self._content = content

spam = MyList([1,2,3,4,5])

len(spam) # prints "5"

spam[0] # prints "1"

您可以通过修改装饰器以将多个方法名称作为参数来进一步简化它。

如果您希望您的类充当一个完整的包装器,您可能会覆盖该类的__getattr__ 方法以在失败之前检查包装的对象。这将模拟没有实际继承的子类的行为。

【讨论】:

  • 我认为覆盖__getattr__ 更接近我正在寻找的东西,但我也看到了装饰器选项中的价值。现在我只需要了解__getattr____getattribute__ 之间的区别:docs.python.org/reference/…
【解决方案2】:

您需要重载__add__ 方法才能获得您想要的c1 + c2 行为。

请参阅 here 了解它们的全部信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 2010-09-25
    • 2012-05-04
    • 2019-12-02
    相关资源
    最近更新 更多