carry **arguments through different scopes/functions
Peter Otten
__peter__ at web.de
Sun Jan 31 08:49:56 EST 2016
c.buhtz at posteo.jp wrote:
> I am not sure what the problem is here, so I don't really know how I
> should call the subject for that question. Please offer a better
> subject.
>
> The code below is a extrem simplified example of the original one. But
> it reproduce the problem very nice. Please focus on the variable
> `return_code`.
>
> There is a `list()` of numbers without the number `7` in. The code
> check if the number `7` is in and should tell that it is not in. But it
> does tell me that `7 is in`. ;)
>
> I think I didn't know some special things about scopes of variables in
> Python. This might be a very good problem to learn more about that. But
> I don't know on which Python topic I should focus here to find a
> solution for my own.
>
> #!/usr/bin/env python3
> import sys
>
> def walkOn_ids(ids, handlerFunction, **handlerArgs):
> for one_id in ids:
> handlerFunction(one_id=one_id, **handlerArgs)
> print('after handler-call for id {}\t{}'
> .format(one_id, handlerArgs))
>
>
> def _on_id(one_id, return_code):
> if return_code is False:
> return
>
> if one_id == 7:
> return_code = True
> else:
> return_code = False
>
> print('one_id: {}\treturn_code: {}'.format(one_id, return_code))
>
>
> def _isSevenInIt(ids):
> return_code = True
>
> walkOn_ids(ids=ids,
> handlerFunction=_on_id,
> return_code=return_code)
>
> return return_code
>
>
> ids = [1,2,3,4,5,6,8,9] # NO 7
> print(ids)
>
> if _isSevenInIt(ids) is True:
> print('7 is in')
> else:
> print('no 7 in it')
>
> sys.exit()
>
> Of course I could make `return_code` a `global` variable. But that is
> not the goal. The goal is to carry this variable inside the
> walker-function and bring the result back. In the original code I will
> use some more complexe data structures with `**handlerArgs`.
The solution that requires the least changes to your code is probably to
turn return_code into an attribute of a mutable argument (called context
below):
#!/usr/bin/env python3
import sys
import types
def walkOn_ids(ids, handlerFunction, **handlerArgs):
for one_id in ids:
handlerFunction(one_id=one_id, **handlerArgs)
print('after handler-call for id {}\t{}'
.format(one_id, handlerArgs))
def _on_id(one_id, context):
if context.return_code:
return
if one_id == 7:
context.return_code = True
print('one_id: {}\treturn_code: {}'.format(one_id, context.return_code))
def _isSevenInIt(ids):
context = types.SimpleNamespace(return_code=False)
walkOn_ids(ids=ids,
handlerFunction=_on_id,
context=context)
return context.return_code
ids = [1, 2, 3, 4, 5, 6, 8, 9] # NO 7
print(ids)
if _isSevenInIt(ids):
print('7 is in')
else:
print('no 7 in it')
However, the resulting code is not very pythonic.
In idiomatic Python the toy problem you present -- looking for the first
item in an iterable that fulfills a certain condition -- would be solved
like that:
def equals_seven(id):
return id == 7
ids = [1, 2, 3, 4, 5, 6, 8, 9] # NO 7
if any(equals_seven(id) for id in ids):
print('7 is in')
else:
print('no 7 in it')
It is likely that your actual code can be simplified, too.
More information about the Python-list
mailing list