لماذا الثعبان رمز استخدام len() وظيفة بدلا من طول الأسلوب ؟

StackOverflow https://stackoverflow.com/questions/237128

سؤال

أنا أعرف هذا الثعبان لديه len() الدالة التي يتم استخدامها لتحديد حجم السلسلة, ولكن كنت أتساءل لماذا انها ليست طريقة كائن string.

التحديث

حسنا, أدركت أنني كنت محرج مخطئا. __len__() هو في الواقع وسيلة من سلسلة الكائن.يبدو الأمر غريبا أن نرى وجوه المنحى رمز في بيثون باستخدام الدالة len على سلسلة الكائنات.وعلاوة على ذلك, كما انه من الغريب أن نرى __len__ اسم بدلا من مجرد لين.

هل كانت مفيدة؟

المحلول

سلاسل لديك طول الطريقة: __len__()

البروتوكول في بيثون هو تنفيذ هذه الطريقة على الكائنات التي لها طول و استخدام المدمج في len() وظيفة, الذي يدعو لك ، على غرار الطريقة التي سوف تنفذ __iter__() واستخدام المدمج في iter() وظيفة (أو طريقة تسمى وراء الكواليس بالنسبة لك) على الكائنات التي iterable.

انظر محاكاة أنواع الحاويات للحصول على مزيد من المعلومات.

هنا قراءة جيدة حول هذا الموضوع من البروتوكولات في بايثون: الثعبان هذا المبدأ

نصائح أخرى

جيم جواب هذا السؤال يمكن أن تساعد ؛ أنا نسخ هنا.نقلا عن Guido van Rossum:

أولا أنا اختار len(x) على x.ليون() عن HCI الأسباب (def __len__() جاء وقت لاحق من ذلك بكثير).هناك نوعان من وتتشابك الأسباب في الواقع كلا HCI:

(أ) بعض عمليات تدوين البادئة فقط يقرأ أفضل من بوستفيكس البادئة (و أقحم!) عمليات لديها تقليد طويل في الرياضيات التي يحب الرموز حيث صور مساعدة رياضيات التفكير في مشكلة.قارن سهلة مع كتابة صيغة مثل x*(a+b) في سa + xب إلى الحماقات من فعل الشيء نفسه باستخدام الخام OO التدوين.

(ب) عندما قرأت التعليمات البرمجية التي يقول len(x) وأنا أعلم أنه يسأل عن طول شيء.هذا يقول لي أمرين:والنتيجة هي عدد صحيح و الحجة هي نوع من الحاويات.على العكس من ذلك ، عندما قرأت x.ليون(), يجب أن نعلم بالفعل أن x هو نوع من الحاويات تنفيذ واجهة أو وراثة من فئة القياسية لين().شاهد الارتباك لدينا بعض الأحيان عند فئة ليست تطبيق الخرائط يحتوي على() أو المفاتيح (طريقة) ، أو شيء ليس ملف لديه أسلوب الكتابة ().

نقول نفس الشيء بطريقة أخرى ، أرى 'ليون' المدمج في العملية.أنا أكره أن تفقد ذلك./.../

هناك len الطريقة:

>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

بيثون هو عملي لغة البرمجة ، len() كونه وظيفة وليس وسيلة str, list, dict الخ.هي واقعية.

على len() المدمج في وظيفة يتعامل مباشرة مع المدمج في أنواع:على CPython تنفيذ len() في الحقيقة ترجع قيمة ob_size مجال في PyVarObject C أن يمثل أي متغير الحجم المدمج في وجوه في الذاكرة.هذا هو كثيرا أسرع من استدعاء الأسلوب-أي البحث سمة يجب أن يحدث.الحصول على عدد العناصر في مجموعة هي عملية مشتركة ويجب أن تعمل بكفاءة لهذه الأساسية وأنواع مختلفة كما str, list, array.array الخ.

ومع ذلك ، من أجل تعزيز الاتساق ، عند تطبيق len(o) إلى نوع معرف من قبل المستخدم ، بيثون المكالمات o.__len__() كما تراجع. __len__, __abs__ وغيرها من أساليب خاصة موثقة في بيثون نموذج البيانات تجعل من السهل لخلق الكائنات التي تتصرف مثل المدمج الإضافية ، تمكين معبرة متسقة للغاية واجهات برمجة التطبيقات نسميه "Pythonic".

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

السبب الثاني ، بدعم من يقتبس من Guido van Rossum مثل هذا واحد, هو أسهل للقراءة والكتابة len(s) من s.len().

التدوين len(s) يتسق مع استخدام عوامل التشغيل الأحادية مع البادئة التدوين ، مثل abs(n). len() يستخدم الطريقة في أكثر الأحيان abs(), و أنه يستحق أن يكون من السهل الكتابة.

قد يكون هناك أيضا السبب التاريخي:في حروف اللغة التي سبقت بايثون (و كان مؤثر جدا في التصميم) ، كان هناك الأحادية المشغل كما هو مكتوب #s مما يعني len(s).

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

هناك بعض الإجابات هنا ، حتى قبل أن أعطي بلدي أود أن أسلط الضوء على عدد قليل من الأحجار الكريمة (لا روبي يقصد التورية) قرأت هنا.

  • بايثون ليست نقية صافية اللغة-هو الغرض العام متعدد نموذج اللغة التي يسمح للمبرمج استخدام النموذج هم أكثر راحة مع و/أو النموذج الذي هو الانسب لحلها.
  • بيثون لديها وظائف من الدرجة الأولى ، لذلك len هو في الحقيقة كائن.روبي, من ناحية أخرى, لا يكون من الدرجة الأولى الوظائف.لذلك len وظيفة الكائن نفسه الأساليب التي يمكنك فحص عن طريق تشغيل dir(len).

إذا كنت لا تحب الطريقة التي يعمل هذا في التعليمات البرمجية الخاصة بك, انها تافهة بالنسبة لك لإعادة تنفيذ الحاويات باستخدام طريقة الدفع المفضلة لديك (انظر المثال أدناه).

>>> class List(list):
...     def len(self):
...         return len(self)
...
>>> class Dict(dict):
...     def len(self):
...         return len(self)
...
>>> class Tuple(tuple):
...     def len(self):
...         return len(self)
...
>>> class Set(set):
...     def len(self):
...         return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
...     print container.len()
...
15
2
15
15

يمكنك أيضا أن أقول

>> x = 'test'
>> len(x)
4

باستخدام بيثون 2.7.3.

فإنه لا ؟

>>> "abc".__len__()
3
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top