tags:

views:

95

answers:

4

I have a python code like this.

File named mymodule.py

class MyBase(object):
    pass

File named data.py

from mymodule import MyBase

class A:
    class NestA(MyBase):
        pass
    class NestB(MyBase):
        pass

class B:
    class NestA(MyBase):
        pass
    class NestB(MyBase):
        pass

if I have a = A.NestA (not it is referring to a class, a is not the object of class NestA but the class itself) how do I find out what nested class hierarchy does a belong to? a.name gives me NestA so that is not a problem. I want to find out what outer class NestA is part of, i.e class A or class B. How do I do it?

A: 

Maybe you want this:

if a is A.NestA:
    print 'A.NestA'

if a is B.NestA:
    print 'B.NestA'

It is not possible to implement it in a more generic way. E.g. The class object in variable a does not contain the information on its container object by default. If you add a reference to the container later, then you would create a reference loop, which is not a good idea IMHO.

fviktor
Not really. I am building a dictionary of this hierarchy. I will not be knowing any thing before about the hierarchy until run time. Thanks for your answer though. Thinking of storing this as an attribute in the inner class itself now.
Madhusudan.C.S
You can do it more generically. One way is using the inspect module. See my answer for details.
Ryan Ginstrom
A: 

You can do something like this with metaclass programming.

class SetOuterClassType(type):
    def __init__(cls, name, bases, attrs):
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, '__set_outerclass__', False):
                attrvalue.__outerclass__ = cls

class OuterClassSetter(object):
    __metaclass__ = SetOuterClassType

class MyBase(object):
    @classmethod
    def fullname(cls):
        if hasattr(cls,'__outerclass__'):
            return '%s.%s' % (
                cls.__outerclass__.__name__, cls.__name__ )
        else:
            return '%s' % cls.__name__


class A(OuterClassSetter):
    class NestA(MyBase):
        __set_outerclass__ = True
    class NestB(MyBase):
        __set_outerclass__ = True


class B(OuterClassSetter):
    class NestA(MyBase):
        __set_outerclass__ = True

    class NestB(MyBase):
        __set_outerclass__ = True

print A.NestA.fullname() # prints 'A.NestA'
print A.NestB.fullname() # prints 'A.NestB'
print B.NestA.fullname() # prints 'B.NestA'
print B.NestB.fullname() # prints 'B.NestB'
Matt Anderson
+1  A: 

What you are asking for is a result of bad design. My advise to you is to redefine your solution.

prime_number
Not necessarily. This is what introspection is all about. The OP hasn't given details about the design, but I can imagine cases where this would be valid.
Ryan Ginstrom
+1  A: 

You can do this with the inspect module:

import inspect

a = A.NestA

print a in [x[1] for x in inspect.getmembers(A, inspect.isclass)]
print a in [x[1] for x in inspect.getmembers(B, inspect.isclass)]

Result:

True
False

Addendum:

If you don't know anything about the classes in the module, you can backtrack and get the module.

# for each class in a's module...
for klass in inspect.getmembers(inspect.getmodule(a), inspect.isclass):
    # see if a is in that class
    if a in [x[1] for x in inspect.getmembers(klass[1], inspect.isclass)]:
        print a, "is a member of", klass[0]

Result:

__main__.NestA is a member of A
Ryan Ginstrom