Assigning the same value to several variables at once

Baldyr

"Hit It"
Joined
Dec 5, 2009
Messages
5,530
Location
Sweden
This is another one of my pointless endeavors threads. Meaning that whether or not I figure this out has no immediate benefit for the actual functionality of my code. Also, its not CivIV specific so I might as well post in somewhere else entirely... :rolleyes: But bare with me. And if you think I'm (still) being silly you can just skip this one. Because I already know its a futile quest.

The background is that I recently figured out a way to get rid of the unaesthetic assignment lines for counter variables and empty data structures. Because I can just add those on the definition line, like this:
Code:
def randomFunction(arg1, arg2, lEmptyList=[], iCounter=0):
As a bonus the actual function becomes more versatile, as it would be possible to for example use it to add to a pre-existing list by entering a third argument.

Now the next step in cleaning up my code is to get rid of the pesky default value assignment in some __init__ definitions. Example:
Code:
        def __init__(self):
                self.player = None
                self.plotList = None
                self.coords = None
                self.Key = None
                self.CyPlayer = None
                self.CyPlot = None
                self.CyCity = None
Clearly there must be another way to set all these class fields to a None value without typing 7 individual statement lines?

I believe that my own ideas thus far have revolved around putting all the attribute names in list and looping it in order to assign each field the same default value. But there were technical challenges I really couldn't overcome. It would however look something like this:
Code:
        def __init__(self):
                setDefaultValue(self, None, "player", "plotList", "coords", "Key", "CyPlayer", "CyPlot", "CyCity")
And the setDefaultValue() function would look something like this:
Code:
def setDefaultValue(pInstance, value, *args):
        for variable in args:
                eval("pInstance." + variable + "=value")
I guess that I'm still struggling wit the eval() built-in function... :rolleyes:

Also I've though of tuple assignment, but then I need a data structure that holds the exact number of None values. But maybe I could make a helper function that makes that for me?
Code:
def getNoneList(iNumEntries, lNoneList=[]):
        while iNumEntries > 0:
                lNoneList.append(None)
                iNumEntries -= 1
        return lNoneList
Then I could have:
Code:
        def __init__(self):
                self.player, self.plotList, self.coords, self.Key, self.CyPlayer, self.CyPlot, self.CyCity = getNoneList(7)
But I'm not sure this is an improvement. Could I get rid of the self. bits if I make these class variables instead? Like:
Code:
class Context:
        player, plotList, coords, Key, CyPlayer, CyPlot, CyCity = getNoneList(7)

        def __init__(self):
                pass
Does anyone have a better implementation for this? (And I still realize this is pretty pointless, but this is actually how I learn. By figuring out some seemingly meaningless idea like this allows me to do something pretty awesome in another context. The thing is of course that I won't know in beforehand when, where or even if it will pay off.)
 
Wouldn't it be easier to just do this.

Code:
class Context:
        player, plotList, coords, Key, CyPlayer, CyPlot, CyCity = ( None, ) * 7
 
Of course it would! :king:

The whole reason for the OP was that I had the feeling there would a simple - and obvious - solution like that! Thank you very much! :goodjob:
 
I think this is even "cleaner":
Code:
class Context:
        player, plotList, coords, Key, CyPlayer, CyPlot, CyCity = [None] * 7
Now if I just wouldn't have to count the number of variables... :p
 
Wohoo! :eek: Now we're talking! Nice!
 
Doesn't this need to go inside __init__()?

Code:
class Context:
    def __init__(self):
        self.player = self.plotList = self.coords = self.Key = self.CyPlayer = self.CyPlot = self.CyCity = None

Class variables belong to the class and not each instance.

But my real point in posting is to warn you about using non-scalar default argument values such as a list: the value is shared for every invocation of the function. In other words, a new list is created once and that same list is used as the default value every time the function is called. If you append values to the list inside the function, they will still be there the next time the function is called.

Here's an example:

Code:
def foo(x, y=[]):
	print x, y
	y.append(x)
	print y

>>> foo(1)
1 []
[1]

>>> foo(2)
2 [1]
[1, 2]

>>> foo(3)
3 [1, 2]
[1, 2, 3]

Using "list()" instead of "[]" doesn't help. You need to use None as the default value and then assign a new list inside the function if it is None.

Code:
def foo(x, y=None):
	if y is None:
		y = []
	print x, y
	y.append(x)
	print y
 
Yeah, I ran into that problem for the first time a couple of months ago, it was a real headache. Now I create all of my sequence types in __init__ just to be on the safe side. I still make my other attribute types class attributes to save memory space in some situations. Actually that's an assumption that I made, maybe EmporerFool or somebody else can confirm that for me. Does a class attribute only exist once for all class instances unless a given class instance changes the attribute's value - then that instance now has it's own copy of the attribute.
 
Class attributes are always tied to the class, and they have a single value shared among all instances of that class. Anything assigned to "self" is an instance attribute, and each instance has its own value. If one instance changes the value of a class attribute, that value is seen by everyone else. Each instance does not contain its own copy of the value. The class is an instance of whatever internal class defines classes.

One thing that helps is to remember that almost everything in Python has a dictionary as part of its structure.

  • A class has a dictionary containing all of its functions and attributes.
  • Each object has a dictionary containing its attributes (those assigned to self.<name>).
  • A module's global variables, functions, and classes are all stored in its globals() dictionary.
  • Local variables in a function are stored in its locals() dictionary.
 
Interesting stuff... Thanks a bunch! :king:
 
Thanks for the info EmperorFool. Through actual use I kinda of figured that was how things worked. but I wasn't 100% certain.
 
Top Bottom