В соответствии с numpy/scipy doc на numpy.r_ здесь, это "не функция, поэтому не принимает параметров".
Если это не функция, то каков правильный термин для "функций", таких как numpy.r_?
В соответствии с numpy/scipy doc на numpy.r_ здесь, это "не функция, поэтому не принимает параметров".
Если это не функция, то каков правильный термин для "функций", таких как numpy.r_?
Это экземпляр класса (он же объект):
In [2]: numpy.r_
Out[2]: <numpy.lib.index_tricks.RClass at 0x1923710>
Класс - это конструкция, которая используется для определения отдельного типа - так как такой класс допускает экземпляры самого себя. Каждый экземпляр может иметь свойства (переменные-члены/экземпляры и методы).
Одним из методов, которые может иметь класс, является метод __getitem__, он вызывается всякий раз, когда вы добавляете [something,something...something] к имени экземпляра. В случае экземпляра numpy.r_ метод возвращает пустой массив.
Возьмите следующий класс, например:
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__ экземпляра myClass, которая вызывается.
В заключение отметим, что для создания экземпляра myClass мне пришлось сделать a = myClass(), тогда как для получения экземпляра RClass вы используете numpy.r_. Это потому, что numpy создает экземпляр RClass и связывает его с именем numpy..r_ себя. Это соответствующая строка в простом исходном коде. На мой взгляд, это довольно уродливо и запутанно!
Я бы сказал, что для всех целей 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))
Объект r_ "злоупотребляет" этим фактом, создавая "функцию", которая принимает нотацию срезов, которая также выполняет некоторые дополнительные функции, такие как объединение всего вместе и возврат результата, так что вы можете написать x = np.r_[1:11, 15, 20:110:10]. "Не функция, поэтому не принимает параметров" в документации немного вводит в заблуждение...