खोज…


जादू / डंडर तरीके

पायथन में मैजिक (जिसे डबल-अंडरस्कोर के लिए एक संक्षिप्त नाम के रूप में भी कहा जाता है) अन्य भाषाओं में ओवरलोडिंग करने वाले ऑपरेटर के लिए एक समान उद्देश्य प्रदान करता है। वे एक वर्ग को अपने व्यवहार को परिभाषित करने की अनुमति देते हैं जब इसे एक संचालन के रूप में उपयोग किया जाता है। वे कुछ अंतर्निहित कार्यों द्वारा कार्यान्वित कार्यान्वयन के रूप में भी कार्य करते हैं।

दो आयामी वैक्टर के इस कार्यान्वयन पर विचार करें।

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__ भी हैं, और कई और।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow