【问题标题】:Create a list property in Python在 Python 中创建列表属性
【发布时间】:2016-01-13 16:05:54
【问题描述】:

我开始使用 Python 3 进行 OOP,我发现 property 的概念非常有趣。

我需要封装一个私有列表,但是如何将这个范例用于列表?

这是我天真的尝试:

class Foo:
    """ Naive try to create a list property.. and obvious fail """

    def __init__(self, list):
        self._list = list

    def _get_list(self, i):
        print("Accessed element {}".format(i))
        return self._list[i]

    def _set_list(self, i, new):
        print("Set element {} to {}".format(i, new))
        self._list[i] = new

    list = property(_get_list, _set_list)

当我尝试以下代码时,这与预期不符,甚至导致 python 崩溃。这是我希望Foo 展示的虚构行为:

>>> f = Foo([1, 2, 3])
>>> f.list
[1, 2, 3]
>>> f.list[1]
Accessed element 1
2
>>> f.list[1] = 12
Set element 1 to 12
>>> f.list
[1, 12, 3]

【问题讨论】:

  • prints 重要吗?
  • @AnandSKumar 是的,因为它们实际上代表了对我使用 inew 的值执行的其他类成员的进一步更新。

标签: python list python-3.x indexing properties


【解决方案1】:

您的代码中存在一些问题。它们可能不是唯一的问题,但修复它们会让你走得更远:

  • 属性用于新样式类。它们源自object

    class Foo(object):

  • getter(property 的第一个参数将在没有参数的情况下调用。所以_get_list 不能有第二个参数i。同样适用于_set_list,它只能有一个参数,不能有两个. (self 是隐含的,这里不计算在内。)

【讨论】:

  • 非常正确。这就是为什么我称我的尝试“天真”;)
【解决方案2】:
import collections


class PrivateList(collections.MutableSequence):
    def __init__(self, initial=None):
        self._list = initial or []

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

    def __getitem__(self, item):
        print("Accessed element {}".format(item))
        return self._list[item]

    def __setitem__(self, key, value):
        print("Set element {} to {}".format(key, value))
        self._list[key] = value

    def __delitem__(self, key):
        print("Deleting element {}".format(key))
        del self._list[key]

    def __len__(self):
        print("Getting length")
        return len(self._list)

    def insert(self, index, item):
        print("Inserting item {} at {}".format(item, index))
        self._list.insert(index, item)


class Foo(object):
    def __init__(self, a_list):
        self.list = PrivateList(a_list)

然后运行这个:

foo = Foo([1,2,3])
print(foo.list)
print(foo.list[1])
foo.list[1] = 12
print(foo.list)

输出:

[1, 2, 3]
Accessed element 1
2
Set element 1 to 12
[1, 12, 3]

【讨论】:

  • 所以我当时需要一个新类并覆盖[] 运算符。现在这很有意义。谢谢! ^ ^
  • 是的,您的代码只检查了对list 属性的访问,而不是对该属性返回的对象的任何操作。
猜你喜欢
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2014-10-17
  • 2019-02-09
  • 2016-11-10
  • 1970-01-01
相关资源
最近更新 更多