I'm sorry if I come across as incredibly stupid, I'm relatively new to python and I can not figure out what I am doing wrong here.
I have two classes, and I try to get the class names of both with
*class*.__class__.__name__
Now, as I said, this works for one class, but doesn't for another.
These are my classes:
class fb():
val = 300
mult = 2.0
shsym = pygame.image.load('img/dummy2.png')
value = 50
class a():
occ = 0
shsym = pygame.image.load('img/it/a/shsym.png')
plsym = pygame.image.load('img/it/a/plsym.png')
value = 100
hesyms = [pygame.image.load('img/a/hesym0',pygame.image.load('img/dummy.png'))]
coord = [(50, 300),(30, 435),(310, 350)]
The variables inside probably don't really matter but as I can't figure out the problem I just included the whole thing.
Then I define them
fob = fb()
ita = a()
Then I set a variable as one of the defined classes
itemselect = fob
And then, finally, I try to check the class' name and look if it begins with 'f' (to see if it is part of a group of items)
if not itemselect.__class__.__name__.startswith("f"):
And in that line I get the error message
Traceback (most recent call last):
File "D:\Programmieren\Cola Atsume\main.py", line 283, in <module>
if not itemselect.__class__.__name__.startswith("f"):
AttributeError: class fa has no attribute '__class__'
When itemselect is ita everything works just fine, but with fob it doesn't. I know I could do this differently, and my whole class system isn't really conventional and all but I don't really want to change it if I don't have to.
Note: This is grindy Python 2 stuff. In Python 3, things are different because in Python 3, every class is "new style" by default. New-Style classes themselves are also "simply" instances of their meta-class (often this meta-class is type
). This means that a class in Python 3 (and a Python 2 class inheriting from object
) in fact has a __class__
attribute (which carries its meta-class). Do not worry about meta-classes now.
When the error happens, itemselect
is a class, not an instance, which is why it doesn’t have a __class__
attribute.
You say that:
Then I set a variable as one of the defined classes
Exactly, and classes do not have a __class__
attribute. Only instances (also called objects) of classes have that attribute:
>>> class Foo:
... pass
...
>>> hasattr(Foo, "__class__")
False
>>> f = Foo()
>>> hasattr(f, "__class__")
True
>>> f.__class__ is Foo
True
You need to distinguish classes and objects strongly, because in most cases it is the wrong thing to do to mix those.
Also, you really, really, really should not be doing this. You can easily convert this to an issubclass-based check.
Create an empty class called f
:
class f:
pass
Now base all your classes whose name starts with f
on that class:
class fb(f):
val = 300
mult = 2.0
shsym = pygame.image.load('img/dummy2.png')
value = 50
And now, instead of doing the nasty .startswith
check, use issubclass
:
if issubclass(itemselect, f):
That is already a lot cleaner than checking for the first character in the name of a class.
Also, as a beginner nowadays, you really really really should not be using Python 2 and now you don’t have an excuse to use old-style classes either, because you know new-style exists. It will make porting your code and your mental model of how Python works to Python 3 easier.