سؤال

I have a Python question.

Let's say we have this class:

class Class:

    def __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

******* This part I am not sure how to code **

    def controls(self, instructions)
        instructions[0] = instructions[1]

***************** ************

    my_class = Class(arg1, arg2, arg3)

    inputs = {"A":[self.arg1, value1],
              "S":[self.arg2, value2],
              "D":[self.arg3, value3]}

    my_class.controls(inputs["A"])

So the dictinary ("inputs") maps keyboard strokes. According to what key is pressed, I need to edit some of the attributes of my_class.

What I am trying to do is this: pass to def controls(self, instructions) the values that need to be edited according to the keystroke. So for example if the user presses "A", then I want to change self.arg1 to value1 from whatever value it has now. Similarly, if he presses "S", I want to edit another attributes to another, etc.

So if I do:

print instructions

I get for keypress "A":

[self.arg1, value1]

So for example, if the user has pressed "A", "S" and "D", once all have been settle here is what my_class should look like:

my_class.arg1 = value1
my_class.arg2 = value2
my_class.arg3 = value3

I made various attemps, but none have been able to actually change the value of self.argX, they all either give me an error or don't accomplish anything useful.

I am currently doing a bunch of If/elif but that's getting lenghty.

So my core question is this:

How can I pass as argument instruction[self.arg1, value1] and have the program edit whatever attribute I give it in instruction[0] and set its value to whatever value I give it in instruction[1] in my_class?

Edit: removed details that aren't relevent to the core of the question after comments below.

هل كانت مفيدة؟

المحلول

I suppose you are looking for something like this:

class DemoClassWhichSolvesProblemButWithoutUnnededFunctions(object):
    def __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

    def controls(self, attribute_value_pair):
        eval_string = attribute_value_pair[0] + " = " + str(attribute_value_pair[1])
        exec(eval_string)


value1, value2, value3 = (1, 2, 3)
my_object = DemoClassWhichSolvesProblemButWithoutUnnededFunctions(0, 0, 0)

print "original values:", my_object.__dict__

inputs = {"A":["self.arg1", value1],
              "S":["self.arg2", value2],
              "D":["self.arg3", value3]}

my_object.controls(inputs["A"]) #my object, not my class...
my_object.controls(inputs["S"])
my_object.controls(inputs["D"])

#Even this one works:
my_object.controls( ("self.totally_new_attribute", "str('other value')") )


print "modified values:", my_object.__dict__

exectakes a string and treats it like a command line written here - which could cause some harm! But I assume you are looking for a solution like this...

نصائح أخرى

I am not sure if I get your question right, but I think what you try to do only can be done in one of the following ways:

  1. Provide the name of the attribute to be set:

    def controls(self, instructions):
        setattr(self, instructions[0], instructions[1])
    
    my_class = Class(arg1, arg2, arg3)
    
    inputs = {"A": ['arg1', value1],
              "S": ['arg2', value2],
              "D": ['arg3', value3]}
    
    my_class.controls(inputs["A"])
    
  2. Provide setter functions:

    def attrsetter(attribute):
        def realsetter(target, value):
            setattr(target, attribute, value)
    
    def controls(self, instructions):
        instructions[0](self, instructions[1])
    
    my_class = Class(arg1, arg2, arg3)
    
    inputs = {"A": [attrsetter('arg1'), value1],
              "S": [attrsetter('arg2'), value2],
              "D": [attrsetter('arg3'), value3]}
    
    my_class.controls(inputs["A"])
    

(I thought the 2nd example wiuld turn out to be simpler, but it is even more complicated now as I wrote it. But I leave it here for now...)

In both cases, I give instructions how to modify the named attribute of the object.

The ways you are trying to accomplish don't work, as this would need pointers, which don't exist in Python.

Now that I think of it, there is one more way to do it. It is elegant, but complicated as well:

def controls(self, instructions):
    # Call the given setter function which acts on the object it is given as a target.
    instructions(self)

my_class = Class(arg1, arg2, arg3)

def set_input(mapping, letter, value):
    def value_setter(func, value):
        def replacement(target):
            func(target, value)
        return replacement
    def outer_wrapper(func):
        mapping[letter] = value_setter(func, value)
    return outer_wrapper

inputs = {}

@set_input(inputs, "A", value1)
def set_arg1(target, value):
    target.arg1 = value

@set_input(inputs, "S", value2)
def set_arg2(target, value):
    target.arg2 = value

@set_input(inputs, "D", value3)
def set_arg3(target, value):
    target.arg3 = value

my_class.controls(inputs["A"])

It works this way: Each of the setter functions is decorated with what the outer function (decorator creating function) set_input() returns: a decorator taking a func, wrapping it into another layer of a function and putting that into the dict.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top