I'm confused when working with nested classes in python. In the code below, I can't access the attribute 'A' defined in 'Outer' class from 'Inner' class - the statement 'B = Outer.A' will raise a 'NameError: name 'Outer' is not defined' error. However, I can access the attribute 'A' if and only if I call it inside a function 'foo_working' from the inner class, and it won't work if I define it in the way of 'foo_not_working'.
It seems I miss some important concept about scope here. I would really appreciate if someone can help explain.
class Outer:
A = 'from outer'
class Inner:
B = Outer.A
@staticmethod
def foo_working():
print(Outer.A)
@staticmethod
def foo_not_working(something=Outer.A):
print(something)
Updates:
Here is where the issue originated from - I'm working with SQLAlchemy where all the tables are defined as classes, and I would like to wrap them into a parent class such as 'MyTables' so it's easier to be managed and imported to other script. I would also like to define the associations in 'MyTables' class and allow some table class to call as 'secondary' in 'relationship' function. However, because of the issue above I can't achieve this (as the reason explained by @Barmar) unless I define all table class at a module level.
I'm new to SQLAlchemy and wonder if there is a solution for it?
- not working
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy import create_engine, Column, Integer, Text
from sqlalchemy import Table, ForeignKey
class MyTables:
Base = declarative_base()
_user_order = Table(
'_user_order', Base.metadata,
Column('user_id', ForeignKey('user.user_id'), primary_key=True),
Column('order_id', ForeignKey('order.order_id'), primary_key=True)
)
class User(Base):
__tablename__ = 'user'
user_id = Column(Integer, primary_key=True)
user_name = Column(Text)
class Order(Base):
__tablename__ = 'order'
order_id = Column(Integer, primary_key=True)
order_name = Column(Text)
users = relationship('User', secondary=_user_order, backref='orders')
database_path = 'sqlite:///../data/database.db'
engine = create_engine(url=database_path, echo=False, future=True)
Base.metadata.create_all(engine)
- working
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy import create_engine, Column, Integer, Text
from sqlalchemy import Table, ForeignKey
Base = declarative_base()
_user_order = Table(
'_user_order', Base.metadata,
Column('user_id', ForeignKey('user.user_id'), primary_key=True),
Column('order_id', ForeignKey('order.order_id'), primary_key=True)
)
class User(Base):
__tablename__ = 'user'
user_id = Column(Integer, primary_key=True)
user_name = Column(Text)
class Order(Base):
__tablename__ = 'order'
order_id = Column(Integer, primary_key=True)
order_name = Column(Text)
users = relationship('User', secondary=_user_order, backref='orders')
database_path = 'sqlite:///../data/database.db'
engine = create_engine(url=database_path, echo=False, future=True)
Base.metadata.create_all(engine)