2016-02-12 70 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只是參數一個類,安:我用這種方法不能說明數組實例之間的區別(儘管您可能會想出一個比較實例屬性的等效檢查)。