[Tutor] assign all parameters of __init__ to class variables?

Steven D'Aprano steve at pearwood.info
Wed Nov 2 23:00:36 CET 2011


On Thu, 3 Nov 2011 12:57:25 am Alex Hall wrote:
> Thanks to both of you, that will work. I can see the argument for
> assigning everything manually, but I have each parameter on its own
> line with a comment to explain what it does, and I know I want all
> parameters to be class-level for every instantiation, so saying
> "self.[varName]=[varName]" twenty times seems like a waste of time
> and space.

Wait, you you want the parameters to be *class level*, that is, shared 
by all instances? But you want them to be set each time you 
instantiate an instance? That's fairly unusual. Normally people want 
each instance to get its own instance-level attributes.

In Python, one way of doing this would be:

class K(object):
    a = 1  # class-level shared attribute defined once only
    def __init__(self, b):
        self.__class__.b = b  # Set the shared class-level attribute


And in action:

>>> ham = K(23)
>>> ham.a, ham.b
(1, 23)
>>> eggs = K(42)
>>> ham.a, ham.b
(1, 42)


Notice that you must assign the attribute on the class object itself, 
not the instance. So if you have a bunch of parameters, rather than 
updating the instance dictionary, you have to update the class 
dictionary. (This makes error checking and parameter validation even 
more important, because you can screw your class up by overwriting 
methods if you pass the wrong parameter name.)

But assuming you like living dangerously, or you trust the caller not 
to be stupid:

class K(object):
    a = 1
    def __init__(self, **kwargs):
        self.__class__.__dict__.update(kwargs)

But having done that, it still won't really work the way you expect 
(or at least the way I *think* you will expect). The problem is that 
the instance still has its own dict, so when the caller assigns to an 
attribute:

instance = K(b=2, c=3)
instance.d = 4

b and c become class-level, as requested, but d is instance-level and 
any other instances will not share that value.

The best way to ensure all instances share the same attributes is with 
the Borg design pattern:

http://code.activestate.com/recipes/66531/

(Also known as Monostate, or the poorly-named "stateless proxy".)

The above recipe is for classic classes, which no longer exist in 
Python 3; for a new-style class version, see the comment by Alex 
Naanou on that page. The other alleged new-style Borgs actually 
implement Singletons.

But if the difference between a Singleton and a Borg matters to you, 
you're probably up to no good. <wink>



-- 
Steven D'Aprano 


More information about the Tutor mailing list