wilbeibi
wilbeibi

Reputation: 3454

What is the scope of this variable `instantiated`

I came across Peter Norvig's implement of singleton class here http://norvig.com/python-iaq.html

def singleton(object, instantiated=[]):
    "Raise an exception if an object of this class has been instantiated before."
    assert object.__class__ not in instantiated, \
        "%s is a Singleton class but is already instantiated" % object.__class__
    instantiated.append(object.__class__)

class YourClass:
    "A singleton class to do something ..."
    def __init__(self, args):
       singleton(self)
       ...

My problem is, if we create two YourClass instances, in the second time, why instantiated is not a empty list? What's the scope of instantiated?

Thank you.

Upvotes: 4

Views: 40

Answers (1)

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52173

From docs:

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. It accumulates the arguments passed to it on subsequent calls.

The value of instantiated is bound to function definition and is initialized only once when you define singleton.

Because of this, every time you call the function, you'll have only one copy of same list:

def test(x, instantiated=[]):
    instantiated.append(x)
    print instantiated

>>> test(3)
[3]
>>> test(5)
[3, 5]
>>> test(6)
[3, 5, 6]

It is same as:

>>> lst = []

>>> def test(x, instantiated):
...     instantiated.append(x)
...     print instantiated

>>> test(3, lst)
[3]
>>> test(5, lst)
[3, 5]
>>> test(6, lst)
[3, 5, 6]

If you want instantiated to be isolated between subsequent function calls, you should define it as a local variable:

def test(x, instantiated=None):
    if instantiated is None:
        instantiated = []
    instantiated.append(x)
    print instantiated

>>> test(3)
[3]
>>> test(5)
[5]
>>> test(6)
[6]

Upvotes: 1

Related Questions