How do I write a function to run a function and return uniquely named outer-scope variables?

Tags: ,



I need to run one function multiple times where 3 out of 5 arguments stay the same every time. How can I write a function to just take the unique arguments as inputs and return the outputs of the inner function as unique variables?

The function I’m trying to run is part of SQLalchemy:

sales = Table('sales', metadata, autoload=True, autoload_with=engine, schema=None)

The first argument, table name, is always different and should also be the name of the variable. The last argument will be different sometimes.

My idea was to create a dictionary with table_name: schema_name and pass it to a function that loops through the dictionary and runs the Table function.

table_names = {'sales': None, 'orders': None, 'customers': 'cust_data'}

def represent_tables(tables: dict):
   for table, schema in tables:
       nonlocal exec(table)
       exec(table) = Table(table, metadata, autoload=True,
                           autoload_with=engine, schema=schema)

represent_tables(table_names)

I guess there are two questions here. Firstly, how do I name a new variable using the string contained in another variable? Secondly, how can I return a variable from a function so that it can be called later on?

Answer

You generally don’t want to dynamically create variables. Use a data structure like a dictionary instead.

How can I write a function to just take the unique arguments as inputs and return the outputs of the inner function as unique variables?

You can create a function that pulls the required objects from your current scope and just returns a Table instance:

engine = create_engine(...)
metadata = MetaData()

def create_table(name, schema=None):
    return Table(name, metadata, autoload=True, autoload_with=engine, schema=schema)

You can then create a dictionary of tables:

tables = {
    'sales': create_table('sales'),
    'orders': create_table('orders'),
    'customers': create_table('customers', schema='cust_data'),
}

If you want less repetition at the cost of readability, you can use a dictionary comprehension to create your tables from an object describing the tables:

table_schemas = {
    'sales': None,
    'orders': None,
    'customers': 'cust_data',
}

tables = {
    name: create_table(name, schema)
    for name, schema in table_schemas.items()
}

SQLAlchemy also has a Metadata.reflect() method that may be useful.



Source: stackoverflow