2016-02-12 42 views
0

我想了解(并最终使用)使用来自numpy的记录数组的对象数组的实现:Numpy object array在审查代码我显然正在学习关于python的新东西,我似乎无法充分了解以下内容:通过函数的Python对象

在obarray.py文件中的函数用于创建一个新的对象,我很困惑,

  1. 为什么使用功能,
  2. 参数如何玩成功能,
  3. 如何使用此函数与直接使用参数创建类不同(推测使用参数作为属性),并且
  4. 这是什么主要 .Obarray我刚刚调用函数时得到了什么?

对于1和2我有一种预感:参数在某种程度上成为对象“局部作用域”,并且可能类似于对象属性?

下面是从该链接的新对象的代码:

import numpy as np 
def make_obarray(klass, dtype): 
    class Obarray(np.ndarray): 
     def __new__(cls, obj): 
      print "CLS:", cls 
      print "OBJ:", obj 
      A = np.array(obj,dtype=np.object) 
      N = np.empty(shape=A.shape, dtype=dtype) 
      for idx in np.ndindex(A.shape): 
       for name, type in dtype: 
        N[name][idx] = type(getattr(A[idx],name)) 
      return N.view(cls) 
     def __getitem__(self, idx): 
      V = np.ndarray.__getitem__(self,idx) 
      if np.isscalar(V): 
       kwargs = {} 
       for i, (name, type) in enumerate(dtype): 
        kwargs[name] = V[i] 
       return klass(**kwargs) 
      else: 
       return V 
     def __setitem__(self, idx, value): 
      if isinstance(value, klass): 
       value = tuple(getattr(value, name) for name, type in dtype) 
      # FIXME: treat lists of lists and whatnot as arrays 
      return np.ndarray.__setitem__(self, idx, value) 
    return Obarray 

这里是我正在测试它:

class Foo: 
      def __init__(self, a, b): 
       self.a = a 
       self.b = b 
      def __str__(self): 
       return "<Foo a=%s b=%s>" % (self.a, self.b) 
dtype = [("a",np.int), 
       ("b",np.float)] 
FooArray = make_obarray(Foo, dtype) 

A = FooArray([Foo(0,0.1),Foo(1,1.2),Foo(2,2.1),Foo(3,3.3)]) 
  1. 当我打电话FooArray我得到__main__.Obarray - 是什么这个?
  2. 作为参数输入的“klass”和“dtype”发生了什么?
  3. 是如何从线沿线的东西此不同:

块引用

class Obarray(np.ndarray): 
    def __new__(cls,input_array, klass, dtype): 
     obj = np.assarray(input_array).view(cls) 
     obj.klass = klass 
     obj.dtype = dtype 
     A = np.array(obj,dtype=np.object) 
     N = np.empty(shape=A.shape, dtype=dt ype) 
     for idx in np.ndindex(A.shape): 
      for name, type in dtype: 
       N[name][idx] = type(getattr(A[idx],name)) 
     obj.N = N.view(np.ndarray) 
     return obj 
+0

我不确定您的困惑是特定于此'numpy'代码还是更一般的。你知道关闭是如何工作的吗?你有没有曾经使用像'collections.namedtuple'这样的类型工厂? – Blckknght

+0

这是一个更常见的问题,出现在这个代码中,所以我用它作为我的例子。是的,我熟悉namedtuple,然而,namedtuple是不可变的 – Skorpeo

回答

0

make_obarray功能是一个工厂,生产类。它返回的类的方法将是可以访问函数的局部变量的闭包(即参数klassdtype),即使它已经完成运行。

这里有一个更简单的关闭,可以帮助你了解他们的工作:

def make_adder(x): 
    def adder(y): 
     return x + y 
    return adder 

make_adder是一个工厂的功能。它返回一个adder函数,它是一个闭包。即使make_adder已返回,adder仍然可以看到make_adder呼叫的x参数在其中被定义。

这与您显示的numpy代码非常相似。 make_obarray函数返回一个类,而不是一个函数,但否则它几乎是相同的。在Python 2中,该类的合格名称将为some_module.Obarray(或Python 3中的some_module.make_obarray.<locals>.Obarray),其中some_module是其中定义的模块的名称(如果已将其模块作为脚本执行,则为__main__)。返回的类的方法将能够看到传递到make_obarrayklassdtype自变量,就像adder函数在我的更简单的示例中可以看到参数make_adder一样。

至于为什么你找到的代码是这样写的,我不能说。或许代码的作者认为能够使用isinstance不同klassdtypeObarray实例区分开来,将是有益的:

FooArray = make_obarray(Foo, dtype) 
BarArray = make_obarray(Bar, some_other_dtype) 

f = FooArray([Foo(1,2)]) 

print(isinstance(f, FooArray)) # True 
print(isinstance(f, BarArray)) # False 

如果klassdtype只是参数一个类,安:我用这种方法不能说明数组实例之间的区别(尽管您可能会想出一个比较实例属性的等效检查)。