How do you make issubclass work

N

Nathan Bullock

Okay I have two files:

a.py:
-----
class cla_a(object): pass

class cla_c(object): pass

if __name__ == "__main__":
mod = __import__("b")
attr = getattr(mod, "cla_b")
print issubclass(attr, cla_a)
print issubclass(cla_c, cla_a)
-----

and b.py:
-----
from a import cla_a

class cla_b(cla_a): pass
-----

now if I do 'python a.py'
it gives me:
False
True

Why is cla_b a subclass and not cla_c?

I think that it has something to with the fact that cla_b is a
subclass of a different instance of cla_a or something like that. But
if that is the case how do I do this sort of thing in python?

Nathan Bullock

http://bullock.mooo.com
 
P

Peter Otten

Nathan said:
Okay I have two files:

a.py:
-----
class cla_a(object): pass

class cla_c(object): pass

if __name__ == "__main__":
mod = __import__("b")
# why not
import b as mod
attr = getattr(mod, "cla_b")

# why not
attr = mod.cla_b
print issubclass(attr, cla_a)
print issubclass(cla_c, cla_a)
-----

and b.py:
-----
from a import cla_a

class cla_b(cla_a): pass
-----

now if I do 'python a.py'
it gives me:
False
True

Should be:
True
False
Why is cla_b a subclass and not cla_c?

Here you have it right again.

That you have two different modules does not affect the class hierarchy.
Y is a subclass of X if X can be found in the inheritance tree of Y, i. e.
occurs directly in Y's bases
True

or indirectly in the bases' bases:
(False, False)

So you can think of subclasses as children and grandchildren, but not as
cousins.

[As modules are cached, subsequent imports of the same module yield the same
module instance. Therefore the same classes (cla_a is cla_a == True) are
seen by all parts of a program and it (normally) doesn't matter in what
module a class is defined.]

Peter
 
N

Nathan Bullock

I think my first post was a little unclear. I will try again.

I have two files, the first is this:

File b.py:
-------------------
from a import cla_a

class cla_b(cla_a): pass
-------------------


File a.py
-------------------
class cla_a(object): pass

class cla_c(cla_a): pass

if __name__ == "__main__":
import b as mod
print issubclass(mod.cla_b, cla_a)
print issubclass(mod.cla_b, mod.cla_a)
print issubclass(cla_c, cla_a)
print mod.cla_a is cla_a
-------------------

Results of 'python a.py'

False
True
True
False


-----------------------------

This is using python 2.3.3. Is this a bug? Why do we have two
different cla_a's which are not the same? And do to this problem how
in the world do I determine if a cla_b is a subclass of cla_a?
Obviously they are, but issubclass doesn't realize it because the
cla_a that I am testing with is not the same instance of cla_a as
cla_b was derived from.
[As modules are cached, subsequent imports of the same module yield the same
module instance. Therefore the same classes (cla_a is cla_a == True) are
seen by all parts of a program and it (normally) doesn't matter in what
module a class is defined.]

Peter

Now I take it from this answer from Peter, that if I did the test in a
third file so that I was using an imported instance of cla_a that
issubclass would then work properly.

Nathan
 
A

Andrew Dalke

Nathan said:
This is using python 2.3.3. Is this a bug? Why do we have two
different cla_a's which are not the same?

Your file 'a.py' is two things. It's the code being used
as the "__main__" module *and* it's used as the "a" module.

Add this to your a.py:__main__ to see the difference.

import sys
main_module = sys.modules["__main__"]
print "main is from", main_module.__file__
a_module = sys.modules["a"]
print "a is from", a_module.__file__
print "Are the modules the same?", a_module == main_module
print "Are the classes the same?", a_module.cla_a ==
main_module.cla_a

You'll see that the file a.py is used twice, and the
class cla_a defined once as __main__.cla_a and the other
as a.cla_a .

To make what you want work, well, a good rule is to avoid
circular imports. Another is that your main code should
not be imported. But if you want so see your code to work
as you expect it to work, you need to change b.py so that
the "from a import cla_a" is instead
"from __main__ import cla_a"

Now I take it from this answer from Peter, that if I did the test in a
third file so that I was using an imported instance of cla_a that
issubclass would then work properly.

It should.

Andrew
(e-mail address removed)
 
A

Alex Martelli

Andrew Dalke said:
To make what you want work, well, a good rule is to avoid
circular imports. Another is that your main code should
not be imported. But if you want so see your code to work
as you expect it to work, you need to change b.py so that
the "from a import cla_a" is instead
"from __main__ import cla_a"

I would suggest a different workaround if it's important that module
a.py be runnable as main _and_ importable as a without getting two
copies: start a.py with the incantation...

import sys
if __name__!='a': sys.modules[a]=sys.modules[__name__]


After this, if any other module should 'import a', it WILL get the
module from a.py, not a separate copy. This won't solve everything, by
a long shot (circular imports _are_ trouble, period), but it will at
least remove the single issue of the "two modules from the same a.py
source file"...!


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top