2009-03-12 17 views
5

मान लीजिए कि आपके पास एक पाइथन विधि है जो पैरामीटर के रूप में एक प्रकार प्राप्त करती है; क्या यह निर्धारित करना संभव है कि दिया गया प्रकार एक नेस्टेड क्लास है या नहीं?
उदा। इस उदाहरण में:पायथन: निर्धारित करें कि कोई वर्ग नेस्टेड

def show_type_info(t): 
    print t.__name__ 
    # print outer class name (if any) ... 

class SomeClass: 
    pass 

class OuterClass: 
    class InnerClass: 
     pass 

show_type_info(SomeClass) 
show_type_info(OuterClass.InnerClass) 

मैं show_type_info(OuterClass.InnerClass) करने के लिए कॉल की तरह भी पता चलता है कि InnerClass OuterClass अंदर परिभाषित किया गया है जाएगा।

+0

स्वयं के साथ क्या गलत है .__ वर्ग __.__ name__? इस जानकारी के लिए आपके पास क्या उद्देश्य है? –

+0

@ एसएलओटी: "आप के साथ क्या गलत है .__ वर्ग __.__ name__" के साथ आपका क्या मतलब है? क्षमा करें, मुझे आपके प्रश्न को समझ में नहीं आता है ... –

+0

@orsogufo: "गलत" क्या है - काम नहीं करता - उचित नहीं है - मदद नहीं करता - टूटा हुआ है - क्या नहीं करता आप चाहते हैं - सही प्रारूप में नहीं है - स्वयं के साथ "गलत" .__ वर्ग __.__ name__? उसके साथ कुछ सही नहीं है, लेकिन मुझे नहीं पता कि आपको क्या पसंद नहीं है। कृपया स्पष्ट करें। –

उत्तर

12

AFAIK, एक वर्ग और कोई अन्य जानकारी नहीं दी गई है, आप यह नहीं बता सकते कि यह एक नेस्टेड क्लास है या नहीं। हालांकि, see here यह निर्धारित करने के लिए कि आप सजावट का उपयोग कैसे कर सकते हैं।

समस्या यह है कि एक नेस्टेड क्लास बस एक सामान्य वर्ग है जो इसकी बाहरी कक्षा का गुण है। अन्य समाधान जो आप संभवतः काम करने की उम्मीद कर सकते हैं - inspect.getmro, उदाहरण के लिए, केवल आपको बेस क्लास नहीं देता है, न कि बाहरी कक्षाएं।

इसके अलावा, नेस्टेड कक्षाओं की शायद ही कभी आवश्यकता होती है। मैं दृढ़ता से पुनर्विचार करता हूं कि यह प्रत्येक विशेष मामले में एक अच्छा दृष्टिकोण है जहां आप एक का उपयोग करने के लिए प्रलोभन महसूस करते हैं।

+0

+1 यह अच्छी सलाह है। –

+0

धन्यवाद, आपका उत्तर स्वीकार कर लिया: बिंदु यह तथ्य है कि एक घोंसला वर्ग बाहरी की विशेषता है। पीएस: मुझे यकीन है कि नेस्टेड कक्षाओं के हमेशा विकल्प होते हैं, लेकिन मैं नहीं देख सकता कि उन्हें एक बुरा विचार क्यों होना चाहिए। –

5

एक आंतरिक कक्षा पायथन में कोई विशेष विशेष विशेषताएं प्रदान नहीं करती है। यह केवल क्लास ऑब्जेक्ट की एक संपत्ति है, पूर्णांक या स्ट्रिंग प्रॉपर्टी से अलग नहीं है। आपका OuterClass/InnerClass उदाहरण बिल्कुल के रूप में फिर से लिखा जा सकता है:

class OuterClass(): pass 
class InnerClass(): pass 
OuterClass.InnerClass= InnerClass 

InnerClass, पता नहीं कर सकते हैं कि क्या यह एक और वर्ग के अंदर घोषित किया गया था, क्योंकि वह सिर्फ एक सादे बाध्यकारी चर है। जादू जो बाध्यकारी विधियों को अपने मालिक 'स्वयं' के बारे में जानता है, यहां लागू नहीं होता है।

जॉन पोस्ट किए गए लिंक में आंतरिक क्लास सजावट जादू एक दिलचस्प दृष्टिकोण है लेकिन मैं इसका उपयोग नहीं करता। यह कक्षाएं यह प्रत्येक बाहरी वस्तु के लिए बनाता है कैश नहीं है, इसलिए यदि आप एक नए InnerClass, प्रत्येक बार जब आप outerinstance.InnerClass फोन:

>>> o= OuterClass() 
>>> i= o.InnerClass() 
>>> isinstance(i, o.InnerClass) 
False # huh? 
>>> o.InnerClass is o.InnerClass 
False # oh, whoops... 

इसके अलावा जिस तरह से यह बाहरी वर्ग चर बनाने का जावा व्यवहार को दोहराने की कोशिश करता है गेटैटर/सेटैटर के साथ भीतरी कक्षा में उपलब्ध बहुत ही कमजोर है, और वास्तव में अनावश्यक है (क्योंकि अधिक पाइथोनिक तरीका मुझे .__ बाहरी __। स्पष्ट रूप से कॉल करना होगा)।

0

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

4

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

जैसे:

import inspect 

def not_toplevel(cls): 
    m = inspect.getmodule(cls) 
    return not (getattr(m, cls.__name__, []) is cls) 

यह आम मामलों के लिए काम करेंगे, लेकिन यह क्या आप स्थितियों में, जहां कक्षाएं नाम दिया जाता है या अन्यथा परिभाषा के बाद चालाकी में चाहते हैं नहीं कर सकते। उदाहरण के लिए:

class C:    # not_toplevel(C) = False 
    class B: pass # not_toplevel(C.B) = True 

B=C.B    # not_toplevel(B) = True 

D=C     # D is defined at the top, but... 
del C    # not_toplevel(D) = True 

def getclass():  # not_toplevel(getclass()) = True 
    class C: pass 
1

आपके उत्तरों के लिए धन्यवाद।
मुझे मेटाक्लास का उपयोग करके यह संभावित समाधान मिला है; मैंने वास्तविक आवश्यकता से बाधा के लिए इसे और अधिक किया है, और यह इस तरह से किया जाता है जो पायथन 3 पर लागू नहीं होगा।
मैं इस समाधान को वैसे भी साझा करना चाहता हूं, इसलिए मैं इसे यहां पोस्ट कर रहा हूं।

#!/usr/bin/env python 
class ScopeInfo(type): # stores scope information 
    __outers={} # outer classes 
    def __init__(cls, name, bases, dict): 
     super(ScopeInfo, cls).__init__(name, bases, dict) 
     ScopeInfo.__outers[cls] = None 
     for v in dict.values(): # iterate objects in the class's dictionary 
      for t in ScopeInfo.__outers: 
       if (v == t): # is the object an already registered type? 
        ScopeInfo.__outers[t] = cls 
        break; 
    def FullyQualifiedName(cls): 
     c = ScopeInfo.__outers[cls] 
     if c is None: 
      return "%s::%s" % (cls.__module__,cls.__name__) 
     else: 
      return "%s.%s" % (c.FullyQualifiedName(),cls.__name__) 

__metaclass__ = ScopeInfo 

class Outer: 
    class Inner: 
     class EvenMoreInner: 
      pass 

print Outer.FullyQualifiedName() 
print Outer.Inner.FullyQualifiedName() 
print Outer.Inner.EvenMoreInner.FullyQualifiedName() 
X = Outer.Inner 
del Outer.Inner 
print X.FullyQualifiedName() 
संबंधित मुद्दे