views:

701

answers:

6

I've been learning how to use Python for the better part of today after giving up on an ugly bash script.

I'm trying to use 2 classes to define a few arrays of objects in which to store some unique strings and integers (1-10). The objects will consist of the following:

object[i].user
         .n     # n = i
         .name
         .coords
         .hero

(param1, param2, param3) will be different for each object.n and object.user, so I'm trying to use an assignment method that doesn't look like garbage after writing 90 unique strings. Nesting an example I found didn't work, so here's the compromise:

class CityBean:
    def __init__(self,name,coords,hero):
        self.name = name
        self.coords = coords
        self.hero = hero

class Castles:
    def __init__(self,user,n):
        self.user = user
        self.n = n
        if self.user == 'user1':
            temp = {
                1:  CityBean( "name1"  , "coord1" , "hero1"),
                ... blah blah blah
                10: CityBean( "name10" , "coord10" , "hero10" )}[self.n]()
        if self.user == 'user2':
            temp = {
                1:  CityBean( "name11" , "coord11" , "hero11" ),
                ... blah blah blah
                10: CityBean( "name20" , "coord20" , "hero20" ) }[self.n]()
        if self.user == 'user3':
            temp = {
                1:  CityBean( "name21" , "coord21" , "hero21" ),
                ... blah blah blah
                10: CityBean( "name30" , "coord30" , "hero30" ) }[self.n]()
        self.name = temp.name
        self.coords = temp.coords
        self.hero = temp.coords
        __del__(temp)

I call it with something like this:

cities = list( Castles("user2",i) for i in range(1,11) )

It gives me this error:

AttributeError: CityBean instance has no __call__ method

And it blames this line:

                10: CityBean( "name20" , "coord20" , "hero20" ) }[self.n]() # pseudo
                10: CityBean( "" , "" , "" ) }[self.n]() # what is actually looks like

What's wrong with my cruddy classes? I'm doing something retarded, aren't I?

A: 

I don't really understand what you're trying to do exactly, but:

 10: CityBean( "name10" , "coord10" , "hero10" )}[self.n]()

if calling something (the () at the end make it a function call).

What you would want is I think temp = { ... 10: CityBean( "name10" , "coord10" , "hero10" )}[self.n]

In that case you'd get the dict entry with key n and label that temp.

extraneon
Yeah, that'd be my quick-fix -- thanks!
tyblu
A: 

Putting parens after a class name in a normal expression instantiates it immediately. If you want to delay instantiation then you'll need to use lambda or functools.partial():

10: lambda: CityBean("", "", "")}...
Ignacio Vazquez-Abrams
+2  A: 

Why did your write this?

temp = {
            1:  CityBean( "name21" , "coord21" , "hero21" ),
            ... blah blah blah
            10: CityBean( "name30" , "coord30" , "hero30" ) }[self.n]()

What do you think temp= {...}[something]() will do?

  1. It creates a dictionary. {...}

  2. It picks one item out of the dictionary. {...}[something]. This will be a CityBean object.

  3. It evaluates that one item as a function {...}[something]() Is CityBean(...)()

Why are you calling the CityBean object as if it was a function?

Further, why are you creating entire dictionaries only to pick a single item of it? What's wrong with if statements?

S.Lott
Perfect! Thanks mate. I thought it just needed the parenthesis in its syntax. Not too sure what a dictionary is, but I see how I can use it. I'm an engineer, so my final code ain't gonna be somethin' to hang on the wall. ;)
tyblu
A: 

your are doing

{
1:  CityBean( "name1"  , "coord1" , "hero1"),
... blah blah blah
10: CityBean( "name10" , "coord10" , "hero10" )}[self.n]()

which is basically from a dict get value based on key, values on your dict are CityBean instances, so in short you are doing this

CityBean( "name1"  , "coord1" , "hero1")()

which is valid but will call the special method __call__ of the instance, so either remove () or add a __call__ method depending on the need

Anurag Uniyal
+3  A: 

It's really hard to guess what you want from what you provided, since, instead of saying what you want to do, you provided your newbie code, so one has a hard guess time.

I'd think something like this would do:

data = {
        (1, 'user1'): ("name1", "coord1", "hero1"),
        (2, 'user1'): ("name2", "coord2", "hero2"),
        #...
        (1, 'user2'): ("name11", "coord11", "hero11"),
        (2, 'user2'): ("name12", "coord12", "hero12"),
        # ...
    }


class CityBean:
    def __init__(self,name,coords,hero):
        self.name = name
        self.coords = coords
        self.hero = hero

class Castles:
    def __init__(self,user,n):
        self.user = user
        self.n = n
        name, coords, hero = data.get((n, user))
        self.citybean = CityBean(name, coords, hero)
nosklo
+1 I bow before your ability to make sense of the goal of the code in this question.
Max Shawabkeh
Hey, that looks really good! Thanks nosklo.
tyblu
@tyblu Note the use of a tuple (1,'user1') as key of the dict. A tuple is immutable and can therefore be used as a key. A list [1, 'user1'] could not be used as a key.
extraneon
@extraneon: A tuple, hey... Seems to be an ambiguous name. :) Thanks for the tip.
tyblu
A: 

Notice, that in python, when you write

CityBean( "name1"  , "coord1" , "hero1")

You initialize the object CityBean. There is no need for an extra ().

Thomas Ahle