【问题标题】:python class behaves like dictionary-or-list-data-likepython 类的行为类似于字典或列表数据
【发布时间】:2017-01-10 04:46:39
【问题描述】:

在 python3 控制台中,输入这些:

>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=4, micro=3, releaselevel='final', serial=0)
>>> type(sys.version_info)  # this is class type
<class 'sys.version_info'>
>>> sys.version_info[0:2]  # ?? But it acts like a list-data-like
(3, 4)

我的问题是:

  1. 类如何表现得像字典或列表数据一样?
  2. 可以举个例子来构造一个这样的类吗?
  3. 是否有一些关于 这个?

【问题讨论】:

  • 注意,这不像字典......它的行为更像是带有命名成员的序列。
  • 是的,我同意你的看法。这是我的错误。@mgilson

标签: python list class dictionary


【解决方案1】:

这很容易......您需要做的就是定义一个处理切片或整数/字符串查找的__getitem__ 方法。你几乎可以做任何你想做的事......

class Foo(object):
    def __init__(self, bar, baz):
        self.bar = bar
        self.baz = baz
    def __getitem__(self, ix):
        return (self.bar, self.baz).__getitem__(ix)

以下是在以下情况下将作为ix 传递给__getitem__ 的备忘单:

f[1]  # f.__getitem__(1)
f[1:]  # f.__getitem__(slice(1, None, None))
f[1:, 2]  # f.__getitem__( (slice(1, None, None), 2) )
f[1, 2]  # f.__getitem__( (1, 2) )
f[(1, 2)]  # f.__getitem__( (1, 2) )

诀窍(可能有点不重要)是简单地编写__getitem__,以便它查看传递的对象的类型,然后做正确的事情。对于我的回答,我通过在我的__getitem__ 中创建一个tuple 作弊,然后我在元组上调用了__getitem__(因为它在我想要支持的所有情况下都做了正确的事情)

以下是一些用法示例:

>>> f = Foo(1, 2)
>>> f[1]
2
>>> f[0]
1
>>> f[:]
(1, 2)

请注意,您通常甚至不需要自己执行此操作。您可以创建一个named tuple 来为您完成这项工作:

from collections import namedtuple
Foo = namedtuple('Foo', 'bar, baz')

而且用法也差不多:

>>> f = Foo(1, 2)
>>> f[1]
2
>>> f[0]
1
>>> f[:]
(1, 2)

这里的主要区别是我们的命名元组是不可变的。一旦创建,我们就无法更改它的成员。

【讨论】:

    【解决方案2】:

    Python 包含多种emulating container types 的方法,例如字典和列表。

    特别是考虑以下类:

     class MyDict(object):
         def __getitem__(self, key):
              # Called for getting obj[key]
    
         def __setitem__(self, key, value):
              # Called for setting obj[key] = value
    

    如果你写

    obj = MyDict()
    

    然后

    obj[3]
    

    将调用第一个方法,并且

    obj[3] = 'foo'
    

    将调用第二种方法。

    如果你还想支持

    len(obj)
    

    那么你只需要添加方法

    def __len__(self):
        # Return here the logical length
    

    这是一个由列表实现的(非常低效的)字典示例

    class MyDict(object):
        def __init__(self, seq=None):
            self._vals = list(seq) if seq is not None else []
    
        def __getitem__(self, key):
            return [v[1] for v in self._vals if v[0] == key][0]
    
        def __setitem__(self, key, val):
            self._vals = [v for v in self._vals if v[0] != key]
            self._vals.append((key, val))
    
        def __len__(self):
            return len(self._vals)
    

    您可以像普通的dict 一样使用它:

    obj = MyDict()
    obj[2] = 'b'
    >>> obj[2]
    'b'
    

    【讨论】:

      【解决方案3】:

      我认为在 python 中,像 ECMAScript(又名 javascript)类是字典或 关联数组associative array)。因为您可以在运行时向您的类添加属性或方法。(see)

      class A(object):
          def __init__(self):
              self.x = 0
      a = A()
      a.y=5
      print a.y # 5
      

      如果你想写一个这样的类,你可以使用__getitem____setitem__ 方法:

      class A(object):
          class B(object):
              def __init__(self, x, y):
                  self.vals = (x, y)
              def __getitem__(self, key):
                  return self.vals[key]
              def __setitem__(self, key, val):
                  self.vals[key] = val
              def __len__(self):
                  return len(self.__vals)
          def __init__(self, x, y):
              self.b = self.B(x,y)
      
      
      
      a = A('foo','baz')
      
      print type(a.b) # __main__.b     __main__ because we run script straightly
      print a.b[:]    # ('foo', 'baz')
      

      【讨论】:

        【解决方案4】:

        您可以通过在类中重写 getitem() 和 setitem() 来实现相同的行为。

            class Example:
                def __getitem__(self, index):
                    return index ** 2
        
            >>> X = Example()
            >>> X[2]                                
            >>> 4
        

        你也可以在你的类中重写 setitem() 来实现 setter 类的东西。

        【讨论】:

          猜你喜欢
          • 2017-10-26
          • 1970-01-01
          • 2013-06-10
          • 1970-01-01
          • 2013-04-18
          • 1970-01-01
          • 2021-06-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多