Re: Curious function argument
ast nom...@invalid.com writes: Hello I saw in a code from a previous message in this forum a curious function argument. def test(x=[0]): print(x[0]) ## Poor man's object x[0] += 1 test() 0 test() 1 test() 2 I understand that the author wants to implement a global variable x . It would be better to write 'global x' inside the function. At first test() function call, it prints 0, that's OK. But at the second call, since we dont pass any argument to test(), x should be equal to its default value [0] (a single item list). But it seems that Python keeps the original object whose content has been changed to 1. Is it a usual way to implement a global variable ? It is not a global, a global would be easily available (visible) to other functions. You can get it if you try but Python also allows you to get private attributes, replace builtins and other things that you should not normally do. *# Poor man's object* in this context suggests that I'm the author. The code is meant as a part of a short Python script that is executed directly. Imagine the *test()* definition is put inside main() function that is called when the script is run. `def test(*, _x=[0]):..` attaches some state (_x list) to the function *test*. It could be used as a way to emulate *nonlocal* keyword: def counter(): count = 0 def increment(): nonlocal count count += 1 return count return increment c = counter() print(c(), c()) # 0, 1 c = counter() print(c(), c()) # 0, 1 an alternative is to create an object using class: class Counter: def __init__(self): self.count = 0 def __call__(self): self.count += 1 return self.count c = Counter() print(c(), c()) For this specific case, you could use `itertools.count`: c = itertools.count() print(next(c), next(c)) which could be implemented here as a generator: def count(): count = 0 while True: count += 1 yield count c = count() print(next(c), next(c)) Objects are data with methods attached, closures are functions with data attached. [1] Sometimes you need to define a class to create objects, in other cases a function is enough (and of course functions are objects too in Python). [1] http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python -- Akira -- https://mail.python.org/mailman/listinfo/python-list
Re: Curious function argument
ast wrote: Hello I saw in a code from a previous message in this forum a curious function argument. def test(x=[0]): print(x[0]) ## Poor man's object x[0] += 1 test() 0 test() 1 test() 2 I understand that the author wants to implement a global variable x . It would be better to write 'global x' inside the function. No, it's not a global. A better description is that it is a way of faking static storage for a function: the function test has a static variable x which is independent of any other function's x, but it can remember its value from one function call to another. At first test() function call, it prints 0, that's OK. But at the second call, since we dont pass any argument to test(), x should be equal to its default value [0] (a single item list). But it seems that Python keeps the original object whose content has been changed to 1. Is it a usual way to implement a global variable ? No, it's unusual. If you actually want a global, use the global keyword. Otherwise, there are often better ways to get a similar effect, such as using a generator: def gen(): x = 0 while True: yield x x += 1 it = gen() next(it) # returns 0 next(it) # returns 1 next(it) # returns 2 You can turn that into functional form like this: import functools func = functools.partial(next, gen()) func() # returns 0 func() # returns 1 func() # returns 2 -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Curious function argument
Hello I saw in a code from a previous message in this forum a curious function argument. def test(x=[0]): print(x[0]) ## Poor man's object x[0] += 1 test() 0 test() 1 test() 2 I understand that the author wants to implement a global variable x . It would be better to write 'global x' inside the function. At first test() function call, it prints 0, that's OK. But at the second call, since we dont pass any argument to test(), x should be equal to its default value [0] (a single item list). But it seems that Python keeps the original object whose content has been changed to 1. Is it a usual way to implement a global variable ? thx -- https://mail.python.org/mailman/listinfo/python-list
Re: Curious function argument
On Wed, 12 Nov 2014 14:07:14 +0100, ast wrote: [function def with mutable default parameter] I understand that the author wants to implement a global variable x . It would be better to write 'global x' inside the function. It may not be the case that the purpose was to implement a global variable, but rather to illustrate what happens when you use a mutable default parameter. At first test() function call, it prints 0, that's OK. But at the second call, since we dont pass any argument to test(), x should be equal to its default value [0] (a single item list). But it seems that Python keeps the original object whose content has been changed to 1. This is explained in the docs: https://docs.python.org/3/reference/compound_stmts.html#function- definitions Default parameter values are evaluated from left to right *when the function definition is executed*[1]. This means that the expression is evaluated once, when the function is defined, and that the same “pre- computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. [1] ie when the function is 'compiled', not each time it executes. -- Denis McMahon, denismfmcma...@gmail.com -- https://mail.python.org/mailman/listinfo/python-list