【问题标题】:Python array slicing -- How can 2D array slicing be implemented?Python 数组切片——如何实现二维数组切片?
【发布时间】:2013-04-12 09:10:48
【问题描述】:

我想知道如何在 Python 中实现二维数组切片?

例如,

arr是自定义类二维数组的一个实例。

如果我想在这个对象上启用 2D 切片语法,如下所示:

arr[:,1:3] #retrieve the 1 and 2 column values of every row

arr[,:3] #retrieve the 1 and 2 column values of every row

用法和语法就像numpy.array。但是我们自己怎么才能实现这种功能呢?

PS:

我的想法:

对于第一种情况,[:,1:3] 部分就像两个切片的元组

但是,对于第二种情况,[,1:3] 似乎很神秘。

【问题讨论】:

  • 如果你正在实现一个类似于 numpy 类的类并且想要类似的行为,为什么不检查他们的代码呢?
  • 你想自己实现,还是想知道怎么做?

标签: python arrays slice


【解决方案1】:

对于读取访问,您需要覆盖 __getitem__ 方法:

class ArrayLike(object):
    def __init__(self):
        pass
    def __getitem__(self, arg):
        (rows,cols) = arg # unpack, assumes that we always pass in 2-arguments
        # TODO: parse/interpret the rows/cols parameters,
        # for single indices, they will be integers, for slices, they'll be slice objects
        # here's a dummy implementation as a placeholder 
        return numpy.eye(10)[rows, cols]

其中一个棘手的地方是__getitem__ 总是只使用一个参数(除了 self), 当您将多个逗号分隔的项目放在方括号内时,您实际上提供了一个元组作为__getitem__ 调用的参数;因此需要 在里面解压这个元组(并且可以选择验证元组的长度是否合适) 函数。

现在给定a = ArrayLike(),你最终得到

  • a[2,3] 表示rows=2cols=3
  • a[:3,2] 表示rows=slice(None, 3, None)cols=3

等等;您必须查看documentation on slice objects 才能决定 你想如何使用切片信息从你的类中提取你需要的数据。

为了使它更像一个 numpy 数组,您还需要覆盖 __setitem__,以 允许分配给元素/切片。

【讨论】:

    【解决方案2】:

    如果它是你自己的类并且你愿意传入一个字符串,这是一个技巧。

    How to override the [] operator?

    class Array(object):
    
        def __init__(self, m, n):
            """Create junk demo array."""
            self.m = m
            self.n = n
            row = list(range(self.n))
            self.array = map(lambda x:row, range(self.m))
    
        def __getitem__(self, index_string):
            """Implement slicing/indexing."""
    
            row_index, _, col_index = index_string.partition(",")
    
            if row_index == '' or row_index==":":
                row_start = 0
                row_stop = self.m
            elif ':' in row_index:
                row_start, _, row_stop = row_index.partition(":")
                try:
                    row_start = int(row_start)
                    row_stop = int(row_stop)
                except ValueError:
                    print "Bad Data"
            else:
                try:
                    row_start = int(row_index)
                    row_stop = int(row_index) + 1
                except ValueError:
                    print "Bad Data"
    
            if col_index == '' or col_index == ":":
                col_start = 0
                col_stop = self.n
            elif ':' in col_index:
                col_start, _, col_stop = col_index.partition(":")
                try:
                    col_start = int(col_start)
                    col_stop = int(col_stop)
                except ValueError:
                    print "Bad Data"
            else:
                try:
                    col_start = int(col_index)
                    col_stop = int(col_index) + 1
                except ValueError:
                    print "Bad Data"
    
            return map(lambda x: self.array[x][col_start:col_stop],
                           range(row_start, row_stop))
    
        def __str__(self):
            return str(self.array)
    
        def __repr__(self):
            return str(self.array)
    
    
    array = Array(4, 5)
    print array
    out: [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
    
    array[",1:3"]
    out: [[1, 2], [1, 2], [1, 2], [1, 2]]
    
    array[":,1:3"]
    out: [[1, 2], [1, 2], [1, 2], [1, 2]]
    

    【讨论】:

      【解决方案3】:

      如果你想知道数组切片的规则,下图可能会有所帮助:

      【讨论】:

        【解决方案4】:

        obj[,:3] 不是有效的python,因此它会引发SyntaxError——因此,您不能在源文件中使用该语法。 (当您尝试在 numpy 数组上使用它时也会失败)

        【讨论】:

        • jokes 我想我们总是希望他们在 python4.0 系列中添加这种语法...
        • 啊,多谢提醒!我想我现在有线索了!
        • 没错,obj[,:3] 不是有效的语法,但您可以同时实现 obj[:,:3]obj[None,:3],因为它们是有效的语法......
        猜你喜欢
        • 1970-01-01
        • 2019-08-08
        • 2020-05-03
        • 2012-11-10
        • 2011-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-06
        相关资源
        最近更新 更多