【问题标题】:Broadcasting function calls in np.arraynp.array 中的广播函数调用
【发布时间】:2013-03-25 23:11:54
【问题描述】:

我正在尝试创建一个填充了一个对象的 NumPy 数组,我想知道是否有一种方法可以将每个对象广播到整个数组以执行某些操作。

代码:

class player:
    def __init__(self,num = 5):
        self.num = num

    def printnum():
        print(self.num)
...

objs = np.array([player(5),player(6)],dtype=Object)
objs.printnum()

就目前而言,这会返回一个错误。我尝试按照手册将 dtype 更改为:_object,但似乎没有任何效果。

【问题讨论】:

    标签: python class object numpy array-broadcasting


    【解决方案1】:

    一个 numpy 对象数组不继承该对象的方法。 ndarray 方法通常作用于整个数组

    这也不适用于内置类型,例如:

    In [122]: import numpy as np
    
    In [123]: n = 4.0
    
    In [124]: a = np.arange(n)
    
    In [125]: n.is_integer()
    Out[125]: True
    
    In [126]: a.is_integer()
    ---------------------------------------------------------------------------
    AttributeError: 'numpy.ndarray' object has no attribute 'is_integer'
    

    Numpy 广播是使用元素运算符完成的,例如加法:

    In [127]: n
    Out[127]: 4.0
    
    In [128]: a
    Out[128]: array([ 0.,  1.,  2.,  3.])
    
    In [129]: n + a
    Out[129]: array([ 4.,  5.,  6.,  7.])
    

    如果您想在数组中的所有元素上基本调用print,您可以简单地重新定义由print 调用的.__repr__() 方法。我会提醒您,通过覆盖该方法会丢失信息。

    In [148]: class player:
       .....:     def __init__(self, num=5):
       .....:         self.num = num
       .....:     def __repr__(self):
       .....:         return str(self.num)
       .....:     
    
    In [149]: objs = np.array([player(5), player(6)])
    
    In [150]: objs
    Out[150]: array([5, 6], dtype=object)
    
    In [151]: print objs
    [5 6]
    

    尽管看起来像,但这与np.array([5,6]) 不一样:

    In [152]: objs * 3
    ----------------------
    TypeError: unsupported operand type(s) for *: 'instance' and 'int'
    

    你可以看到覆盖__repr__的缺点。

    更简单的方法是使用您当前的printnum() 方法,但在循环中调用它:

    In [164]: class player:
       .....:     def __init__(self, num=5):
       .....:         self.num = num
       .....:     def printnum(self):
       .....:         print(self.num)
       .....:         
    
    In [165]: for p in objs:
       .....:     p.printnum()
       .....:
    5
    6
    

    或者,也许定义你的方法来返回一个字符串而不是打印一个,然后进行列表理解:

    In [169]: class player:
       .....:     def __init__(self, num=5):
       .....:         self.num = num
       .....:     def printnum(self):
       .....:         return str(self.num)
       .....: 
    
    In [170]: objs = np.array([player(5), player(6)])
    
    In [171]: [p.printnum() for p in objs]
    Out[171]: ['5', '6']
    

    【讨论】:

    • 我明白了。我尽力避免使用 for 循环。谢谢,这回答了我的问题。
    • 仅供参考,@user2243024 通过数组广播的“元素方式”函数类型(我使用+ 作为示例)称为ufuncs
    【解决方案2】:

    您的代码中有几个拼写错误:printnum() 需要 self arg 和 Object->object

    class player:
        def __init__(self, num=5):
            self.num = num
    
        def printnum(self):
            print(self.num)
    
    
    objs = np.array([player(5),player(6)], dtype=object)
    
    # It's not a "broadcast" (what you mean is map), but it has the same result
    # plus it's pythonic (explicit + readable)
    for o in objs:
        o.printnum()
    

    看起来你真正想做的是创建一个生成器对象。谷歌python generator yield,你会得到一些像this这样的例子

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多