简体   繁体   中英

forward declaration on python vs using globals()

I have a global dict like this :

mydict = {
   "name1" : {
       "description"   : "random text 1" ,
       "function_name" : foo
    }
}

This is a global function in a module that doesn't have a if __name__ == "__main__":

That means that I need to declare the foo before I reference it - from what I have tried. Otherwise when I run my code I get 'foo' is not defined .

Later in one of my other function what i want to do is something like :

def randomCaller() :
   # ....
   mydict[ "name1" ][ "function_name"]()

Since I don't want to change how the file is structured - an alternative that I have is to use the name and change the above code into :

mydict = {
   "name1" : {
       "description"   : "random text 1" ,
       "function_name" : "foo"
    }
}
def randomCaller() :
   # ....
   fname = mydict[ "name1" ][ "function_name"]
   globals()[ fname ]()

Is there any concern/risk on the above? Would you suggest something different?

@MarkMeyer came up with a great workaround for this in the comments:

"function_name": lambda *args, **kwargs: foo(*args, **kwargs)

(the arguments can be whatever you need them to be. This is the most flexible arrangement, but if you know foo() will use a certain set of arguments you can arrange the lambda to mirror that).

Ordinarily, this type of use of a lambda would be pretty useless ("why not just call foo in the first place?"). However, in this particular use case, it's uniquely useful, because the name foo is only evaluated when the lambda is called, and not when it's assigned.

In other words, this works on my python console:

>>> f1 = lambda: foo()
>>> f1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
NameError: name 'foo' is not defined
>>> def foo():
...     print("Hello World!")
...
>>> f1()
Hello World!

That said, this solution is hacky, and might play weirdly with namespaces. The best way to handle the problem would be to just define foo() before defining mydict , but if you absolutely must declare mydict first, you could also simply declare "function_name": None initially, and then set it to foo() after you've defined foo() :

mydict = {
    "name1" : {
       "description"   : "random text 1" ,
       "function_name" : None
    }
}
...
def foo():
    ...
mydict["name1"]["function_name"] = foo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM