Numpy: يجب أن يُشتق ndarray من المجموعات. abc.Sequence؟

تم إنشاؤها على ١ ديسمبر ٢٠١٢  ·  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 ليس أيضًا فئة فرعية من التسلسل (لا يحتوي ndarray على أساليب index أو count أو __reversed__ ). لذلك أعتقد أنه يمكنك اعتبار هذا إما سوء استخدام random.sample أو كسر توافق مع الإصدارات السابقة بواسطة Python 3.x.

عادل بما فيه الكفاية ، ولكن بعد قولي هذا ، يمكننا بسهولة _جعل_ ndarray تسلسلًا ،
نظرًا لأن كل هذه الأساليب منطقية وستكون مباشرة
تنفيذ. في الواقع مجرد الوراثة منه سيكون كافياً ، منذ Sequence
يوفر جميع الطرق المفقودة مثل mixins.
في 2 ديسمبر 2012 13:30 ، كتب "Ralf Gommers" [email protected] :

يقوم Python 3.x ببساطة بإجراء فحص أكثر صرامة في random.sample من
بايثون 2.x. في 2.x numpy ، لا يعد numpy فئة فرعية من التسلسل (لا يحتوي ndarray على
الفهرس أو العد أو الطرق المعكوسة ). لذلك أعتقد أنه يمكنك اعتبار هذا على أنه
إما إساءة استخدام العشوائية أو انقطاع التوافق مع الإصدارات السابقة
بايثون 3.x.

-
يمكنك الرد على هذه الرسالة الإلكترونية مباشرةً أو عرضها على Gi tHubhttps: //github.com/numpy/numpy/issues/2776#issuecomment -10929601.

كنت سأقول نفس الشيء ، لولا المثال 2to3 الذي يجعل هذا أكثر دقة.
ليس هناك حاجة إلى الفهرس والعد: الرابط ،
تم تنفيذ جميع الأساليب المجردة لـ Sequence بالفعل ، أما الطرق الأخرى فلها تطبيقات افتراضية.

المشكلة هي أن MutableSequence هو الأكثر صحة في الواقع ، و insert لم يتم تنفيذه.

لا تنسى المصفوفات 0-d رغم ذلك ، لست متأكدًا مما يحدث معهم الآن ، لكنهم ليسوا تسلسلًا حقًا ، أليس كذلك؟

حسنًا ، Sequence مخصص للكائنات غير القابلة للتغيير ، بعض أساليب MutableSequence (extension ، pop) لا معنى لها. لذا نعم ، يمكننا إضافة هذه الطرق الثلاثة ، لكن لا يبدو الأمر على ما يرام.

يبدو لي أنه لا يوجد سبب حقيقي لطلب random.sample Sequence مثيل

__setitem__ ، لكن ليس __delitem__ ، لذلك ربما SomewhatMutableSequence ؟

من المنطقي أن تفسر الواجهة على أنها "يجب أن يحتوي التسلسل على كل هذه الأشياء ، لكن البعض الآخر قد يكون كذلك
لديك O () رهيبة "، وهذا هو السبب في أنها تقدم تطبيقات ساذجة لبعض الأساليب.
بالتأكيد ليست دلالات insert ، pop غير واضحة في سياق ndarray.
لست متأكدًا من الشيء الصحيح فيما يتعلق بالتكرار على مصفوفة 0-d.
يمكن للمرء أن يجادل بأن تقديم طريقة __iter__ يؤدي إلى زيادة TypeError بدلاً من ذلك
StopIteration انتهاكًا لكتابة البط على أي حال.

تحرير : على الرغم من أنني متأكد من أن هذا لم يكن قرارًا مهملاً.

يمكن أن يكون ndarray مجرد تسلسل ، وهذا لا يعني أنه يجب أن يكون غير قابل للتغيير.

بالمناسبة. لا يدعم تطبيق قائمة CPython أيضًا الإدراج الفعال والبوب ​​والتمديد أيضًا ولكنه لا يزال متسلسلًا متغيرًا

لا يمكن لـ ndarray دعم الإدخال الموضعي / pop / extension (ndarray's لها حجم ثابت) ، لذلك في حين أنه تسلسل قابل للتغيير ، فهو ببساطة ليس 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 (التسلسل) أرى فقط len(population) ثم التحويل إلى قائمة. http://hg.python.org/cpython/file/22d891a2d533/Lib/random.py

تحتوي أنواع سلسلة Pandas و 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 سيكون مزعجًا بشكل كبير لأفراد الباندا. (لا يعد DataFrame فئة فرعية من ndarray ، لذا فهو غير ذي صلة من الناحية الفنية ، إلا أنني أعتقد أنه يجب أن تظل السلسلة و DataFrame متزامنتين.) أعتقد أنه يمكننا أن نسأل wesm عما يعتقده ولكن ...
  • انطلق وأعلن عن ndarray وفئاته الفرعية لإرضاء تعريف Sequence ، واقبل أنه بالنسبة لبعض الفئات الفرعية ndarray ستكون هذه كذبة. فقط على الأجزاء النادرة الاستخدام من واجهة Sequence ، على الرغم من ذلك ، وعادة ما تكون أنواع Python كاذبة على أي حال ...
  • أعد تشغيل التسلسل الهرمي للميراث لفصل الوظائف عن هراء الطبقة الأساسية المجردة. فعل
class multidim_ndarray(ndarray, Sequence):
  pass

وإنشاء نسخ متعددة المصفوفات المعتمة من هذه الفئة بدلاً من ذلك. لا تتأثر الفئات الفرعية لأنها تستمر في الوراثة من ndarray ، وليس multidim_ndarray . بالطبع ، يمكن أن ينتقل كائن ndarray واحد بين 0-d ومتعدد الأبعاد عبر .resize() ...

  • اقبل أن ndarray لن يكون Sequence أبدًا.

[الشيء isSequenceType هو نوع من التشتيت. هذه وظيفة قديمة تسبق وجود فئات أساسية مجردة (والتي تمت إضافتها في 2.6) ، ولا تحاول حتى تحديد الواجهة التفصيلية المطلوبة للتسلسلات - إنها تتحقق فقط من أن النوع (1) يحدد __getitem__ (2) ليس مدمجًا dict . من الواضح أن هذا سيعطي إجابة خاطئة في العديد من المواقف (على سبيل المثال ، أي شيء يعمل مثل إملاء ولكن ليس كذلك!). لذلك إذا كان المرء يريد بالفعل نوع التسلسل ، فإن isinstance(obj, Sequence) سوف يقوم بعمل أفضل ، و 2to3 يفعل الشيء الصحيح. لكنها تخلق مشكلة لـ numpy ...]

ربما يكون من الممكن إقناع أفراد الثعبان بإنشاء فئة جديدة مثل SequenceBase والتي تكون حتى أقل من التسلسل ولا تضمن .index أو .count ، ولكن فقط .__len__ و __getitem__ أو ما شابه ذلك؟ من الجيد أن يحتوي Sequence على شيء مثل index ، لكن يبدو من الغريب بعض الشيء فرضه على أشياء مثل numpy خلال جعله على ما يبدو كيفية كتابة تسلسل مثل الأشياء بطة. هل يدرك أهل الثعبان أن هذا يمثل مشكلة إلى حد ما؟

يعجبني اقتراحseberg ؛ إذا لم يوافق مطورو Python ، فسأختار النقطة الثانية منnjsmith. الخيار المفقود هو أن تقول فقط أن ndarrays لا تفي بواجهة التسلسل. ليس الأمثل ، ولكن أفضل من الرصاص 1 و 3 إيمهو.

[عفوًا ، كان "الخيار المفقود" موجودًا كخيار 4 ، ولكن بطريقة ما قرر محلل تخفيض السعر أن يطويه في الرمز النقطي السابق بطريقة مربكة وغير قابلة للقراءة. لقد قمت بتحرير التعليق لإصلاح التنسيق.]

نصف الأنواع المسجلة بـ Sequence ، أي buffer و xrange ، ليس لديها هذه الطرق أيضًا. ليس من الواضح بالنسبة لي أن هذه طرق مطلوبة للواجهة بقدر ما هي طرق ملائمة لأولئك الذين يستخدمون collections.Sequence كفئة أساسية / mixin.

rkern : التقاط جيد. لذلك ربما يكون الحل هو إضافة مكالمة إلى Sequence.register(np.ndarray) مكان ما. (قد يكون هذا أيضًا حلاً بديلاً للمراسل الأصلي).

ربما يجب أن نطبق __reversed__ في مرحلة ما أيضًا ...

rkern أنت محق ، هذا مذكور كمسألة مفتوحة في PEP: http://www.python.org/dev/peps/pep-3119/#sequences. من الغريب أن الأشخاص السياسيين السياسيين ذوي الحالة النهائية قد يواجهون مشكلات مفتوحة.

أعتقد أن عنوان هذا الخطأ مضلل بعض الشيء ، لأن الخطأ لا يوجد إلا في لغة python3. بالتأكيد ، random.sample(numpy_array) يعمل في python2 ، لكن isinstance(np.array([1]), collections.Sequence) يجب أن يُرجع True في أي Python> = 2.6.

لقد واجهت للتو هذا الخطأ في Python 2.7 باستخدام وحدة autopep8. بشكل افتراضي ، يتم تحويل بعض استدعاءات عامل التشغيل .isSequenceType () إلى isinstance (x ، collections.Sequence). سيصبح الاختبار خاطئًا عندما أجتاز في numpy.ndarray. يمكن أن يكون هذا خطأ متستر للغاية.

صادفته للتو أيضًا مع Python 2.7 ، باستخدام وحدة python-pillow. استدعاءات Image.point (lut، mode) isinstance (lut، collections.Sequence) ، الإصدار السابق يستخدم عامل التشغيل .isSequenceType ()

قد يكون الوقت مناسبًا الآن لإعادة النظر في هذا حيث تم تسجيل الأنواع العددية العددية (# 4547) ،

لذلك ربما يكون الحل هو إضافة استدعاء إلى Sequence.register (np.ndarray) في مكان ما.

نعم ، هذا حل وسط جيد.

نعم ، من فضلك أضف Sequence.register(np.ndarray) مكان ما.

mitar أي مصلحة في تقديم العلاقات العامة؟

بالتأكيد. إلى أين يذهب هذا؟ في نفس الملف حيث تم إنشاء 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 الذي تفكر فيه هنا. أنا لا أفهم ذلك بالضبط.

حالة الاستخدام هي كتابة رمز عام يعرف كيفية التحويل بين الأشياء ، مثل ما إذا كان يمكنك التكرار عبر تسلسل واستعادة البعد عن طريق التباين ، ثم التكرار. ثم يمكنني تحويل قائمة القوائم بنفس طريقة المصفوفة الثانية الثانية ، ولكن يمكن تعميمها على أبعاد متعددة وما إلى ذلك. ولست مضطرًا لأن أتحقق أكثر من مجرد أنه تسلسل.

كما ذكرنا ، هناك مشكلتان تتعلقان برؤية المصفوفات كتسلسلات بيثون متداخلة. __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)

لذلك أنا أميل إلى رؤية "مجموعة هو تسلسل" وذلك قياسا على إشكالية قليلا (وهذا لا يعني أنه لا يمكن أن يكون uesful، أنا أعترف).
ومع ذلك ، مهما كانت حالة الاستخدام ، فإنني أشعر بالفضول إذا لم يكن من الأفضل استكشاف ABC جديد ، مثل "ElementwiseContainer". واحد يخبر المستخدم أيضًا أن + و == ، وما إلى ذلك سيعمل على كل عنصر ، وعلى عكس متواليات Python ، يجب ألا يتوقعوا + للتسلسل ( yes + ليس جزءًا من Sequence ABC ، ​​لكنه يبدو طبيعيًا في Python).

مجرد مارة -
لقد كتبت إلى Python-ideas الأسبوع الماضي لأنني لاحظت أن Python collections.abc.Sequence لا يطبق __eq__ ومقارنات أخرى - على الرغم من أنه يحتوي على جميع الطرق الأخرى لتنفيذ تلك لجعل التسلسل يتصرف مثل القوائم و مجموعات. (يقودني موضوع البريد هذا إلى هذه المشكلة).

كنت أقترح إضافة __eq__ هناك ، لكن من الواضح أن ذلك سيجعل تلك التسلسلات تبتعد عن سلوك Numpy.array.

ماذا عن إضفاء الطابع الرسمي أكثر ، في Python ، ما هي "التسلسلات" ثم تفويض هذه الأشياء التي قد تتباعد كحالات متخصصة - لدرجة إضافة collections.abc.ComparableSequence هناك؟ (ونظرًا لأن + للإلغاء مذكور أعلاه ، فربما يشير اسم آخر إلى "تسلسلات تؤدي إلى مقارنة منطقية واحدة ، وتتصرف كقياسات للتسلسل والضرب في العدد" - أي سلوك Python لقائمة + و * في القائمة و tuples). لذلك ، يمكن إضفاء الطابع الرسمي على المواصفات الموجودة في Sequence بطريقة تطابقها تمامًا المصفوفات المعقدة أحادية الأبعاد.

يمكن أن يساعد هذا الشكل الرسمي لما هو تسلسل Python أيضًا في الاختلافات الأخرى ، مثل تلك المذكورة في https://github.com/numpy/numpy/issues/2776#issuecomment -330865166 أعلاه.

لا أشعر بالحافز الكافي للسير في هذا الطريق بمفردي ، ولكن إذا كان هذا منطقيًا ، فسأساعد في كتابة PEP وأساعد في دفعه. (أردت فقط التحقق من سبب عدم إنشاء التسلسل __eq__ ، وربما يكون لديّ علاقات عامة لذلك عندما طرحت هذا الأمر)

jsbueno مشكلتي هي أنني لا أرى حقًا ما هو إضافي ، أو بين التعريفين سيكون مفيدًا بالفعل لمستخدمي ndarray . أفضل ما يمكنني التفكير فيه هو Collection الذي يحتوي على count() و index() ، لكن هل هذا مفيد؟ أي شيء آخر سيكون ABC للأشياء التي ليس لدى Python نفسها مفهومًا عنها.

أعتقد أن SymPy قد فهمت الأمر بشكل أكثر صحة. يتكرر عبر جميع عناصر مصفوفاته ، مما يجعله على الأقل Collection .
الآن ، أشك في أنه يمكننا فعل الكثير حيال ذلك ، ولست متأكدًا من أن تكرار SymPy لجميع العناصر مفيد للغاية (وبديهي) ، ولكن على الأقل التكرار لجميع العناصر يتوافق مع __contains__ . لاحظ أن هذا يعني أيضًا أن len(Matrix) هو عدد العناصر ، و _not_ Matrix.shape[0] !

مع وجود خطر تكرار الكثير من الأعلى ، باستثناء المصفوفات 1-D ، ما هي المصفوفات المعقدة ؟:

  • 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__ لديه فرصة.)

أنا شخصياً أتوقع أن المصفوفات 1-D جانباً ، فإن المصفوفات هي ببساطة وحوش مختلفة جدًا مقارنة بمجموعات Python. عند التفكير في سلوك التكرار ، ستحتاج إلى MultidimensionalCollection للإشارة بشكل خاص إلى عدم التطابق بين __contains__ و __iter__ (لكن هل هذا مفيد؟).

عند النظر إلى ما هو أبعد مما هو محدد حاليًا بواسطة Sequence ، سأعيد التأكيد على أنني أعتقد أن ElementwiseCollection (المشغلون هم عاملون أساسيون بدلاً من مشغلي الحاويات ، على سبيل المثال + ) هو الأكثر تحديد خصائص المصفوفات غير المعقدة وجميع إبداءات الإعجاب بشكل عام (انظر برمجة المصفوفات). إنه أيضًا مفهوم غريب تمامًا - وأحيانًا يتعارض مع - بايثون نفسها.

الشيء الوحيد هو تعليم المصفوفات ذات البعد الواحد ، والمصفوفات ذات البعد الواحد فقط كتسلسلات ، حيث إنها لا تحتوي على عدم تطابق بين المصفوفات الفرعية مقابل العنصر. عند هذه النقطة ، نعم ، لم يتم تعريف __eq__ بالطبع بالنسبة لهم ، و __nonzero__ لم يتم تعريفه بشكل مشابه لتسلسلات Python النموذجية.

أشكركم على الرد ، وأنا أعتذر مرة أخرى للقفز في 8 سنوات طويلة هنا. بتعليقك ، بعد ساعتين من آخر تبادل للبريد الإلكتروني ، والدردشة مع صديق آخر في المنتصف ، أوافق على أن معظم هذه الأشياء من الأفضل تركها كما هي. في وقت ما في المستقبل ، يمكن أن تختار Python أن يكون لها تعريف أكثر رسمية للتسلسل من "أي مجموعات. abc.Sequence تنفذ الآن".

سأضيف فقط ، بعد قراءة تعليقاتك أعلاه ، أنني أعتقد أن الخصائص التي أدرجتها كـ "ما الذي يجعل تسلسل Python" تفتقر إلى الميزة الأكثر أهمية التي تجعل ndarras تشبه التسلسلات مثل القوائم و tuples بالنسبة لي: وجود فهرس متجاور- مساحة يمكنها معالجة جميع العناصر الفردية. لكنني لا أعتقد أن إضفاء الطابع الرسمي على 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 وربما تكريس نمط التسلسل المتداخل.

قد تكون طرق مثل المذكورة أعلاه معقولة كبروتوكول للمستهلك للعمل مع أي مجموعة تشبه المصفوفة ، ولكن هل هذه هي المشكلة التي نحاول حلها :)؟ يبدو أنها ليست مثل الأشياء التي قد ترغب تسلسلات بايثون النموذجية في كشفها.

@ eric-wieser

أنت على حق بالطبع ، لكن لا يمكنك تكرار التسلسل بأكمله. يمكنك انتقاء بعض العناصر فقط.

تضمين التغريدة

ما زلت أعتقد أننا نركز أكثر من اللازم على ما يمكن فعله وليس بما يكفي على ماهية المشاكل في هذا الوقت

أنا أتفق معك. ما نوع المشاكل التي تتخيلها؟ أتخيل أنه عندما يخرج الرقم 1.10 بأنواع ، سأحتاج أحيانًا إلى استخدام مصفوفة متداخلة أحادية البعد كسلسلة. إذا كنت أرغب في القيام بذلك حاليًا ، فأنا بحاجة إلى:

  • تحقق من أنه أحادي البعد ، و
  • اتصل بـ 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 على أبجديات ،

الآن بعد أن ذكرت ذلك ، ربما كان يجب أن تعيد جميع الطرق المقترحة وجهات نظر. بهذه الطريقة ، يمكنهم الإجابة بشكل صحيح على فحوصات الحالة.

قد تكون طرق مثل المذكورة أعلاه معقولة كبروتوكول للمستهلك للعمل مع أي مجموعة تشبه المصفوفة ، ولكن هل هذه هي المشكلة التي نحاول حلها :)؟ يبدو أنها ليست مثل الأشياء التي قد ترغب تسلسلات بايثون النموذجية في كشفها.

أوافق بالتأكيد على أن الإجابة على ذلك تعتمد على المشاكل التي نحاول حلها. بعد أن شربت نوع التعليق التوضيحي كوول أيد ، أنا مهتم بكتابة رمز مختصّر يمرر mypy دون إلقاء الكود مع # type: ignore . ما هي المشاكل التي تفكر فيها؟

حسنًا ، من المحتمل أن تكون تلميحات الكتابة والتفاعل مع كائنات أخرى تشبه المصفوفة دافعًا جيدًا. قد أقترح فتح موضوع جديد أو موضوع قائمة بريدية. في الوقت الحالي ، لست متأكدًا من أفضل ما يجب التفكير فيه هنا ، فالكتابة تتشكل ، لذلك ربما ينتهي الأمر بتوضيح بعض الأشياء.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

keithbriggs picture keithbriggs  ·  3تعليقات

inducer picture inducer  ·  3تعليقات

qualiaa picture qualiaa  ·  3تعليقات

Kreol64 picture Kreol64  ·  3تعليقات

dmvianna picture dmvianna  ·  4تعليقات