How can I pass my locals and access the variables directly from another function?

。_饼干妹妹 提交于 2019-11-27 07:02:33

问题


Let's say I have this :


def a(dict):
  locals().update(dict)
  print size

def b():
  size = 20
  f(locals())

What do I have to do to access the size variable directly from the a function? I know of :


size = dict["size"]

but I think there should be a more direct way. I tried using locals().update(dict) but it didn't work. Is there a betteer way ?


回答1:


The Python compiler optimizes access to local variables by recognizing at compile time whether the barenames a function is accessing are local (i.e., barenames assigned or otherwise bound within the function). So if you code:

def lv1(d):
  locals().update(d)
  print zap

the compiler "knows" that barename zap is NOT local (not assigned in function lv1) and so it compiles code to access it as a global instead -- whatever d contains won't matter.

If you prefer slow and bloated code, you can defeat the optimization by using an exec inside the function -- when the compiler sees the keyword exec, it KNOWS you're trying to make your code as slow, bloated and buggy as possible, and so it cooperates by not optimizing in any way, just about.

So, the following code works as you desire:

def lv1(d):
  exec ""
  locals().update(d)
  print zap

lv1({'zap': 23})

it emits 23 as you want.

I hope it's clear from the above "deadpan humor" that the technique is not recommended, but I'd better spell it out very explicitly: for the dubious syntactic pleasure of writing print zap in lieu of print locals()['zap'], you ARE paying a hefty price in terms of performance. Still, like all sorts of dangerous tools that can be useful in rare use cases for really experienced guru-level programmers who really truly know what they're doing and why, exec is there, available for you to use (or mis-use) at your whim: Python does NOT stand in your way!-)




回答2:


Is this helping you somehow?

def print_size(size=None):
    print(size)

dict = {'size': 'XXL'}
print_size(**dict)



回答3:


You can use closures to access the scope of another function:

def b():

  def a():
    print size

  size = 20
  a()

The trick is to stack functions which belongs together in each other. This way the inner function a can access the local variables of the outer function b.

But I don't know what you're really up to so I'm not sure if this helps.




回答4:


print size

cannot work, because "size" is not known when the code is compiled. Your code will work if you change it like this:

def a(dict):
    locals().update(dict)
    print locals()["size"]

def b():
    size = 20
    a(locals())

But as the comment to your question already suggests: This is very strange code. I'm very sure that there are better solutions, if you explain what you really want to do.




回答5:


I know, I know, the question is old and the accepted answer is already great.

Just adding two cents because it seems obvious but not mentioned: Make size local by assigning it a (default) value explicitly.

def a(dict):
    size = 20  # size default value <- quick (and dirty?) fix
    locals().update(dict)
    print (size)

def b():
    size = 20
    a(locals())

So, the added line (size = 20) in a() makes size be an actual local variable without the needing for exec, being python3 compatible and without the optimization drawback.

And how could that be useful???

Well, with that we can implement something like def f(x, *args, y=10) in python2 as that raises a syntax error in python2 but just works in python3:

def f(x, *args, **kwargs):
   y = 10
   locals().update(kwargs)
   print (x, y)

The example above works in python2 and python3



来源:https://stackoverflow.com/questions/1277519/how-can-i-pass-my-locals-and-access-the-variables-directly-from-another-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!