কলিং এর মধ্যে কোন পার্থক্য আছে len([1,2,3])নাকি [1,2,3].__len__()?
যদি কোনও দৃশ্যমান পার্থক্য না থাকে তবে পর্দার আড়ালে আলাদাভাবে কী করা হয়?
উত্তর:
lenএকটি সংগ্রহ দৈর্ঘ্য পেতে একটি ফাংশন। এটি কোনও অবজেক্টের __len__পদ্ধতিতে কল করে কাজ করে । __something__বৈশিষ্ট্যগুলি বিশেষ এবং সাধারণত চোখের বেশি দেখা যায় এবং সাধারণত সরাসরি ডাকা উচিত নয়।
অনেক আগে সিদ্ধান্ত নেওয়া হয়েছিল যে কোনও কিছুর দৈর্ঘ্য পাওয়া একটি ফাংশন হওয়া উচিত এবং কোনও পদ্ধতি কোড নয়, যুক্তি দিয়ে যে len(a)এর অর্থ প্রাথমিকভাবে a.len()স্পষ্ট হবে তবে ততটা পরিষ্কার হবে না। পাইথন যখন শুরু হয়েছিল __len__তখনও এর অস্তিত্ব lenছিল না এবং এটি একটি বিশেষ জিনিস যা কয়েক ধরণের অবজেক্টের সাথে কাজ করেছিল। আমাদের পরিস্থিতিটি ছেড়ে দেয় কি না তা পুরোপুরি বোঝায়, এটি এখানেই রয়েছে।
এটি প্রায়শই এমন হয় যে কোনও অন্তর্নির্মিত বা অপারেটরের "সাধারণ" আচরণটি __whatever__জড়িত অবজেক্টগুলিতে উপযুক্ত জাদু পদ্ধতিগুলি (যেমন নামগুলির সাথে থাকে ) কল করা হয়। প্রায়শই অন্তর্নির্মিত বা অপারেটরের "সংযোজিত মান" থাকে (এটি জড়িত বস্তুর উপর নির্ভর করে বিভিন্ন পাথ গ্রহণ করতে সক্ষম হয়) - lenবনামের ক্ষেত্রে __len__এটি বিল্ট-ইনটি থেকে নিখরচায় কিছুটা বিশুদ্ধতা যাচাই করে চলেছে যা অনুপস্থিত is যাদু পদ্ধতি:
>>> class bah(object):
... def __len__(self): return "an inch"
...
>>> bah().__len__()
'an inch'
>>> len(bah())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
যখন আপনি lenঅন্তর্নির্মিতকে কোনও কল দেখেন , আপনি নিশ্চিত হন যে প্রোগ্রামটি যদি তার পরেও ব্যতিক্রম বাড়ানোর পরিবর্তে অব্যাহত থাকে, কলটি একটি পূর্ণসংখ্যা, অ-নেতিবাচক এবং 2 ** 31 এর চেয়ে কম ফিরিয়ে দেয় - কখন আপনি এই কলটি দেখতে পাচ্ছেন xxx.__len__(), আপনার কোনও নিশ্চিততা নেই (কোডটির লেখক পাইথনের সাথে অপরিচিত বা কোনও ভাল ;-) পর্যন্ত নয়।
অন্যান্য বিল্ট-ইনগুলি সাধারণ স্যানিটি চেক এবং পঠনযোগ্যতার বাইরে আরও বেশি যুক্ত মূল্য সরবরাহ করে। বিল্টিনগুলিতে কল এবং অপারেটরদের ব্যবহারের মাধ্যমে পাইথনের সমস্ত কাজকে অভিন্নভাবে ডিজাইনের মাধ্যমে, যাদু পদ্ধতিগুলির মাধ্যমে কল করার মাধ্যমে কখনই প্রোগ্রামাররা কোন ঘটনাটি মনে রাখার বোঝা থেকে রক্ষা পায় না। (কখনও কখনও ত্রুটি পিছলে যায়: 2.5 অবধি, আপনাকে কল করতে হয়েছিল foo.next()- 2.6 এ, এটি এখনও পিছনের সামঞ্জস্যের জন্য কাজ করে, আপনাকে কল করা উচিত next(foo), এবং 3.*ম্যাজিক পদ্ধতিটি __next__"ওফস-এ" এর পরিবর্তে সঠিকভাবে নামকরণ করা হয়েছে next! - )।
সুতরাং সাধারণ নিয়মটি কখনই সরাসরি কোনও যাদু পদ্ধতিতে কল করা উচিত নয় (তবে সর্বদা অন্তর্নির্মিতের মাধ্যমে সর্বদা অপ্রত্যাশিতভাবে) যদি না আপনি সঠিকভাবে জানেন তবে আপনাকে কেন এটি করা প্রয়োজন (যেমন, আপনি যখন সাবক্লাসে এই জাতীয় পদ্ধতিটি উপেক্ষা করছেন, যদি সাবক্লাসকে সুপারক্লাসে স্থগিত করা দরকার যা ম্যাজিক পদ্ধতিতে স্পষ্ট কলের মাধ্যমে করা আবশ্যক)।
def len(x): return "I am a string." print(len(42)) print(len([1,2,3]))এবং এটি I am stringদুবার মুদ্রিত হয়েছিল। আপনি আরও ব্যাখ্যা করতে পারেন?
__len__বিশেষ পদ্ধতি (ফাংশন নয়) বলে।
lenনা (আমার উদাহরণে মত) কিছু অন্যান্য ফাংশন যা একই নাম ঘটেছে - len। "আপনি অন্তর্নির্মিত ফাংশন লেনটিকে পুনরায় সংজ্ঞায়িত করছেন" বা এর মতো কোনও সতর্কতা নেই। আমার মতে, অ্যালেক্স তার উত্তরে যা বলেছিল তা সম্পর্কে আমি নিশ্চিত হতে পারি না।
len in vars(__builtins__).values()।
আপনি লেন () প্রায় সমতুল্য হিসাবে ভাবতে পারেন
def len(x):
return x.__len__()
একটি সুবিধা হ'ল এটি আপনাকে পছন্দ মতো জিনিস লেখার অনুমতি দেয়
somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist)
পরিবর্তে
map(list.__len__, somelist)
বা
map(operator.methodcaller('__len__'), somelist)
যদিও কিছুটা আলাদা আচরণ আছে। উদাহরণস্বরূপ ints ক্ষেত্রে
>>> (1).__len__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__len__'
>>> len(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
operator.methodcallerপরিবর্তে মানে ধরে নিচ্ছি operator.attrgetter।
আপনি পাইথন্ড ডক্স পরীক্ষা করতে পারেন :
>>> class Meta(type):
... def __getattribute__(*args):
... print "Metaclass getattribute invoked"
... return type.__getattribute__(*args)
...
>>> class C(object):
... __metaclass__ = Meta
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print "Class getattribute invoked"
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10