Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #80602 > unrolled thread
| Started by | "ast" <nomail@invalid.com> |
|---|---|
| First post | 2014-11-12 14:07 +0100 |
| Last post | 2014-11-28 08:52 +0300 |
| Articles | 5 — 5 participants |
Back to article view | Back to comp.lang.python
Curious function argument "ast" <nomail@invalid.com> - 2014-11-12 14:07 +0100
Re: Curious function argument Denis McMahon <denismfmcmahon@gmail.com> - 2014-11-12 14:03 +0000
Re: Curious function argument Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2014-11-12 09:18 -0500
Re: Curious function argument Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-11-15 21:39 +1100
Re: Curious function argument Akira Li <4kir4.1i@gmail.com> - 2014-11-28 08:52 +0300
| From | "ast" <nomail@invalid.com> |
|---|---|
| Date | 2014-11-12 14:07 +0100 |
| Subject | Curious function argument |
| Message-ID | <54635bce$0$2384$426a74cc@news.free.fr> |
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
[toc] | [next] | [standalone]
| From | Denis McMahon <denismfmcmahon@gmail.com> |
|---|---|
| Date | 2014-11-12 14:03 +0000 |
| Message-ID | <m3vpce$pm6$2@dont-email.me> |
| In reply to | #80602 |
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, denismfmcmahon@gmail.com
[toc] | [prev] | [next] | [standalone]
| From | Dennis Lee Bieber <wlfraed@ix.netcom.com> |
|---|---|
| Date | 2014-11-12 09:18 -0500 |
| Message-ID | <mailman.15721.1415801914.18130.python-list@python.org> |
| In reply to | #80602 |
On Wed, 12 Nov 2014 14:07:14 +0100, "ast" <nomail@invalid.com> declaimed
the following:
>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... The author implemented a mutable DEFAULT argument.
The argument can still be overloaded by passing something else into the
function.
y = [0]
z = 234
test(y)
test(z)
This would not work if one instead declared a global "x"
--
Wulfraed Dennis Lee Bieber AF6VN
wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-11-15 21:39 +1100 |
| Message-ID | <54672d63$0$12983$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #80602 |
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
[toc] | [prev] | [next] | [standalone]
| From | Akira Li <4kir4.1i@gmail.com> |
|---|---|
| Date | 2014-11-28 08:52 +0300 |
| Message-ID | <mailman.16394.1417154034.18130.python-list@python.org> |
| In reply to | #80602 |
"ast" <nomail@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
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web