How can I find the value of an arbitrary variable in Enclosed namespace in Python

Viewed 49

Python has several built-in functions and magic dictionaries that let me examine the value of a variable with an arbitrary name. locals()['foo'] yields the value of the local variable named foo; globals()['foo'] yields the value of that name at global scope. If I have a class instance x, I can look at x.__dict__ to see the values of instance variables.

I can't seem to find any way to leverage Python's LEGB name evaluation mechanism to find the value of an arbitrarily named variable in the "closest" scope.

def foo(cmd: str, b: str, c=None, d=None, e=None):
    req_x = {'c', 'd'}
    req_y = {'c', 'e'}
    if cmd == 'x':
        data = {name: locals()[name] for name in req_x}
    elif cmd == 'y':
        data = {name: locals()[name] for name in req_y if locals()[name] in b}

This doesn't work, because locals() within a comprehension is scoped to that comprehension. The variables in foo, including parameters, are in the Enclosed scope; not Local, not Global, not Built-in. Python itself can search the enclosed scopes; the reference to b in the second comprehension is legal and well-defined.

What would I use in place of locals()[name] to get the value of a variable with that name according to LEGB search rules?

("Capture the value of locals() outside the comprehension and reference the copy inside the comprehension" is a useful workaround, but it's not an answer to my question.)

1 Answers

I'm not entirely sure why it is happening, but I would guess that it is because your query is hard-coded to use :name as the parameter name, which is different than the one that SQLAlchemy would have chosen. You can override the parameter name by using the bindparam construct:

@classmethod
def get_by_name(cls, name):
    sql = '''
    SELECT first_name, last_name FROM dbo.[user] WHERE username = :username
    '''
    obj = DBSession.query(cls).from_statement(text(sql)).params(
        username=name.encode()).first()
    return obj
Related