উত্তর:
আপনি মাঝে মাঝে যা দেখতে পাবেন তা নিম্নলিখিত:
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
পাইথনের আনুষ্ঠানিক ইন্টারফেস চুক্তি নেই (এবং এটির প্রয়োজন নেই), বিমূর্ততা এবং ইন্টারফেসের মধ্যে জাভা-শৈলীর পার্থক্য বিদ্যমান নেই। কেউ যদি একটি আনুষ্ঠানিক ইন্টারফেস সংজ্ঞায়িত করার প্রচেষ্টা চালায় তবে এটি একটি বিমূর্ত শ্রেণিও হবে। কেবলমাত্র পার্থক্যগুলি ডকাস্ট্রিংয়ের বর্ণিত অভিপ্রায় থাকবে।
যখন আপনার হাঁসের টাইপিং থাকে তখন বিমূর্ত এবং ইন্টারফেসের মধ্যে পার্থক্য একটি চুলচেরা জিনিস।
জাভা ইন্টারফেস ব্যবহার করে কারণ এর একাধিক উত্তরাধিকার নেই।
পাইথনের একাধিক উত্তরাধিকার রয়েছে বলে আপনি এটির মতো কিছু দেখতেও পারেন
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
এটি মিশ্রণগুলির সাথে এক ধরণের অ্যাবস্ট্রাক্ট সুপারক্লাস ব্যবহার করে যা ছিন্নমূল কংক্রিটের সাবক্লাসগুলি তৈরি করে।
NotImplementedError("Class %s doesn't implement aMethod()" % (self.__class__.__name__))
আরও তথ্যবহুল ত্রুটির বার্তাটি :)
পাইথনে অ্যাবস্ট্রাক্ট ক্লাস এবং ইন্টারফেসের মধ্যে পার্থক্য কী?
একটি ইন্টারফেস, কোনও বস্তুর জন্য, সেই অবজেক্টের পদ্ধতি এবং বৈশিষ্ট্যের একটি সেট।
পাইথনে, আমরা একটি ইন্টারফেস সংজ্ঞা এবং প্রয়োগ করতে একটি বিমূর্ত বেস শ্রেণি ব্যবহার করতে পারি।
উদাহরণস্বরূপ, বলুন আমরা collections
মডিউলটি থেকে একটি বিমূর্ত বেস ক্লাস ব্যবহার করতে চাই :
import collections
class MySet(collections.Set):
pass
আমরা যদি এটি ব্যবহার করার চেষ্টা করি তবে আমরা একটি পাই TypeError
কারণ আমাদের তৈরি করা শ্রেণি সেটগুলির প্রত্যাশিত আচরণকে সমর্থন করে না:
>>> MySet()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__
সুতরাং আমরা এ বাস্তবায়ন প্রয়োজন অন্তত __contains__
, __iter__
এবং __len__
। ডকুমেন্টেশন থেকে এই প্রয়োগের উদাহরণটি ব্যবহার করুন :
class ListBasedSet(collections.Set):
"""Alternate set implementation favoring space over speed
and not requiring the set elements to be hashable.
"""
def __init__(self, iterable):
self.elements = lst = []
for value in iterable:
if value not in lst:
lst.append(value)
def __iter__(self):
return iter(self.elements)
def __contains__(self, value):
return value in self.elements
def __len__(self):
return len(self.elements)
s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2
প্রাসঙ্গিক পদ্ধতিতে মেটাকগ্লাস সেট করে এবং ডেকরেটার abc.ABCMeta
ব্যবহার করে আমরা আমাদের নিজস্ব বিমূর্ত বেস ক্লাস তৈরি করতে পারি abc.abstractmethod
। মেটাক্লাসটি __abstractmethods__
অ্যাট্রিবিউটে সজ্জিত ফাংশনগুলি যুক্ত করা হবে , ততক্ষণ সংজ্ঞা দেওয়া না হওয়া অবধি তড়িঘড়ি আটকাবে ।
import abc
উদাহরণস্বরূপ, "কার্যকর" এমন কিছু হিসাবে সংজ্ঞায়িত করা হয়েছে যা কথায় প্রকাশ করতে পারে। বলুন আমরা পাইথন 2 এ কার্যকরভাবে কার্যকর এমন একটি বিমূর্ত বেস শ্রেণি সংজ্ঞা দিতে চেয়েছিলাম:
class Effable(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
বা পাইথন 3-এ, মেটাক্লাস ঘোষণার সামান্য পরিবর্তন সহ:
class Effable(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
এখন যদি আমরা ইন্টারফেসটি বাস্তবায়ন না করে কার্যকর একটি অবজেক্ট তৈরি করার চেষ্টা করি:
class MyEffable(Effable):
pass
এবং এটি ইনস্ট্যান্ট করার চেষ্টা করুন:
>>> MyEffable()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__
আমাদের বলা হয় যে আমরা কাজ শেষ করিনি।
এখন আমরা যদি প্রত্যাশিত ইন্টারফেস সরবরাহ করে মেনে চলি:
class MyEffable(Effable):
def __str__(self):
return 'expressable!'
তারপরে আমরা বিমূর্তটি থেকে প্রাপ্ত ক্লাসের কংক্রিট সংস্করণটি ব্যবহার করতে সক্ষম হয়েছি:
>>> me = MyEffable()
>>> print(me)
expressable!
ইতিমধ্যে এই ইন্টারফেসগুলি বাস্তবায়িত ভার্চুয়াল সাবক্লাসেসের মতো আমরা এর সাথে আরও কিছু করতে পারি, তবে আমি মনে করি এটি এই প্রশ্নের আওতার বাইরে। এখানে প্রদর্শিত অন্যান্য পদ্ধতিগুলির ক্ষেত্রে abc
মডিউলটি ব্যবহার করে এই পদ্ধতিটি মানিয়ে নিতে হবে ।
আমরা দেখিয়েছি যে একটি অ্যাবস্ট্রাক্ট বেস ক্লাস তৈরি পাইথনের কাস্টম অবজেক্টের জন্য ইন্টারফেসকে সংজ্ঞায়িত করে।
পাইথন> = 2.6 এর অ্যাবস্ট্রাক্ট বেস ক্লাস রয়েছে ।
অ্যাবস্ট্রাক্ট বেস ক্লাস (সংক্ষেপিত এবিসি) হাঁস-টাইপিংয়ের পরিপূরক যখন ইন্টারফেসগুলি সংজ্ঞায়িত করার উপায় সরবরাহ করে যখন হ্যাশট্রের () এর মতো অন্যান্য কৌশলগুলি আনাড়ি হয়ে থাকে। পাইথন ডেটা স্ট্রাকচার (সংগ্রহ মডিউলে), সংখ্যা (সংখ্যার মডিউলে) এবং স্ট্রিমগুলির (আইও মডিউলে) অনেকগুলি বিল্টিন এবিসি নিয়ে আসে। আপনি এবিসি মডিউলটি দিয়ে নিজের নিজস্ব এবিসি তৈরি করতে পারেন।
রয়েছে Zope ইন্টারফেস মডিউল দেখবেন, যার পাকান মতো zope বাইরে প্রকল্প দ্বারা ব্যবহৃত হয়। আমি এর সাথে সত্যই পরিচিত নই, তবে এখানে একটি উইকি পৃষ্ঠা রয়েছে যা সাহায্য করতে পারে।
সাধারণভাবে, আপনাকে অজগর শ্রেণীর ধারণা বা পাইথনে ইন্টারফেসের প্রয়োজন নেই (সম্পাদিত - বিশদর জন্য এস.লোটের উত্তর দেখুন)।
পাইথনের আসলেই কোন ধারণা নেই।
এটি হাঁসের টাইপিং ব্যবহার করে, যা ইন্টারফেসের প্রয়োজনীয়তা সরিয়ে দেয় (কমপক্ষে কম্পিউটারের জন্য :-))
পাইথন <= 2.5: বেস ক্লাসগুলি স্পষ্টতই বিদ্যমান, তবে কোনও পদ্ধতিকে 'খাঁটি ভার্চুয়াল' হিসাবে চিহ্নিত করার কোনও সুস্পষ্ট উপায় নেই, সুতরাং শ্রেণিটি সত্যই বিমূর্ত নয়।
পাইথন> = 2.6: বিমূর্ত বেস ক্লাসগুলি বিদ্যমান ( http://docs.python.org/library/abc.html )। এবং আপনাকে এমন উপায়ে নির্দিষ্ট করতে অনুমতি দেয় যা অবশ্যই সাবক্লাসে প্রয়োগ করা উচিত। আমি সিনট্যাক্সটি বেশি পছন্দ করি না তবে বৈশিষ্ট্যটি এখানে রয়েছে। বেশিরভাগ সময় ক্লায়েন্ট পক্ষ থেকে 'ব্যবহার করে' থেকে হাঁসের টাইপিং ব্যবহার করা ভাল।
আরও প্রাথমিক পদ্ধতিতে ব্যাখ্যা করার জন্য: একটি ইন্টারফেস হ'ল খালি মাফিন প্যানের মতো। এটি এমন কোনও শ্রেণীর ফাইল যা পদ্ধতি সংজ্ঞাগুলির একটি সেট সহ কোনও কোড নেই।
একটি বিমূর্ত শ্রেণি একই জিনিস, তবে সমস্ত ফাংশন খালি থাকার প্রয়োজন হয় না। কিছু কোড থাকতে পারে। এটি কঠোরভাবে খালি নয়।
কেন পার্থক্য করুন: পাইথনে খুব বেশি ব্যবহারিক পার্থক্য নেই, তবে একটি বৃহত প্রকল্পের পরিকল্পনার স্তরে ইন্টারফেসগুলি নিয়ে কথা বলা আরও সাধারণ হতে পারে, কারণ কোনও কোড নেই। বিশেষত যদি আপনি জাভা প্রোগ্রামারদের সাথে কাজ করছেন যারা এই শব্দটির সাথে অভ্যস্ত।
সাধারণভাবে, ইন্টারফেসগুলি কেবল সেই ভাষাগুলিতেই ব্যবহৃত হয় যা একক-উত্তরাধিকার শ্রেণির মডেল ব্যবহার করে। এই একক-উত্তরাধিকারী ভাষায়, ইন্টারফেসগুলি সাধারণত ব্যবহৃত হয় যদি কোনও শ্রেণি কোনও নির্দিষ্ট পদ্ধতি বা পদ্ধতির সেট ব্যবহার করতে পারে। এছাড়াও এই একক-উত্তরাধিকারী ভাষাগুলিতে, বিমূর্ত ক্লাসগুলি হয় না কোনও বা ততোধিক পদ্ধতি ছাড়াও শ্রেণিবদ্ধ ভেরিয়েবলগুলি সংজ্ঞায়িত করতে ব্যবহৃত হয় বা একক-উত্তরাধিকারের মডেলটি ব্যবহার করে যে পদ্ধতিগুলির সেট ব্যবহার করতে পারে এমন শ্রেণীর সীমাটি সীমাবদ্ধ করতে ব্যবহার করা হয়।
একাধিক-উত্তরাধিকারের মডেলকে সমর্থন করে এমন ভাষাগুলি কেবল ক্লাস বা বিমূর্ত বেস ক্লাস ব্যবহার করে এবং ইন্টারফেস নয়। পাইথন যেহেতু একাধিক উত্তরাধিকারকে সমর্থন করে তাই এটি ইন্টারফেস ব্যবহার করে না এবং আপনি বেস ক্লাস বা বিমূর্ত বেস ক্লাস ব্যবহার করতে চান।
বিমূর্ত শ্রেণি ক্লাস যা এক বা একাধিক বিমূর্ত পদ্ধতি ধারণ করে। বিমূর্ত পদ্ধতি সহ, বিমূর্ত শ্রেণিতে স্থিতিশীল, শ্রেণি এবং উদাহরণ পদ্ধতি থাকতে পারে। তবে ইন্টারফেসের ক্ষেত্রে এটির বিমূর্ত পদ্ধতি কেবল অন্য নয়। সুতরাং বিমূর্ত শ্রেণীর উত্তরাধিকারী হওয়া বাধ্যতামূলক নয় তবে ইন্টারফেসের উত্তরাধিকারী হওয়া বাধ্যতামূলক।
সম্পূর্ণতার জন্য, আমাদের PEP3119 উল্লেখ করতে হবে যেখানে ABC চালু হয়েছিল এবং ইন্টারফেসের সাথে তুলনা করা হয়েছিল, এবং মূল তালিনের মন্তব্য।
বিমূর্ত শ্রেণি নিখুঁত ইন্টারফেস নয়:
তবে আপনি যদি এটি নিজের মতো করে লেখার বিষয়টি বিবেচনা করেন:
def some_function(self):
raise NotImplementedError()
interface = type(
'your_interface', (object,),
{'extra_func': some_function,
'__slots__': ['extra_func', ...]
...
'__instancecheck__': your_instance_checker,
'__subclasscheck__': your_subclass_checker
...
}
)
ok, rather as a class
or as a metaclass
and fighting with python to achieve the immutable object
and doing refactoring
...
আপনি বেশ দ্রুত বুঝতে পারবেন যে আপনি অবশেষে অর্জনের জন্য চাকাটি আবিষ্কার করছেন
abc.ABCMeta
abc.ABCMeta
অনুপস্থিত ইন্টারফেস কার্যকারিতাটির একটি দরকারী সংযোজন হিসাবে প্রস্তাবিত হয়েছিল, এবং অজগর মতো ভাষায় এটি যথেষ্ট ন্যায্য।
অবশ্যই, সংস্করণ 3 রচনাকালীন এটি আরও উন্নত হতে সক্ষম হয়েছিল এবং নতুন সিনট্যাক্স এবং অপরিবর্তনীয় ইন্টারফেস ধারণা যুক্ত করা ...
উপসংহার:
The abc.ABCMeta IS "pythonic" interface in python