python - कैसे एक विधि के लिए एक उदाहरण के सदस्य के एक डिफ़ॉल्ट तर्क मान पारित करने के लिए?




instance-variables default-arguments (4)

"स्व" को किसी भी वर्ग के कार्यों के लिए पहले तर्क के रूप में पारित करने की आवश्यकता है यदि आप चाहते हैं कि वे गैर-स्थिर तरीकों के रूप में व्यवहार करें।

यह ऑब्जेक्ट को संदर्भित करता है। आप "स्व" को डिफ़ॉल्ट तर्क के रूप में पारित नहीं कर सकते क्योंकि यह स्थिति पहले तर्क के रूप में ठीक है।

आपके मामले में "फ़ॉर्मेटिंग = सेल्फफॉर्म" के बजाय "फ़ॉर्मेटिंग = कोई नहीं" का उपयोग करें और फिर नीचे दिए गए कोड से मान असाइन करें:

[संपादित करें]

class c:
        def __init__(self, cformat):
            self.cformat = cformat

        def process(self, formatting=None):
            print "Formating---",formatting
            if formatting == None:
                formatting = self.cformat
                print formatting
                return formatting
            else:
                print formatting
                return formatting

c("abc").process()          # prints "abc"
c("abc").process("xyz")     # prints "xyz"

नोट: "प्रारूप" को चर नाम के रूप में उपयोग न करें, क्योंकि यह अजगर में अंतर्निहित फ़ंक्शन है

मैं उदाहरण की विशेषता के मान का उपयोग करके इंस्टेंस विधि के लिए एक डिफ़ॉल्ट तर्क पास करना चाहता हूं:

class C:
    def __init__(self, format):
        self.format = format

    def process(self, formatting=self.format):
        print(formatting)

कोशिश करते समय, मुझे निम्न त्रुटि संदेश मिलता है:

NameError: name 'self' is not defined

मैं इस तरह से व्यवहार करने की विधि चाहता हूं:

C("abc").process()       # prints "abc"
C("abc").process("xyz")  # prints "xyz"

यहाँ क्या समस्या है, यह काम क्यों नहीं करता है? और मैं यह काम कैसे कर सकता था?


आप वास्तव में इसे डिफ़ॉल्ट मान के रूप में परिभाषित नहीं कर सकते हैं, क्योंकि डिफ़ॉल्ट मान का मूल्यांकन तब किया जाता है जब विधि परिभाषित की जाती है जो कि किसी भी उदाहरण से पहले होती है। सामान्य पैटर्न इसके बजाय कुछ इस तरह से करना है:

class C:
    def __init__(self, format):
        self.format = format

    def process(self, formatting=None):
        if formatting is None:
            formatting = self.format
        print(formatting)

self.format का उपयोग केवल तभी किया जाएगा यदि formatting None

डिफ़ॉल्ट मान कैसे काम करते हैं इस बिंदु को प्रदर्शित करने के लिए, इस उदाहरण को देखें:

def mk_default():
    print("mk_default has been called!")

def myfun(foo=mk_default()):
    print("myfun has been called.")

print("about to test functions")
myfun("testing")
myfun("testing again")

और यहाँ उत्पादन:

mk_default has been called!
about to test functions
myfun has been called.
myfun has been called.

गौर करें कि कैसे mk_default को केवल एक बार mk_default गया था, और फ़ंक्शन को कभी भी कॉल करने से पहले हुआ था!


चूंकि आप self.format को एक डिफ़ॉल्ट तर्क के रूप में उपयोग करना चाहते हैं, इसका मतलब यह है कि विधि को विशिष्ट होना चाहिए (यानी वर्ग स्तर पर इसे परिभाषित करने का कोई तरीका नहीं है)। इसके बजाय आप उदाहरण के लिए वर्ग __init__ दौरान विशिष्ट विधि को परिभाषित कर सकते हैं। यह वह जगह है जहां आपके पास विशिष्ट विशेषताओं को इंस्टाल करने की पहुंच है।

विधि के एक अद्यतन (विशिष्ट) संस्करण को प्राप्त करने के लिए एक functools.partial का उपयोग functools.partial

from functools import partial


class C:
    def __init__(self, format):
        self.format = format
        self.process = partial(self.process, formatting=self.format)

    def process(self, formatting):
        print(formatting)


c = C('default')
c.process()
# c.process('custom')  # Doesn't work!
c.process(formatting='custom')

ध्यान दें कि इस दृष्टिकोण के साथ आप केवल कीवर्ड द्वारा संबंधित तर्क पास कर सकते हैं, क्योंकि यदि आपने इसे स्थिति द्वारा प्रदान किया है, तो यह partial विरोध पैदा करेगा।

एक अन्य तरीका यह है कि __init__ में विधि को परिभाषित करना और सेट करना है:

from types import MethodType


class C:
    def __init__(self, format):
        self.format = format

        def process(self, formatting=self.format):
            print(formatting)

        self.process = MethodType(process, self)


c = C('test')
c.process()
c.process('custom')
c.process(formatting='custom')

यह तर्क को स्थिति से पारित करने की अनुमति देता है, हालांकि विधि संकल्प आदेश कम स्पष्ट हो जाता है (जो उदाहरण के लिए आईडीई निरीक्षण को प्रभावित कर सकता है, लेकिन मुझे लगता है कि आईडीई के लिए विशिष्ट वर्कआर्ड हैं)।

एक अन्य दृष्टिकोण एक विशेष डेकोरेटर के साथ इस तरह के "उदाहरण विशेषता डिफॉल्ट" के लिए एक कस्टम प्रकार बनाने के लिए होगा जो संबंधित getattr तर्क भरने का कार्य करता है:

import inspect


class Attribute:
    def __init__(self, name):
        self.name = name


def decorator(method):
    signature = inspect.signature(method)

    def wrapper(self, *args, **kwargs):
        bound = signature.bind(*((self,) + args), **kwargs)
        bound.apply_defaults()
        bound.arguments.update({k: getattr(self, v.name) for k, v in bound.arguments.items()
                                if isinstance(v, Attribute)})
        return method(*bound.args, **bound.kwargs)

    return wrapper


class C:
    def __init__(self, format):
        self.format = format

    @decorator
    def process(self, formatting=Attribute('format')):
        print(formatting)


c = C('test')
c.process()
c.process('custom')
c.process(formatting='custom')

पायथन में, self का नाम विशेष नहीं है । यह केवल पैरामीटर नाम के लिए एक सम्मेलन है, यही कारण है कि __init__ में एक self पैरामीटर है। (वास्तव में, __init__ बहुत विशेष भी नहीं है, और विशेष रूप से यह वास्तव में वस्तु नहीं बनाता है ... यह एक लंबी कहानी है)

C("abc").process() एक C आवृत्ति बनाता है, C श्रेणी में process विधि को देखता C , और उस विधि को पहले पैरामीटर के रूप में C उदाहरण के साथ कहता है। यदि आप इसे प्रदान करते हैं तो यह self पैरामीटर में समाप्त हो जाएगा।

यहां तक ​​कि अगर आपके पास वह पैरामीटर था, हालांकि, आपको def process(self, formatting = self.formatting) जैसी कोई चीज़ लिखने की अनुमति नहीं होगी, क्योंकि डिफ़ॉल्ट बिंदु निर्धारित करने के बाद self उस दायरे में नहीं आता है। पायथन में, पैरामीटर के लिए डिफ़ॉल्ट मान की गणना तब की जाती है जब फ़ंक्शन संकलित किया जाता है, और फ़ंक्शन के लिए "अटक" जाता है। (यही कारण है कि, यदि आप एक डिफ़ॉल्ट जैसे [] उपयोग करते हैं, तो वह सूची फ़ंक्शन के कॉल के बीच परिवर्तनों को याद रखेगी।)

मैं यह काम कैसे कर सकता हूं?

पारंपरिक तरीका यह है कि None डिफ़ॉल्ट के रूप में उपयोग न करें, और उस मूल्य की जांच करें और इसे फ़ंक्शन के अंदर बदलें। आप पा सकते हैं कि यह उद्देश्य के लिए एक विशेष मूल्य बनाने के लिए थोड़ा सुरक्षित है (एक object उदाहरण आप सभी की जरूरत है, जब तक आप इसे छिपाते हैं ताकि कॉलिंग कोड एक ही उदाहरण का उपयोग न करें) None बजाय। किसी भी तरह से, आपको इस मूल्य के लिए जांचना चाहिए, न कि ==





default-arguments