2011-10-05 72 views
7

Gần đây tôi đã gặp sự cố khi tạo mảng đối tượng Numpy bằng cách sử dụng ví dụ:Mảng đối tượng khó khăn

a = np.array([c], dtype=np.object) 

trong đó c là một thể hiện của một số lớp phức tạp, và trong một số trường hợp NumPy cố gắng truy cập một số phương pháp của lớp đó. Tuy nhiên, làm:

a = np.empty((1,), dtype=np.object) 
a[0] = c 

giải quyết vấn đề. Tôi tò mò về sự khác biệt giữa hai nội bộ này. Tại sao trong trường hợp đầu tiên có thể Numpy thử và truy cập một số thuộc tính hoặc phương pháp của c?

EDIT: Đối với hồ sơ, đây là mã ví dụ đó chứng tỏ vấn đề:

import numpy as np 

class Thing(object): 

    def __getitem__(self, item): 
     print "in getitem" 

    def __len__(self): 
     return 1 

a = np.array([Thing()], dtype='object') 

này in ra getitem hai lần. Về cơ bản, nếu có __len__ có trong lớp, thì đây là thời điểm một người có thể gặp phải hành vi không mong muốn.

+0

Không liên quan, nhưng tại sao 'np.object' và không chỉ' object'? – JBernardo

+0

Hai giá trị này tương đương nhau ('' object == np.object'' trả về '' True'') vì vậy điều này không liên quan đến các vấn đề tôi thấy. – astrofrog

+1

@astrofog Đó là lý do tại sao tôi hỏi và nói rằng nó không liên quan. – JBernardo

Trả lời

9

Trong trường hợp đầu tiên a = np.array([c], dtype=np.object), không biết gì về hình dạng của mảng dự định.

Ví dụ, khi bạn xác định

d = range(10) 
a = np.array([d]) 

Sau đó, bạn mong đợi NumPy để xác định hình dạng dựa vào độ dài của d.

Vì vậy, tương tự như trong trường hợp của bạn, khó khăn sẽ cố gắng để xem nếu len(c) được xác định và nếu có, để truy cập các yếu tố của c qua c[i].

Bạn có thể nhìn thấy hiệu quả bằng cách định nghĩa một lớp như

class X(object): 
    def __len__(self): return 10 
    def __getitem__(self, i): return "x" * i 

Sau đó

print numpy.array([X()], dtype=object) 

sản xuất

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]] 

Ngược lại, trong trường hợp thứ hai của bạn

a = np.empty((1,), dtype=np.object) 
a[0] = c 

Sau đó, hình dạng của a đã được xác định. Do đó, có thể chỉ cần gán trực tiếp đối tượng.

Tuy nhiên, mức độ này chỉ đúng vì a là một vectơ. Nếu nó đã được xác định với một hình dạng khác nhau thì truy cập phương pháp vẫn sẽ xảy ra. Sau đây ví dụ vẫn sẽ gọi ___getitem__ trên một lớp

a = numpy.empty((1, 10), dtype=object) 
a[0] = X() 
print a 

lợi nhuận

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]] 
+0

Đây chính xác là những gì tôi cần - về cơ bản nếu '' __len__'' được xác định thì đó là khi tôi gặp vấn đề! – astrofrog

Các vấn đề liên quan