Setting a Global Default for class construction?

Geoff Gerrietts geoff at gerrietts.net
Fri Jan 31 23:55:22 CET 2003


Quoting Josh English (english at spiritone.com):
> Here is the code that I am struggling with in a Python module:
> 
> _Thing = "it"
> 
> def SetThing(s):
> 	global _Thing
> 	_Thing = str(s)
> 
> class NewThing:
> 	def __init__(self,thing=_Thing):
> 		self.Thing = _Thing
> 
> I thought that this would work if I called:
> 
> >>>SetThing('hallo')
> >>>a = NewThing()
> >>>a.Thing
> 'it'
> 
> I would expect a.Thing to return 'hallo', not 'it'. Is this possible to 
> do in Python?

Lots of ways to do it. The quick and dirty way is not as nice as the
easy way, so we'll do the easy way:

class _ThingClass:
  thing = "it"
_Thing = _ThingClass()

def SetThing(s):
  global _Thing
  _Thing.thing = str(s)

class NewThing:
  def __init__(self, thing=_Thing):
    self.Thing = thing.thing

  def alternate_init(self):
    self.Thing = _Thing.thing

  def second_alternate(self):
    self.Thing = _Thing

Now, the code will do roughly what you expect.
>>> SetThing('hallo')
>>> a = NewThing()
>>> a.Thing
'hallo'

But one thing that's important to note is that if we continue, it
might not.

>>> SetThing('goodbye')
>>> a.Thing
'hallo'

The issue you're running up against is that your assignment in
SetThing is changing which object (string) the global name "_Thing" is
bound to. You're not changing some object "_Thing", you're pointing
the name "_Thing" at some new object.

In your example, the name "self.Thing" is being pointed at the value
of the global name "_Thing", at construction time for the instance.
When the object is constructed, _Thing points at "it".

Meanwhile, thing=_Thing is pointing the name "thing" at the object
pointed to by the global name "_Thing". This assignment is performed
at "compile-time", when the __init__ function is defined. That means
"thing" will always point at "it", regardless of when you instantiate
your objects.

A rough diagram:

 before SetThing:
   +---------+                  +------+
   | _Thing  |   ---------->    | "it" |
   +---------+                  +------+

                                +---------+
                                | "hallo" |
                                +---------+
                              
  
 after SetThing:

                                +------+
                                | "it" |
                                +------+

   +---------+                  +---------+
   | _Thing  |   ---------->    | "hallo" |
   +---------+                  +---------+


In the revised code example, __init__ assigns the local name "thing"
to the object pointed to by the global name "_Thing". The global name
"_Thing" points to an instance of the _ThingClass class. Then, we
assign the name "self.thing" to point at the "thing" attribute on that
object. This results in the behavior you were expecting, because the
object never changes -- its attributes do. 

A diagram:

 before SetThing:
   +---------+   +--------+ 
   | _Thing  |-->| object | 
   +---------+   |--------|    +------+
                 | *thing |--->| "it" |
                 +--------+    +------+
                            
                               +---------+
                               | "hallo" |
                               +---------+
                            

  after SetThing:
                               +------+
                               | "it" |
   +---------+   +--------+    +------+
   | _Thing  |-->| object | 
   +---------+   |--------|    +---------+
                 | *thing |--->| "hallo" |
                 +--------+    +---------+
                            

In the code example, the alternate_init is equivalent to the __init__,
but without the "optional" argument. The second_alternate doesn't do
exactly the same thing as the other examples. This second alternate
could be used to always have access to the newest _Thing.thing value,
but it would require printing a.Thing.thing instead of a.Thing.

Wow, a lot more than I meant to write on this topic, hope it helps.

--G.

-- 
Geoff Gerrietts             "People talk fundamentals and superlatives 
<geoff at gerrietts net>     and then make some changes of detail." 
http://www.gerrietts.net                  --Oliver Wendell Holmes Jr





More information about the Python-list mailing list