2015-05-13 6 views
18

आप कैसे हैं "अक्षम" __call__ एक उपवर्ग पर विधि तो निम्न बात लागू होगा:एक अजगर उपवर्ग uncallable बनाने के लिए

class Parent(object): 
    def __call__(self): 
     return 

class Child(Parent): 
    def __init__(self): 
     super(Child, self).__init__() 
     object.__setattr__(self, '__call__', None) 

>>> c = Child() 
>>> callable(c) 
False 

यह और कुछ गैर प्रतिदेय को __call__ सेट करने का प्रयास करने के अन्य तरीकों मूल्य अभी भी बच्चे को कॉल करने योग्य के रूप में दिखाई देता है।

+7

यह प्रश्न पूछता है, क्या यह एक अच्छा वर्ग है कि बच्चे वर्ग में अभिभावक वर्ग के इंटरफेस को तोड़ना अच्छा विचार है? –

+1

'कॉल करने योग्य (ओबीजे) 'चेक' हैशटर (ओबीजे,' __call __ ') '; मुझे नहीं लगता कि आप 'चाइल्ड' को विशेषता नहीं दे सकते हैं, क्योंकि यह विरासत तोड़ देगा। – jonrsharpe

+1

क्या यह '__call__' संदर्भ' del' पर काम करेगा? – TigerhawkT3

उत्तर

14

आप नहीं कर सकते। जैसा कि जोनशर्प बताते हैं, Child को विशेषता नहीं है, और callable(Child()) इसका उत्तर देने के लिए निर्भर करता है। यहां तक ​​कि AttributeError उठाए जाने वाले एक वर्णक को भी यह काम नहीं करेगा, इस बग रिपोर्ट के अनुसार: https://bugs.python.org/issue23990। एक अजगर 2 उदाहरण:

>>> class Parent(object): 
...  def __call__(self): pass 
... 
>>> class Child(Parent): 
...  __call__ = property() 
... 
>>> c = Child() 
>>> c() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: unreadable attribute 
>>> c.__call__ 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: unreadable attribute 
>>> callable(c) 
True 

इसका कारण यह है callable(...) वर्णनकर्ता प्रोटोकॉल बाहर काम नहीं करता है। असल में ऑब्जेक्ट को कॉल करना, या __call__ विशेषता का उपयोग करना, सामान्य डिस्क्रिप्टर प्रोटोकॉल के माध्यम से, किसी संपत्ति के पीछे होने पर भी विधि को पुनर्प्राप्त करना शामिल है। लेकिन callable(...) अब तक जाने से परेशान नहीं है, अगर इसे कुछ भी मिल जाए तो यह संतुष्ट है, और माता-पिता के प्रत्येक उप-वर्ग में __call__ के लिए होगा - या तो सबक्लास में एक विशेषता, या Parent की परिभाषा।

तो जब आप वास्तव में किसी भी अपवाद के साथ उदाहरण को कॉल कर सकते हैं, तो आप कभी भी callable(some_instance_of_parent) वापस झूठ नहीं बना सकते हैं।

+0

अधिक तर्क को उत्तर में लाने के लिए उपयोगी हो सकता है, यह ध्यान में रखते हुए कि '__call__ = property()' 'हैट्टर (चाइल्ड(), '__call __') 'वापसी' गलत होगा, लेकिन 'कॉल करने योग्य' को प्रभावित नहीं करेगा यह एक विशेषता के लिए, उदाहरण नहीं, वर्ग की जांच करता है। – jonrsharpe

+0

@jonrsharpe ऐसा हो गया। यह कैसा दिखता है –

+0

अच्छा लगता है, धन्यवाद! – jonrsharpe

1

कक्षा के सार्वजनिक इंटरफ़ेस को मूल रूप से मूल से मूल तक बदलने का बुरा विचार है।

जैसा कि कहीं और बताया गया है, आप cant uninherit __call__। यदि आपको वास्तव में कॉल करने योग्य और गैर कॉल करने योग्य कक्षाओं में मिश्रण करने की आवश्यकता है तो आपको किसी अन्य परीक्षण (कक्षा विशेषता जोड़ने) का उपयोग करना चाहिए या किसी भी कार्यक्षमता वाले वेरिएंट को कॉल करने के लिए इसे सुरक्षित बनाना चाहिए।

बाद करने के लिए, आप NotImplemented (या बेहतर, अपने खुद के एक कस्टम अपवाद) को बढ़ाने के लिए __call__ रद्द कर सकते थे अगर किसी कारण से आप प्रतिदेय वेरिएंट के साथ में एक गैर प्रतिदेय वर्ग मिश्रण करना चाहता था:

class Parent(object): 
    def __call__(self): 
     print "called" 

class Child (Parent): 
    def __call__(self): 
     raise NotACallableInstanceException() 

for child_or_parent in list_of_children_and_parents(): 
    try: 
     child_or_parent() 
    except NotACallableInstanceException: 
     pass 

या, बस पास के साथ फोन ओवरराइड:

class Parent(object): 
    def __call__(self): 
     print "called" 

class Child (Parent): 
    def __call__(self): 
     pass 

कौन सा अभी भी प्रतिदेय होगी, लेकिन सिर्फ एक nullop हो।

+0

टिप्पणियों के अनुसार, इनमें से कोई भी 'कॉल करने योग्य' – jonrsharpe

+0

सत्य के परिणाम को प्रभावित नहीं करता है। ओपी का इरादा लगता है ... गलत ... – theodox

+0

यह दर्शाता है कि ... – theodox

संबंधित मुद्दे