python single integer variable between function

给你一囗甜甜゛ 提交于 2019-12-12 09:08:17

问题


Is there a way to exchange between child and parent functions a variable that is not a list?

#parent

list=[0]*1
singlevalue = 0

#child - 0
def test():
    list[0]= list[0]+1
    return list

#parent
test() #>>1 
test() #>>2


#child - 1
def test():
    singlevalue = singlevalue +1
    return singlevalue

#parent
test() >>
#    singlevalue = singlevalue +1
#UnboundLocalError: local variable 'singlevalue' referenced before assignment

The example show you that with list it output 1 and keep it for next execution. Why the singlevalue have a different way?


回答1:


Both answers so far suggest a solution, which was not the point of the post. The difference is that regarding the list, you are working with a reference and are not manipulating a "bound" variable, as you would do with singlevalue. As soon as you would try to do: l = l + [1] for example, you would try to modify the bound l and get the same error. That is because of how scoping in python work!

In short:

singlevalue [local variable] = singlevalue [actually a global variable but access to locally stored variable] + 1 [constant]

singlevalue is stored locally. Now it wants to access that locally stored variable, which doesn't have a value yet, as it wasn't assigned. IF you want to store it globally you need to use the global keyword.

list[0] [slot in a referenced list] = list[0] [still same slot, which has a value already]+1

Hence, no problem. :)

In more Detail:

We can have a look at python's bytecode here and see the difference in loading:

>>> def m():
...  y = 1
...  def test():
...   y = y + 1
...   return y
...  test()
>>> m()
UnboundLocalError: local variable 'y' referenced before assignment
>>> dis.dis(m)
  [... cur here ... Inside of test()]
              # <-- here the value of the constant is loaded from the local namespace
  3           6 LOAD_CONST               2 (<code object test at 02A067B8, file "<pyshell#33>", line 3>)                   
              9 MAKE_FUNCTION            0
             12 STORE_FAST               1 (test)
  [... cut here ...]

>>> def l():
...  li = [1]
...  def test():
...   li[0] = li[0] + 1
...   return li
...  test()
>>> l()
[... cut here ... Inside of test()]
              # <-- here a reference is loaded!
  3           9 LOAD_CLOSURE             0 (li)
             12 BUILD_TUPLE              1
             15 LOAD_CONST               2 (<code object test at 02A06698, file "<pyshell#28>", line 3>)
             18 MAKE_CLOSURE             0
             21 STORE_FAST               0 (test)
[... cut here ...]

As this post would be getting too long I recommend to execute above's commands and have a look here: http://docs.python.org/2/library/dis.html to see the difference!

The main difference in how things are stored, however, happens in the first block:

  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (y) # <- push loaded constant to stack

  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               1
              6 STORE_DEREF              0 (li) # <- stores the value in the list

Have a look here!

I hope this helps clearing the difference. Cheers!




回答2:


Would it be helpful to have a look at defining functions on how to pass arguments?

Passing arguments might be more reliable than manipulating a "variable" of which you're hoping it is globally accessible and mutable.

Actually, the "variables" are names for references in a (particular) namespace and if you'd check with

print id(ll)    # as suggested by others: please don't name your list list ;)
print id(singlevalue)

in your functions, you'd see they didn't change. Consequently, you can refer to the name singlevalue in any function and print it without any problem.

When trying to change their values, the situation changes:

Lists are mutable objects, you can mess around with them (in any function) without changing their references. Whether it's a better/sexier/more pythonic idea to pass them as arguments is another point.

Strings, however, are immutable. Within you function, you might assign the value of singlevalue to another name and boths names will have the same reference. But when you change the value of the new name, it'll have a new reference!

Therefore, i'd suggest to be as lazy as possible but better pass data rather than poking around in the "surrounding" namespace and hope for your best ;)




回答3:


Don't use global variables. Simply reassign the value of the variable each time.

some_variable = 0
def test():
    return some_variable + 1


some_variable = test()  # 1
some_variable = test()  # 2

Test session on the interactive interpreter:

>>> a = 0
>>> def test():
...     return a + 1
... 
>>> a = test()
>>> a
1
>>> a = test()
>>> a
2


来源:https://stackoverflow.com/questions/17142544/python-single-integer-variable-between-function

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