2013-09-03 3 views

ответ

28

Это экземпляр класса (он же объект):

In [2]: numpy.r_ 
Out[2]: <numpy.lib.index_tricks.RClass at 0x1923710> 

Класс представляет собой конструкцию, которая используется для определения отчетливой типа - в таком класс позволяет экземпляров самой себя. Каждый экземпляр может иметь свойства (переменные и методы члена/экземпляра).

Один из методов, которым может обладать класс, это метод __getitem__, который вызывается всякий раз, когда вы добавляете [something,something...something] к имени экземпляра. В случае экземпляра numpy.r_ метод возвращает массив numpy.

Возьмем следующий класс, например:

class myClass(object) 
    def __getitem__(self,i) 
    return i*2 

Посмотрите на эти выходы для указанного класса:

In [1]: a = myClass() 

In [2]: a[3] 
Out[2]: 6 

In [3]: a[3,4] 
Out[3]: (3, 4, 3, 4) 

Я звоню __getitem__ метод MyClass (через [] скобках) и __getitem__ метод возвращается (содержимое списка * 2 в этом случае) - это не класс/экземпляр ведет себя как функция - это функция __getitem__ e myClass экземпляр, который вызывается.

На заключительной ноте, вы заметите, что экземпляр myClass я должен был сделать a = myClass() тогда, чтобы получить экземпляр RClass вы используете numpy.r_ Это потому, что NumPy конкретизирует RClass и связывает его с именем numpy.r_ себе. This is the relevant line in the numpy source code. По-моему, это довольно уродливо и сбивает с толку!

+4

Это на самом деле экземпляр «RClass», а не сам класс. –

+1

@RobertKern. Вы, конечно, правы, я внесла поправки в свой ответ, чтобы отразить это. –

+0

Можете ли вы объяснить окружающим, что же такое разница между экземпляром класса и самим классом? – usethedeathstar

31

Я бы сказал, что для всех целей r_есть функция, но одна реализована умным взломом с использованием другого синтаксиса. Майк уже объяснил, как r_ на самом деле не является функцией, но экземпляр класса RClass, который имеет __getitem__, так что вы можете использовать его как r_[1]. Косметическая разница заключается в том, что вы используете квадратные скобки вместо изогнутых, поэтому вы не выполняете вызов функции, но вы фактически индексируете объект. Хотя это технически верно, для всех целей он работает точно так же, как вызов функции, но тот, который позволяет некоторым дополнительным синтаксисам не допускаться нормальной функцией.

Мотивация для создания r_, вероятно, исходит из синтаксиса Matlab, который позволяет строить массивы очень компактным образом, например x = [1:10, 15, 20:10:100]. Чтобы достичь того же значения в numpy, вам нужно будет сделать x = np.hstack((np.arange(1,11), 15, np.arange(20,110,10))). Использование двоеточий для создания диапазонов не допускается в python, но они существуют в виде нотации среза для индексации в список, например L[3:5] и даже A[2:10, 20:30] для многомерных массивов.Под капотом, это индекс обозначение преобразуется в вызов к __getitem__ методу объекта, где запись двоеточия преобразуется в срезе объект:

In [13]: class C(object): 
    ...:  def __getitem__(self, x): 
    ...:   print x 

In [14]: c = C() 

In [15]: c[1:11, 15, 20:110:10] 
(slice(1, 11, None), 15, slice(20, 110, 10)) 

The r_ объекта «злоупотребление» этот факт, чтобы создать " функция ", которая принимает нотацию фрагмента, которая также выполняет некоторые дополнительные вещи, такие как объединение всех вместе и возвращение результата, так что вы можете написать x = np.r_[1:11, 15, 20:110:10]. «Не функция, поэтому не принимает никаких параметров» в документации немного вводит в заблуждение ...

+1

В некотором смысле это сводится к методу '__getitem__' и методу' __call__'. 'np.array',' np.r_' и '[]' имеют первое, функция имеет более позднюю. На самом деле любой объект может быть вызван, если он имеет '__call__'. – hpaulj

+0

Отличная перспектива! –