I have the following code:
def f():
class XYZ:
# ...
cls = type('XXX', (XYZ, ), {})
# ...
return cls
I am now using it as follows:
C1 = f()
C2 = f()
and it seems to work fine: C1 is C2 returns False, there’s no conflict between the class attributes of the two classes, etc.
Question 1
Why is that? How is it possible that C1 and C2 are both shown as class
<'__main__.XXX'>
and yet not the same class?
Question 2
Is there some problem with the fact that I have two identical names for two different classes?
Question 3
I would like to be able to write instead:
f('C1')
f('C2')
with the same effect. Is it possible?
Question 4
If I want C1 to look like a regular class, not main.XXX, is it ok to say:
C1.__name__ = '__main__.C1'
Question 3
To have
cls.__name__be anything you want, (with a nod to delnan’s suggestion)Question 1
The reason that
c1 is not c2is that they are two different objects stored at two different locations in memory.Question 4
Try an answer to question 1 and see how it works out for you
Question 2
It can complicate debugging that their class attributes
__name__share a common value and this is bad enough to take pains to avoid. (see question 3). I would maintain though that they don’t have the same name. One is namedC1and the other is namedC2(at least in the scope you are showing. If you were to pass them to a function, then there name in that scope would be the same as the name of parameter that they were passed through)In fact, I’m so sure that they don’t have the same name that trying to tell me otherwise is likely to cause me to turn the music up louder and pretend I can’t hear you.
In response to comment
It can be done but it’s just wrong. I’ll illustrate anyway because it’s illuminating:
This just works by sticking the class in the globals dict keyed by
clsname. But what’s the point? You can stick it in the globals dict under any name in fact because this is just another assignment. You are best off just returning the class from the function and letting the caller decide what name to give the class in it’s own scope. You still have the__name__attribute of the class set to the string you pass to the function for debugging purposes.