Curious function argument

Akira Li 4kir4.1i at gmail.com
Fri Nov 28 06:52:25 CET 2014


"ast" <nomail at 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





More information about the Python-list mailing list