Python Language
ओवरलोडिंग
खोज…
जादू / डंडर तरीके
पायथन में मैजिक (जिसे डबल-अंडरस्कोर के लिए एक संक्षिप्त नाम के रूप में भी कहा जाता है) अन्य भाषाओं में ओवरलोडिंग करने वाले ऑपरेटर के लिए एक समान उद्देश्य प्रदान करता है। वे एक वर्ग को अपने व्यवहार को परिभाषित करने की अनुमति देते हैं जब इसे एक संचालन के रूप में उपयोग किया जाता है। वे कुछ अंतर्निहित कार्यों द्वारा कार्यान्वित कार्यान्वयन के रूप में भी कार्य करते हैं।
दो आयामी वैक्टर के इस कार्यान्वयन पर विचार करें।
import math
class Vector(object):
# instantiation
def __init__(self, x, y):
self.x = x
self.y = y
# unary negation (-v)
def __neg__(self):
return Vector(-self.x, -self.y)
# addition (v + u)
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
# subtraction (v - u)
def __sub__(self, other):
return self + (-other)
# equality (v == u)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
# abs(v)
def __abs__(self):
return math.hypot(self.x, self.y)
# str(v)
def __str__(self):
return '<{0.x}, {0.y}>'.format(self)
# repr(v)
def __repr__(self):
return 'Vector({0.x}, {0.y})'.format(self)
अब विभिन्न अभिव्यक्तियों में Vector
वर्ग के उदाहरणों का स्वाभाविक रूप से उपयोग करना संभव है।
v = Vector(1, 4)
u = Vector(2, 0)
u + v # Vector(3, 4)
print(u + v) # "<3, 4>" (implicit string conversion)
u - v # Vector(1, -4)
u == v # False
u + v == v + u # True
abs(u + v) # 5.0
कंटेनर और अनुक्रम प्रकार
कंटेनर प्रकारों का अनुकरण करना संभव है, जो कुंजी या इंडेक्स द्वारा एक्सेस मूल्यों का समर्थन करते हैं।
विरल सूची के इस अनुभवहीन कार्यान्वयन पर विचार करें, जो स्मृति को संरक्षित करने के लिए केवल अपने गैर-शून्य तत्वों को संग्रहीत करता है।
class sparselist(object):
def __init__(self, size):
self.size = size
self.data = {}
# l[index]
def __getitem__(self, index):
if index < 0:
index += self.size
if index >= self.size:
raise IndexError(index)
try:
return self.data[index]
except KeyError:
return 0.0
# l[index] = value
def __setitem__(self, index, value):
self.data[index] = value
# del l[index]
def __delitem__(self, index):
if index in self.data:
del self.data[index]
# value in l
def __contains__(self, value):
return value == 0.0 or value in self.data.values()
# len(l)
def __len__(self):
return self.size
# for value in l: ...
def __iter__(self):
return (self[i] for i in range(self.size)) # use xrange for python2
फिर, हम एक नियमित list
तरह बहुत कुछ एक sparselist
उपयोग कर सकते हैं।
l = sparselist(10 ** 6) # list with 1 million elements
0 in l # True
10 in l # False
l[12345] = 10
10 in l # True
l[12345] # 10
for v in l:
pass # 0, 0, 0, ... 10, 0, 0 ... 0
कॉल करने योग्य प्रकार
class adder(object):
def __init__(self, first):
self.first = first
# a(...)
def __call__(self, second):
return self.first + second
add2 = adder(2)
add2(1) # 3
add2(2) # 4
अनुपयोगी व्यवहार को संभालना
यदि आपका वर्ग प्रदान किए गए तर्क प्रकारों के लिए एक विशिष्ट अतिभारित ऑपरेटर को लागू नहीं करता है, तो उसे return NotImplemented
( ध्यान दें कि यह एक विशेष स्थिरांक है , NotImplementedError
के समान नहीं) को return NotImplemented
करना चाहिए। यह पायथन को ऑपरेशन के काम करने के अन्य तरीकों की कोशिश करने के लिए वापस गिरने की अनुमति देगा:
जब
NotImplemented
लौटाया जाता है, तो दुभाषिया फिर ऑपरेटर के आधार पर दूसरे प्रकार, या कुछ अन्यNotImplemented
पर परिलक्षित ऑपरेशन का प्रयास करेगा। यदि सभी प्रचालित ऑपरेशनNotImplemented
वापसNotImplemented
, तो दुभाषिया एक उपयुक्त अपवाद जुटाएगा।
उदाहरण के लिए, x + y
दिया जाता है, यदि x.__add__(y)
, तो अनइम्प्लिमेंटेड रिटर्न, y.__radd__(x)
बजाय प्रयास किया जाता है।
class NotAddable(object):
def __init__(self, value):
self.value = value
def __add__(self, other):
return NotImplemented
class Addable(NotAddable):
def __add__(self, other):
return Addable(self.value + other.value)
__radd__ = __add__
जैसा कि यह परिलक्षित पद्धति है, हमें सभी मामलों में अपेक्षित व्यवहार प्राप्त करने के लिए __add__
और __radd__
को लागू __add__
; सौभाग्य से, जैसा कि वे दोनों इस सरल उदाहरण में एक ही काम कर रहे हैं, हम एक शॉर्टकट ले सकते हैं।
उपयोग में:
>>> x = NotAddable(1)
>>> y = Addable(2)
>>> x + x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NotAddable' and 'NotAddable'
>>> y + y
<so.Addable object at 0x1095974d0>
>>> z = x + y
>>> z
<so.Addable object at 0x109597510>
>>> z.value
3
ऑपरेटर ओवरलोडिंग
नीचे वे ऑपरेटर हैं जिन्हें कक्षाओं में अतिभारित किया जा सकता है, साथ ही आवश्यक विधि परिभाषाएँ और अभिव्यक्ति के भीतर उपयोग में ऑपरेटर का एक उदाहरण।
एनबी एक चर नाम के रूप में other
का उपयोग अनिवार्य नहीं है, लेकिन आदर्श माना जाता है।
ऑपरेटर | तरीका | अभिव्यक्ति |
---|---|---|
+ जोड़ | __add__(self, other) | a1 + a2 |
- घटाव | __sub__(self, other) | a1 - a2 |
* गुणन | __mul__(self, other) | a1 * a2 |
@ मैट्रिक्स गुणन | __matmul__(self, other) | a1 @ a2 ( पायथन 3.5 ) |
/ मंडल | __div__(self, other) | a1 / a2 ( केवल पायथन 2 ) |
/ मंडल | __truediv__(self, other) | a1 / a2 ( पायथन 3 ) |
// फ्लोर डिवीजन | __floordiv__(self, other) | a1 // a2 |
% मोदुलो / अवशेष | __mod__(self, other) | a1 % a2 |
** शक्ति | __pow__(self, other[, modulo]) | a1 ** a2 |
<< बिटकॉइन लेफ्ट शिफ्ट | __lshift__(self, other) | a1 << a2 |
>> बिटवाइज़ राइट शिफ्ट | __rshift__(self, other) | a1 >> a2 |
& बिटवाइज़ और | __and__(self, other) | a1 & a2 |
^ बिटवाइज XOR | __xor__(self, other) | a1 ^ a2 |
| (बिटवाइज़ ओआर) | __or__(self, other) | a1 | a2 |
- निषेध (अंकगणित) | __neg__(self) | -a1 |
+ सकारात्मक | __pos__(self) | +a1 |
~ बिटवाइज़ not | __invert__(self) | ~a1 |
< कम है | __lt__(self, other) | a1 < a2 |
<= कम या बराबर | __le__(self, other) | a1 <= a2 |
== बराबर | __eq__(self, other) | a1 == a2 |
!= नहीं के बराबर | __ne__(self, other) | a1 != a2 |
> बड़ा | __gt__(self, other) | a1 > a2 |
>= से अधिक या उसके बराबर | __ge__(self, other) | a1 >= a2 |
[index] सूचकांक ऑपरेटर | __getitem__(self, index) | a1[index] |
in में ऑपरेटर | __contains__(self, other) | a2 in a1 |
(*args, ...) कॉलिंग | __call__(self, *args, **kwargs) | a1(*args, **kwargs) |
__pow__
लिए वैकल्पिक पैरामीटर modulo
उपयोग केवल pow
-इन फ़ंक्शन द्वारा किया जाता है।
एक बाइनरी ऑपरेटर से संबंधित प्रत्येक विधि में एक "समरूप" विधि होती है, जो __r
शुरू __r
, उदाहरण के लिए __radd__
:
class A:
def __init__(self, a):
self.a = a
def __add__(self, other):
return self.a + other
def __radd__(self, other):
print("radd")
return other + self.a
A(1) + 2 # Out: 3
2 + A(1) # prints radd. Out: 3
__i
साथ शुरू होने वाले एक संगत inplace संस्करण:
class B:
def __init__(self, b):
self.b = b
def __iadd__(self, other):
self.b += other
print("iadd")
return self
b = B(2)
b.b # Out: 2
b += 1 # prints iadd
b.b # Out: 3
चूंकि इन तरीकों के बारे में कुछ खास नहीं है, भाषा के कई अन्य हिस्से, मानक पुस्तकालय के कुछ हिस्सों, और यहां तक कि तीसरे पक्ष के मॉड्यूल अपने आप पर जादू के तरीकों को जोड़ते हैं, जैसे किसी वस्तु को किसी प्रकार की वस्तु या गुणों की जांच करने के तरीके। उदाहरण के लिए, अंतर्निहित str()
फ़ंक्शन ऑब्जेक्ट की __str__
विधि को कॉल करता है, अगर यह मौजूद है। इनमें से कुछ उपयोग नीचे सूचीबद्ध हैं।
समारोह | तरीका | अभिव्यक्ति |
---|---|---|
int करने के लिए कास्टिंग | __int__(self) | int(a1) |
पूर्ण कार्य | __abs__(self) | abs(a1) |
करने के लिए कास्टिंग str | __str__(self) | str(a1) |
unicode लिए कास्टिंग | __unicode__(self) | unicode(a1) (केवल पायथन 2) |
स्ट्रिंग प्रतिनिधित्व | __repr__(self) | repr(a1) |
कास्टिंग टू bool | __nonzero__(self) | bool(a1) |
स्ट्रिंग स्वरूपण | __format__(self, formatstr) | "Hi {:abc}".format(a1) |
हैशिंग | __hash__(self) | hash(a1) |
लंबाई | __len__(self) | len(a1) |
औंधा | __reversed__(self) | reversed(a1) |
मंज़िल | __floor__(self) | math.floor(a1) |
अधिकतम सीमा | __ceil__(self) | math.ceil(a1) |
संदर्भ प्रबंधकों के लिए विशेष तरीके __enter__
और __exit__
भी हैं, और कई और।