Numpy: ndarray должен быть производным от collections.abc.Sequence?

Созданный на 1 дек. 2012  ·  49Комментарии  ·  Источник: numpy/numpy

@juliantaylor поднял этот вопрос в вопросе о

Пример из билета:

import numpy as np
import random
random.sample(np.array([1,2,3]),1)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user1/py33/lib/python3.3/random.py", line 298, in sample
    raise TypeError("Population must be a sequence or set.  For dicts, use list(d).")
TypeError: Population must be a sequence or set.  For dicts, use list(d).

Это происходит в 3.3 с 1.7.0rc1.dev-3a52aa0 и в 3.2 с 1.6.2.
2.7, конечно, это не касается.

Соответствующий код из cpython / Lib / random.py: 297

from collections.abc import Set as _Set, Sequence as _Sequence
def sample(self, population, k):
# ...
    if not isinstance(population, _Sequence):
        raise TypeError("Population must be a sequence or set.  For dicts, use list(d).")

Я не смог найти другое место в stdlib с помощью аналогичного теста, но lib2to3
показал предполагаемую эквивалентность:

lib2to3/fixes/fix_operator.py
5:operator.isSequenceType(obj)   -> isinstance(obj, collections.Sequence)

в 2.7

In [6]: operator.isSequenceType(np.array([1]))
Out[6]: True

а в 3.3 / 3.2

>>> isinstance(np.array([1]), collections.Sequence)
False

Самый полезный комментарий

Да, просто добавьте куда-нибудь Sequence.register(np.ndarray) .

Все 49 Комментарий

Python 3.x просто выполняет более строгую проверку в random.sample чем Python 2.x. В 2.x numpy также не является подклассом Sequence (ndarray не имеет методов index , count или __reversed__ ). Поэтому я думаю, вы можете расценить это либо как неправильное использование random.sample либо как нарушение обратной совместимости Python 3.x.

Достаточно справедливо, но, тем не менее, мы могли бы легко _make_ ndarray последовательность,
поскольку все эти методы имеют смысл и их легко
воплощать в жизнь. Фактически было бы достаточно просто унаследовать от него, поскольку Sequence
предоставляет все недостающие методы в виде примесей.
2 декабря 2012 г. в 13:30 «Ральф Гоммерс» [email protected] написал:

Python 3.x просто выполняет более строгую проверку в random.sample, чем
Python 2.x. В 2.x numpy также не является подклассом Sequence (ndarray не имеет
index, count или обратные методы). Я думаю, вы можете рассматривать это как
либо неправильное использование random.sample, либо нарушение обратной совместимости
Python 3.x.

-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/numpy/numpy/issues/2776#issuecomment -10929601.

Я бы сказал то же самое, если бы не пример 2to3, который делает это более тонким.
index и count не нужны, я считаю: Link ,
Все абстрактные методы для Sequence уже реализованы, остальные имеют реализации по умолчанию.

Проблема в том, что MutableSequence на самом деле более корректно, а insert не реализуется.

не забывайте массивы 0-d, я не уверен, что с ними происходит прямо сейчас, но они на самом деле не Последовательность, не так ли?

Хм, Sequence предназначен для неизменяемых объектов, некоторые методы MutableSequence (extend, pop) не имеют смысла. Так что да, мы могли бы добавить эти 3 метода, но это не совсем правильно.

Мне кажется, что для random.sample действительно нет причин требовать экземпляр Sequence .

__setitem__ реализовано, но не __delitem__ , так что, может быть, SomewhatMutableSequence ?

Имеет смысл интерпретировать интерфейс как «последовательность должна иметь все это, но некоторые могут
имеют ужасный O () ", поэтому они предлагают наивные реализации некоторых методов.
Разумеется, семантика insert , pop неясна в контексте ndarray.
Однако я не уверен, что правильно с итерацией по массиву 0-d.
Можно возразить, что предложение метода __iter__ который просто вызывает TypeError а не
StopIteration в любом случае является нарушением утиного набора текста.

edit : Хотя я уверен, что это не было неосторожным решением.

ndarray может быть просто последовательностью, это не значит, что она должна быть неизменной.

Кстати. реализация списка CPython также не поддерживает эффективную вставку, выталкивание и расширение, но это все еще MutableSequence

ndarray не может поддерживать вставку / поп / расширение на месте (ndarray имеют фиксированный размер), поэтому, хотя это изменяемая последовательность, это просто не Python MutableSequence (и никогда не будет). Однако он может и должен поддерживать интерфейс Sequence .

Было бы неплохо, если бы random.sample не проверял это, но при более внимательном рассмотрении у этого есть веская причина - он имеет несколько различных реализаций для разных типов входных аргументов, поэтому ему нужен какой-то способ различать их. Нельзя просто начать индексацию и надеяться на лучшее. Возможно, мы могли бы зарегистрировать ошибку и попытаться убедить их вернуться к реализации последовательности по умолчанию для нераспознанных типов, но самый ранний, который может помочь, - это 3.4 ...

Однако замечание о массивах 0-d - это хорошо; Массивы 0-d не поддерживают интерфейс Sequence (они даже не Iterable ). Но для Python не так уж и страшно, если они лгут о том, что они Sequence s, а затем ждут, пока фактический доступ вызовет ошибку - утиный ввод означает, что вы всегда можете потерпеть неудачу, если хотите :-). Вероятно, можно каким-то образом сделать isinstance(a, Sequence) успешным для многомерных массивов и неудачным для массивов 0-d; если мы сможем это сделать, тогда круто. Но даже если мы не можем, лучше всего, вероятно, превратить ndarray в Sequence s.

Обратите внимание, что в MaskedArray уже есть метод count , поэтому добавление его в ndarray, который делает что-то другое, сломает его.

О массивах 0-D лучше думать как о скалярах с несколькими удобными методами (по крайней мере, я так о них думаю); помимо того, что они не являются повторяемыми, они также не индексируются, что еще более странно, если вы думаете о них как о массивах. Таким образом, сделать массивы 0-D несовместимыми по-другому - это не большая проблема, imho.

@njsmith где вы видите несколько реализаций? После проверки isinstance (Sequence) я вижу только len(population) а затем преобразование в список. http://hg.python.org/cpython/file/22d891a2d533/Lib/random.py

Типы Pandas Series и DataFrame также имеют несовместимые методы подсчета и атрибут индекса.

@rgommers : Хм, вы правы, меня ввело в заблуждение сообщение об ошибке, и я подумал, что оно также принимает целые числа в качестве сокращения для range() , а это не так. Тем не менее, они хотят определить различное поведение для наборов, последовательностей и отображений. Может быть, мы сможем убедить их, что они должны переключить его на

if isinstance(population, _Set):
    population = tuple(population)
if isinstance(population, _Mapping):
    raise Blarrrgh()
# Otherwise assume that we have a sequence and hope

Это также хороший момент в отношении существующих подклассов ndarray. Не похоже, что есть способ сказать, что ndarray - это Sequence но его подклассы не являются :-(. Итак, какой вариант наименее плох, учитывая, что некоторые из этих подклассов не могут удовлетворить Sequence интерфейс без нарушения совместимости?

  • Устарели несовместимые использования в подклассах ndarray и в конечном итоге удалите их и замените на Sequence -совместимые версии. Это кажется выполнимым для методов count , но изменение имени Series.index будет чрезвычайно разрушительным для людей pandas. (DataFrame не является подклассом ndarray, поэтому технически это не актуально, за исключением того, что, я полагаю, Series и DataFrame должны быть синхронизированы.) Я думаю, мы можем спросить @wesm, что он думает, но ...
  • Идите вперед и объявите ndarray и его подклассы, чтобы удовлетворить определению Sequence , и примите, что для некоторых подклассов ndarray это будет ложью. Однако только в редко используемых частях интерфейса Sequence , а типы Python все равно обычно лежат ...
  • Перегруппируйте нашу иерархию наследования, чтобы отделить функциональность и бессмыслицу абстрактного базового класса. Делать
class multidim_ndarray(ndarray, Sequence):
  pass

и вместо этого сделайте экземпляры этого класса multi-dim array. Подклассы не затрагиваются, потому что они продолжают наследовать от ndarray , а не multidim_ndarray . Конечно, один объект ndarray может переходить между 0-d и многомерным через .resize() ...

  • Примите тот факт, что ndarray никогда не будет Sequence .

[ isSequenceType немного отвлекает. Это старая функция, которая предшествовала существованию абстрактных базовых классов (которые были добавлены в 2.6) и даже не пытается определить подробный интерфейс, необходимый для последовательностей - она ​​просто проверяет, что ваш тип (1) определяет __getitem__ , (2) не является встроенным dict . Очевидно, что это даст неправильный ответ во многих ситуациях (например, все, что действует как диктовка, но не является таковой!). Так что, если кому-то действительно нужен тип последовательности, то isinstance(obj, Sequence) будет работать лучше, а 2to3 поступит правильно. Но это создает проблему для numpy ...]

Возможно, удастся убедить разработчиков Python создать новый класс, например SequenceBase который даже ниже Sequence и не гарантирует .index или .count , а только .__len__ и __getitem__ или что-то подобное? Все хорошо, что в Sequence есть что-то вроде index , но кажется немного странным навязывать его таким вещам, как numpy по-видимому, делая это так, как последовательность вроде вещей должна быть утилизирована. Знают ли разработчики Python о том, что это несколько проблематично?

Мне нравится предложение @seberg; если разработчики Python не согласны, я бы выбрал второй пункт @njsmith. Отсутствует возможность просто сказать, что ndarrays не удовлетворяет интерфейсу Sequence. Не оптимально, но лучше, чем пули 1 и 3 имхо.

[Упс, «отсутствующий вариант» был там как вариант 4, просто каким-то образом парсер уценки решил вставить его в предыдущий пункт запутанным и нечитаемым способом. Я отредактировал комментарий, чтобы исправить форматирование.]

Половина типов, зарегистрированных с помощью Sequence , т.е. buffer и xrange , также не имеют этих методов. Мне не ясно, что это обязательные методы интерфейса, а также удобные методы для тех, кто использует collections.Sequence как базовый класс / миксин.

@rkern : Хороший улов. Так что, возможно, решение - просто добавить куда-нибудь вызов Sequence.register(np.ndarray) . (Это также было бы обходным путем для исходного репортера.)

В какой-то момент нам, вероятно, следует реализовать __reversed__ ...

@rkern, вы правы, это упомянуто как открытая проблема в PEP: http://www.python.org/dev/peps/pep-3119/#sequences. Странно, что у PEP со статусом Final могут даже быть нерешенные вопросы.

Я думаю, что название этой ошибки немного вводит в заблуждение, поскольку ошибка существует не только в python3. Конечно, random.sample(numpy_array) работает в python2, но isinstance(np.array([1]), collections.Sequence) должен возвращать True в любом python> = 2.6.

Я только что столкнулся с этой ошибкой в ​​Python 2.7, используя модуль autopep8. По умолчанию он преобразовал некоторые вызовы operator.isSequenceType () в isinstance (x, collections.Sequence). Тест станет False, когда я передам numpy.ndarray. Это может быть очень подлый баг.

Просто столкнулся с этим с Python 2.7, используя модуль python-Pillow. Image.point (lut, mode) вызывает isinstance (lut, collections.Sequence), в предыдущей версии использовался operator.isSequenceType ()

Теперь, возможно, самое подходящее время вернуться к этому, поскольку числовые числовые скалярные типы были зарегистрированы (# 4547),

Так что, возможно, решение состоит в том, чтобы просто добавить где-нибудь вызов Sequence.register (np.ndarray).

Ага, это хороший компромисс.

Да, просто добавьте куда-нибудь Sequence.register(np.ndarray) .

@mitar есть интерес к подаче PR?

Конечно. Куда это должно идти? В том же файле, где создан np.ndarray ?

Просто чтобы убедиться, что мы действительно думаем, что это хорошая идея: мы просто сейчас добавляем устаревание для пустого массива, равного False (# 9718), то есть мы удаляем одну из вещей, которая работает для последовательностей) . Читая комментарии, я думаю, что уже пришел к выводу, что скаляры массива не будут работать, поэтому я предполагаю, что пустой массив может быть частью этого нарушенного обещания ...

Для дальнейшего использования, правильное место для этого, вероятно, будет в numpy.core.multiarray :
https://github.com/numpy/numpy/blob/4f1541e1cb68beb3049a21cbdec6e3d30c2afbbb/numpy/core/multiarray.py

Хорошо, я хочу это. Как? Вот как бы я реализовал их как методы:

def __reversed__(self):
    return iter(self[::-1])

def index(self, value) -> int:
    return np.in1d(self, value).nonzero()[0]

def count(self, value) -> int:
    return (self == value).sum()

# Necessary due to lack of __subclasshook__
collections.abc.register(np.ndarray)

Мы обнаружили, что в последней версии Tensorflow (2.0) наличие Sequence.register(np.ndarray) приводит к неправильной работе Tensorflow. Кажется, он где-то проверяет, является ли значение последовательностью, а затем использует иначе, чем если бы это ndarray.

См .: https://gitlab.com/datadrivendiscovery/d3m/issues/426

Весело. Я почти уверен, что лучше проверить, является ли что-то массивом, потому что это почти всегда будет специально обработанным случаем.

Вероятно, порядок проверки типов неправильный, сначала нужно проверить ndarray, а затем последовательность. Но если вы сначала проверите последовательность, то теперь этот блок кода выполняется.

@mitar Мы рассматриваем возможность закрытия, потому что __contains__ / operator.in ведет себя по-другому (рекурсивно, а не для последовательностей), поэтому он нарушает контракт API. У вас есть вариант использования для этого?

Не могли бы вы подробнее рассказать о контракте API, который вы здесь имеете в виду. Я не совсем понимаю.

Пример использования - это написание общего кода, который знает, как преобразовывать между вещами, например, если вы можете перебирать последовательность и возвращать размерность путем разделения, а затем рекурсивно. Затем я могу преобразовать список списков так же, как 2d ndarray, но его можно обобщить на несколько измерений и так далее. И мне не нужно проверять больше, чем просто последовательность.

Как уже упоминалось, существует несколько проблем с просмотром массивов как вложенных последовательностей Python. __contains__ - наиболее очевидный вариант, во-вторых, массивы 0-D определенно не являются вложенными последовательностями. Также существуют тонкости, такие как измерение длины 0, и обычно arr[0] = 0 не означает, что arr[0] == 0 , поскольку arr[0] может быть самим произвольным массивом (который лучше было бы записать как arr[0, ...] . Лично я считаю, что интерпретация "вложенной последовательности" хороша, но менее полезна, чем мы думаем (т.е. я редко повторяю массив как for col in array и даже если я это делаю, я был бы не против написать for col in array.iter(axis=0)

Поэтому я склонен рассматривать «массив как последовательность» как слегка проблематичную аналогию (я признаю, что это не означает, что она не может быть полезной).
Однако, каким бы ни был вариант использования, мне любопытно, не лучше ли было бы изучить новый ABC, такой как новый «ElementwiseContainer». Тот, который также сообщает пользователю, что + и == и т. Д. Будут работать с каждым элементом , и что, в отличие от последовательностей Python, они не должны ожидать, что + объединит ( да + не является частью последовательности ABC, но кажется естественным в Python).

Просто проходя мимо -
На прошлой неделе я написал Python-ideas, потому что заметил, что Python collections.abc.Sequence не реализует __eq__ и другие сравнения, хотя у него есть все другие методы для их реализации, чтобы Sequence вел себя как списки и кортежи. (эта переписка привела меня к этой проблеме).

Я предлагал добавить туда __eq__ , но это, очевидно, приведет к тому, что эти последовательности будут отличаться от поведения Numpy.array.

А как насчет большей формализации в Python того, что такое «Последовательности», а затем делегирования этих вещей, которые разошлись бы как особые случаи, до точки добавления туда collections.abc.ComparableSequence ? (и поскольку выше было упомянуто + для канкатенации, возможно, какое-то другое имя будет означать «последовательности, которые в результате сравнения дают одно логическое значение и ведут себя как скаляры для конкатенации и умножения на скаляр» - то есть - поведение Python для + и * в списке и кортежах). Следовательно, спецификации Sequence могут быть формализованы таким образом, чтобы хотя бы одномерные массивы numpy точно соответствовали бы им.

Эта формализация того, что представляет собой последовательность Python, также может помочь с другими расхождениями, такими как упомянутое в https://github.com/numpy/numpy/issues/2776#issuecomment -330865166 выше.

Я не чувствую себя достаточно мотивированным, чтобы идти по этому пути в одиночку - но если это имеет смысл, я с радостью помогу написать PEP и помочь его протолкнуть. (Я просто хотел проверить, почему последовательность не создала __eq__ , и, возможно, иметь PR для этого, когда я поднял это)

@jsbueno, моя проблема в том, что я действительно не понимаю, какое дополнительное или промежуточное определение действительно было бы полезно для пользователей ndarray . Лучшее, что я могу придумать, - это Collection котором есть count() и index() , но полезно ли это? Все остальное было бы азбукой для вещей, о которых сам Python не имеет почти никакого представления.

Я думаю, что SymPy на самом деле понял это лучше. Он перебирает все элементы своих матриц, что, по крайней мере, делает его Collection .
Я сомневаюсь, что мы можем что-то с этим поделать, и я даже не уверен, что итерация всех элементов в SymPy очень полезна (и интуитивно понятна), но, по крайней мере, итерация всех элементов согласуется с __contains__ . Обратите внимание, что это также означает, что len(Matrix) - это количество элементов, а _not_ Matrix.shape[0] !

С риском повторения большого количества сверху, помимо одномерных массивов, что такое массивы numpy ?:

  • Container : элементов: heavy_check_mark:
  • Sized + Iterable подмассивов (если не 1-D): вопрос:
  • Reversible : мы могли бы просто реализовать это, не беспокойтесь об этом. :вопрос:
  • count() и index() : могут быть реализованы для элементов (: heavy_check_mark :)
  • Sequence : Несоответствие между итерируемым подмассивом и контейнером элемента : x:

Так что даже некоторые из самых фундаментальных свойств противоречат друг другу. NumPy может быть Container который знает, как делать .index() и .count() , то есть Sequence но без части Iterable . Хотя это независимо Iterable , но из подмассивов .
И если это кажется запутанным беспорядком, то я согласен, но я думаю, что это сделано намеренно. Единственное верное решение - либо пойти по пути SymPy, либо просто не быть Iterable для начала. (мы не можем пойти по пути SymPy, и я сомневаюсь, что отказ от __iter__ имеет шанс.)

Лично я ожидаю, что, если отбросить одномерные массивы, подобные массивы - это просто очень разные звери по сравнению с коллекциями Python. При рассмотрении итерационного поведения вам понадобится MultidimensionalCollection чтобы специально сигнализировать о несоответствии между __contains__ и __iter__ (но полезно ли это?).

Если посмотреть за пределы того, что в настоящее время определено Sequence , я повторю, что я думаю, что ElementwiseCollection (операторы являются поэлементными операторами, а не операторами контейнера, например, + ) являются наиболее подходящими. определение характеристик массивов numpy и всех подобных массивов в целом (см. Программирование массивов). Однако это также концепция, полностью чуждая самому Python, а иногда и противоречащая ему.

Единственное, что можно сделать, это пометить одномерные массивы и только одномерные массивы как последовательности, поскольку они не имеют несоответствия подмассиву и элементу. В этот момент да, __eq__ конечно, не определен для них, а __nonzero__ не определяется аналогично типичным последовательностям Python.

Спасибо за ответ, и я еще раз прошу прощения за то, что запрыгнул в 8-летний фургон здесь. С вашим комментарием, через пару часов после последней переписки по электронной почте и беседой с другим другом в середине, я согласен, что большинство из этих вещей лучше оставить как есть. Когда-нибудь в будущем Python может выбрать более формальное определение Sequence, чем «все, что collection.abc.Sequence реализует сейчас».

Я просто добавлю, после прочтения ваших комментариев выше, что я думаю, что характеристикам, которые вы указали как «то, что делает последовательность Python», не хватает самой важной функции, которая делает ndarrays для меня похожими на последовательности, такие как списки и кортежи: наличие непрерывного индекса - пространство, которое может адресовать все отдельные элементы. Но я не думаю, что формализация abc для этого будет иметь какую-либо практическую ценность ни в кодировании, ни в хинтинге статического типа.

@seberg Это отличный синопсис.

Эта проблема, похоже, связана с использованием ndarray в контекстах, которые ожидают Sequence или Iterable или Container . Простым подходом было бы наличие членов в ndarray которые предоставляют дешевые представления, которые обещают и предоставляют соответствующий интерфейс и отвечают на проверки isinstance . Например:

class ndarray(Generic[T]):
    def as_container(self) -> Container[T]:
        if self.ndim == 0:
            raise ValueError
        return ContainerView(self)  # correctly answers __len__, __iter__ etc.
    def as_subarray_iterable(self) -> Iterable[np.ndarray[T]]:
        if self.ndim <= 1:
            raise ValueError
        return SubarrayIterableView(self)
    def as_scalar_sequence(self) -> Sequence[T]:
        if self.ndim != 1:
            raise ValueError
        return ScalarView(self)
    def as_subarray_sequence(self) -> Sequence[np.ndarray[T]]:
        if self.ndim <= 1:
            raise ValueError
        return SubarraySequenceView(self)  # this view has to reinterpret __contains__ to do the expected thing.

Вместо обещания ndarray быть всем для всех, пользователь спрашивает, что ему нужно, и если ndarray может предоставить это, он делает это самым дешевым способом. Если не может, возникает исключение. Это упрощает код пользователя, перемещая проверку ndim должен выполнять пользователь (особенно при использовании аннотаций типов), в ndarray .

Должна ли последняя аннотация быть Sequence а не Iterable ?

@ eric-wieser Ага! Благодарю. Что ты думаешь?

Ну, as_subarray_sequence практически list(arr) :)

@ eric-wieser Да, я думал, что будет дешевле предоставить обзор, но я понятия не имею.

Ну, list(arr) просто производит len(arr) просмотров, которые вы все равно получите, если бы я повторил.

Я по-прежнему думаю, что мы слишком много внимания уделяем тому, что можно сделать, и не уделяем достаточно внимания проблемам в настоящее время. В частности, все приведенные выше методы очень легко реализовать, если вы знаете, что у вас есть ndarray-подобный (я не согласен с тем, что массивы 0-D не являются контейнерами). Таким образом, они были бы полезны, только если бы для них был стандартизированный ABC, и в этом случае было бы также достаточно определить, что базовая индексация совместима с numpy и, возможно, включает свойство .flat .

Исходная проблема ( random.sample перестала работать) кажется неактуальной из-за прошедшего времени. Да, это слегка раздражает, но, возможно, это даже к лучшему, поскольку пользователь может ожидать выбора подмассивов или элементов.

Я уверен , что мы разорвать некоторые утки набрав код. Некоторые проблемы, вероятно, возникают с сериализацией (у меня нет под рукой примеров). И многие из таких кодов не будут иметь проблем с использованием isinstance проверок на ABC s, но ненавидят проверять конкретно np.ndarray . Я не вижу, как добавление методов в ndarray могло бы помочь в этом, нам понадобится новый ABC , вероятно, с немногим большим, чем свойство .ndim и, возможно, сохраняющим итерацию стиля вложенной последовательности.

Такие методы, как вышеупомянутые, могут быть разумными в качестве потребительского протокола для работы с любыми массивами, но это проблема, которую мы пытаемся решить :)? Они не похожи на вещи, которые хотели бы раскрыть типичные последовательности Python.

@ eric-wieser

Вы, конечно, правы, но вы не можете перебирать всю последовательность. Вы можете выделить только несколько элементов.

@seberg

Я все еще думаю, что мы слишком много внимания уделяем тому, что можно сделать, и недостаточно - о проблемах в настоящее время.

Я согласен. Какие проблемы вы придумываете? Я предполагаю, что когда появится numpy 1.10 с типами, я иногда захочу использовать одномерный массив numpy в качестве последовательности. Если я хочу сделать это сейчас, мне нужно:

  • убедитесь, что он одномерный, и
  • вызовите cast чтобы сообщить mypy, что это на самом деле последовательность.

Вот почему я хочу предоставить метод, позволяющий это делать автоматически. Я тоже ненавижу большие интерфейсы, но мне кажется, что такие методы или простые функции будут становиться все более и более распространенными по мере того, как аннотации типов становятся популярными. Что вы думаете?

(Я не согласен с тем, что массивы 0-D не являются контейнерами).

Понятия не имею, но в настоящее время вы делаете рейз на __len__ , поэтому кажется, что они не работают как контейнеры. Я думаю, что mypy было бы полезно сообщить об ошибке, если вы передадите массив 0-D функции, которая принимает контейнер. Его не поймают, если вы сделаете контейнеры массивов 0-D.

нам понадобится новый ABC, вероятно, с немногим большим, чем свойство .ndim и, возможно, закрепляющим итерацию в стиле вложенной последовательности.

Я не хотел добавлять это в свое предложение, но я думаю, что вы все равно туда и направитесь. Я заядлый пользователь прекрасно продуманной библиотеки JAX. Я предполагаю, что в будущем numpy.ndarray и jax.numpy.ndarray (у которого есть подклассы) будут наследовать от некоторого абстрактного NDArray некоторого вида. У вас может быть намного больше, чем ndim . В идеале это должно быть не менее NDArray(Generic[T]) , и, возможно, событие тоже имеет форму или количество измерений. Он может иметь __eq__ возвращающий NDArray[np.bool_] . Вы, наверное, знаете лучше меня :)

Несколько лет назад я искал эту проблему, чтобы предположить, что numpy.array должен унаследовать от collections.Sequence , но теперь я считаю аргументы (особенно ваши !!) в этой теме очень убедительными. Массивы Numpy на самом деле не являются последовательностями, и кажется, что их использование принесет больше вреда, чем пользы. Почему бы просто не позволить им быть их собственными делами и не заставить пользователей явно запрашивать нужный им интерфейс?

И у многих из таких кодов не возникнет проблем с использованием проверок isinstance на ABC,

Теперь, когда вы упомянули об этом, возможно, все предложенные мной методы должны были возвращать представления. Таким образом, они могут правильно отвечать на проверки экземпляра.

Такие методы, как вышеупомянутые, могут быть разумными в качестве потребительского протокола для работы с любыми массивами, но это проблема, которую мы пытаемся решить :)? Они не похожи на вещи, которые хотели бы раскрыть типичные последовательности Python.

Я определенно согласен с тем, что ответ на это зависит от проблем, которые мы пытаемся решить. Выпив помощь kool с аннотациями типов, я заинтересован в написании краткого numpy-кода, который передает mypy без засорения кода с помощью # type: ignore . Какие проблемы вы имеете в виду?

Что ж, подсказки типа и взаимодействие с другими объектами, подобными массивам, вероятно, являются хорошей мотивацией. Я мог бы предложить открыть новый выпуск или тему в списке рассылки. Прямо сейчас я не уверен, о чем лучше думать здесь, набор текста формируется, так что, возможно, это в конечном итоге прояснит некоторые вещи.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги