-1

I wrote this code to access an object via user input. It works with locals (I know I can make dictionary too)

class Dragon:

    def __init__(self, head, legs):
        self.head = head
        self.legs = legs

    def sum(self):
        return self.head + self.legs


redfire = Dragon(2, 4)
dic1 = {"redfire": redfire}
input_object = input()
print(dic1[input_object].sum())

but when I'm trying to do the same with methods of the class:

class Dragon:

    def __init__(self, head, legs):
        self.head = head
        self.legs = legs

    def sum(self):
        return self.head + self.legs

    def mul(self):
        return self.head * self.legs


redfire = Dragon(2, 4)
dic1 = {"redfire": redfire, "sum": Dragon.sum(self), "mul": Dragon.mul}
input_object = input()
input_method = input()
print(dic1[input_object].dic1[input_method])

I'm getting all kinds of errors asking me to modify my dictionary:

Traceback (most recent call last):   
  File "C:\Users\millw0rm\test.py", line 10, in <module>
    dic1 = {"redfire": redfire, "sum": Dragon.sum(self), "mul": Dragon.mul} 
NameError: name 'self' is not defined

What can I do to define a valid key for my methods in my dictionary?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
ItsJay
  • 188
  • 4
  • 17
  • why `Dragon.sum`? You already created the `redfire` instance, why not add that to the dict? In that case, `self` will be implicitly passed. Or, add `Dragon.sum(redfire)` which is a silly way of doing the **exact** same thing. – Dimitris Fasarakis Hilliard Aug 06 '16 at 09:33
  • Do you want `getattr(dic1[input_object], input_method)()`? – jonrsharpe Aug 06 '16 at 09:39
  • actually i dont have a clue what i was doing with that method part in dictionary.look, imagine you have several classes with several methods within them and you have a bunch of objects how do you write a piece of code asking user for a desired object an a method of its class to do an opperation on attributes of that object. like in this one i get the object redfire and after that i wanted to get method sum from an input to do the opperation . – ItsJay Aug 06 '16 at 09:47
  • 1
    Then yes, the above line is what you want. See e.g. http://stackoverflow.com/q/3521715/3001761 – jonrsharpe Aug 06 '16 at 10:13

3 Answers3

0

You are not using class method rightly :

redfire = Dragon(2, 4)
dic1 = {"redfire": redfire, "sum": Dragon.sum(self), "mul": Dragon.mul}

In fact, in your class function definition: def sum(self):, self refer to an object of the class.

You should then use it like this :

# Create one dragon
redfire = Dragon(2, 4)
# Enter the dragon in the dict
dic1 = {"redfire": redfire, "sum": redfire.sum(), "mul": redfire.mul()}

Therefore you are using redfire.sum() that is basically using sum() function on the object redfire that is a Dragon object.

For the second part of your work: print(dic1[input_object].dic1[input_method]), you need to store a reference to a function:

sum_method = Dragon.sum
sum_redfire = sum_method(redfire)

Finaly we get:

redfire = Dragon(2, 4)
sum_method = Dragon.sum
dict1 = {"redfire": redfire, "sum": sum_method}
input_object = input()
input_method = input()
print(dict1[input_method](dict1[input_object]))
Xavier C.
  • 1,921
  • 15
  • 22
  • Xavier that not what im asking i want to get both objects and methods from user .image if i have like 1000 objects! cant make a dictionary that big. and by the way with replacing your code i still get an error AttributeError: 'Dragon' object has no attribute 'dic1' – ItsJay Aug 06 '16 at 09:54
  • Millw0 have add a part to my answer, that should help you, tell me if it is not enough :) – Xavier C. Aug 06 '16 at 10:11
0

There's no point storing the methods in the dictionary: they're already stored in the Dragon class itself. As jonrsharpe mentions in the comments, you can use the built-in getattr function to retrieve an attribute of a class instance; that applies to methods like your sum and mul as well as the simple head and legs attributes.

Here's a re-organised version of your code that I think you'll find useful. I've added a __repr__ method to the class so that we get useful info when we print a Dragon instance.

class Dragon:
    def __init__(self, head, legs):
        self.head = head
        self.legs = legs

    def sum(self):
        return self.head + self.legs

    def mul(self):
        return self.head * self.legs

    def __repr__(self):
        return 'Dragon({}, {})'.format(self.head, self.legs)

dragons = {}
dragons["redfire"] = Dragon(2, 4)
dragons["greenfire"] = Dragon(1, 2)
print(dragons)

name = input("name: ")
method_name = input("method: ")
d = dragons[name]
method = getattr(d, method_name)
print(d, method())    

test

{'redfire': Dragon(2, 4), 'greenfire': Dragon(1, 2)}
name: redfire
method: sum
Dragon(2, 4) 6

Of course, you could create the dragons dictionary like this:

dragons = {
    "redfire": Dragon(2, 4),
    "greenfire": Dragon(1, 2),
}
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • thats right guess dont need that d in last line...you can check my modified code im getting class name of objects in z value and lol asked locals() for a lil bit of help – ItsJay Aug 06 '16 at 12:31
  • @Millw0 Sure, those last 3 lines in my 1st code block _can_ be condensed down to `print(dragons[name], getattr(dragons[name], method_name)())` but I wanted to make the code more readable. – PM 2Ring Aug 06 '16 at 12:43
0

Thanks so much everbody especially jonrsharp and PM 2Ring for mentioning getattr() function . code below is what i was seeking for

class Dragon:
    def __init__(self,head,tail):
        self.head=head
        self.tail=tail
    def sum(self):
        return (self.head + self.tail)
class Snake:
    def __init__(self,head,tail):
        self.head=head
        self.tail=tail
    def sum(self):
        return (self.head * self.tail)
python=Snake(1,1)
anakonda=Snake(3,5)     
redfire=Dragon(2,4)
hellfly=Dragon(2,10)
x=input()
y=input()
z=objectdic[x].__class__.__name__
print(getattr(locals()[z],y)(locals()[x]))
ItsJay
  • 188
  • 4
  • 17
  • It's not a good idea to use `locals()` unless you're doing something special that _really_ needs it, and you _don't_ need it here. Using `locals()` makes it harder to read the code (which makes it harder to maintain). – PM 2Ring Aug 06 '16 at 12:48