WorldSEnder
WorldSEnder

Reputation: 5044

An object that describes the current scope

An API I use defines a method like this:

def show_prop(object, propname): #...

What it's supposed to do is display the property on screen by calling getattr(object, propname) and allow the user to change the attribute, resulting in setattr(object, propname).

There is no way I can change that behaviour but I want to use the API to show a local variable to the user and receive the normal feedback from the user?

I thought of a builting variable describing the current scope and the variables available, kind of like a local __dict__ but I haven't found such thing.

userinput = "Default input"
show_prop(__mysterious_unknown__, 'userinput')
# Do something exciting with the changed userinput

Is this possible to achieve?

Upvotes: 1

Views: 318

Answers (1)

6502
6502

Reputation: 114529

No. Local write access can be done only directly in the scope or in nested scopes using nonlocal (Python3 only).

Python doesn't have the concept of "pointer" and the only way to specify a writable place is passing a reference to the container and the "name" of the member (or the index of the array, the key of the dict).

What you can do is however create a small object on the fly just for this:

class Bunch:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

def foo():
    my_local = 42
    ...
    myobj = Bunch(my_local=my_local) # create the dummy instance
    show_prop(myobj, "my_local")     # call the original code
    my_local = myobj.my_local        # get modified value back
    ...

In Python3 would be possible to create a magic object instance that when written to the member will mutate the local on the fly (using the new Python3 nonlocal keyword and either a property or a __getattr__/__setattr__ catch-all). I wouldn't go for this kind of strange magic unless it's really needed however...

For example:

def foo(obj, name):
    # the fixed API
    setattr(obj, name, 1 + getattr(obj, name))

def bar():
    myloc = 11

    # magic class...
    class MyClass:
        def __getattr__(self, name):
            # accessing any member returns the current value of the local
            return myloc
        def __setattr__(self, name, value):
            # writing any member will mutate the local (requires Python3)
            nonlocal myloc
            myloc = value

    foo(MyClass(), "myloc")
    print(myloc) # here myloc will have been incremented

bar()

Upvotes: 1

Related Questions