I am new to Python and want to create classes/structures similar to c++ but I have problems understanding what python actually does
from dataclasses import dataclass
class innerClass:
x: int
class outerClass:
a: innerClass
b: str
c: str
test_1 = outerClass()
def setTest(val):
global test_1
test_1.x=val
def getTest():
z=1
global test_1
if z==1:
setTest(z)
return [test_1.x]
getTest()
If I change the value of z to z=0 then it has the following issue
Traceback (most recent call last):
File "simplePy.py", line 27, in <module>
getTest()
File "simplePy.py", line 25, in getTest
return [test_1.x]
AttributeError: 'outerClass' object has no attribute 'x'
so I have two questions
- how does it access x with only test_1.x? I would expect it to be test_1.a.x as outerClass->innerClass->variable
- as it worked with
z=1why does it complain about x not being an attribute withz=0? I was expecting it to return either rubbish value or zero
2 Answers 2
I think the main problem is that outerClass has no x. You should call outerClass.inner.x.
You also forgot to use the dataclass decorator in your classes. Without it, they behave like regular classes and you'd need to define an __init__.
Furthermore, the globals are not doing anything. A variable must be defined as global if you want to re-assign it, eg test_1 = None, but you can re-assign its attributes without the global keyword.
Here's my version of the code:
from dataclasses import dataclass
@dataclass
class InnerClass:
x: int
@dataclass
class OuterClass:
inner: InnerClass
a: str
b: str
c: str
outter_instance = OuterClass(inner=InnerClass(x=0), a="a", b="b", c="c")
print(outter_instance.inner.x)
outter_instance.inner.x = 5
print(outter_instance.inner.x)
Some things I did:
- use the dataclass decorator
- use PascalCase in classes names, which is the standard in Python
- rename some attributes to make them clearer, eg
outter_instanceandOutClass.inner - remove the functions and run everything in the module
Finally, you can also do this without dataclasses:
class InnerClass:
def __init__(self, x: int):
self.x = x
class OuterClass:
def __init__(self, inner: InnerClass, a:str, b:str, c:str):
self.inner = inner
self.a = a
self.b = b
self.c = c
outter_instance = OuterClass(inner=InnerClass(x=0), a="a", b="b", c="c")
print(outter_instance.inner.x)
outter_instance.inner.x = 5
print(outter_instance.inner.x)
Comments
- How does it access x with only test_1.x? I would expect it to be test_1.a.x as outerClass->innerClass->variable
When you call setTest(z) it creates the test_1.x attribute. Python doesn't normally prevent you from creating new attributes in an object (it's possible to prevent this, but it's not the default).
- as it worked with z=1 why does it complain about x not being an attribute with z=0? I was expecting it to return either rubbish value or zero
With z = 0 you never call setTest(), so the x attribute is never added to the object. So you get an error when you try to access it.
6 Comments
test_1.a.x=val I get AttributeError: 'int' object has no attribute 'x'test_1.a to an InnerClass instance. You need test_1 = OuterClass(InnerClass(0), 0, 0)
@dataclassdecorators.global test_1, since neither of the function assigns the variable.