Python: 传递字符串在类中引用 (self.string)

0 投票
2 回答
7175 浏览
提问于 2025-04-18 06:26

我有一个关于Python的问题。

假设我们有这样一个类:

class Class:

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

******* 这一部分我不太确定怎么写 **

    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"])

这个字典(“inputs”)用来记录键盘按键。根据按下的键,我需要修改我这个类的一些属性。

我想做的是:把需要根据按键修改的值传给 def controls(self, instructions)。比如说,如果用户按下“A”,那么我想把 self.arg1 的值改成 value1,无论它现在是什么值。类似的,如果按下“S”,我想把另一个属性改成另一个值,等等。

所以如果我这样做:

print instructions

当按下“A”键时,我得到:

[self.arg1, value1]

举个例子,如果用户按下了“A”、“S”和“D”,在所有这些都处理完后,我的类应该是这样的:

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

我尝试了很多方法,但都没能成功改变 self.argX 的值,要么出错,要么没什么用。

我现在在用很多的 If/elif,但这样写太长了。

所以我最核心的问题是:

我怎么能把 instruction[self.arg1, value1] 作为参数传入,让程序根据 instruction[0] 修改我类中的某个属性,并把它的值设置为 instruction[1] 中的值呢?

编辑:根据下面的评论,去掉了一些与问题核心无关的细节。

2 个回答

0

我不太确定我是否理解你的问题,但我觉得你想做的事情只能通过以下几种方式来实现:

  1. 提供要设置的属性名称:

    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. 提供设置函数:

    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"])
    

(我原以为第二个例子会更简单,但写下来后发现其实更复杂。不过我先把它留在这里…)

在这两种情况下,我都给出了如何修改对象中指定属性的说明。

你尝试的方法是行不通的,因为这需要指针,而Python中并没有指针的概念。

现在想想,还有一种方法可以做到。这种方法优雅,但也比较复杂:

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"])

它的工作原理是这样的:每个设置函数都被一个外部函数(创建装饰器的函数)set_input() 返回的装饰器装饰,这个装饰器接收一个func,将其包裹在另一个函数层中,并把这个层放入字典中。

2

我想你是在寻找类似这样的东西:

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__

exec这个命令会把你给的字符串当成命令行来执行,这样可能会带来一些风险!不过我猜你是在找这样的解决方案……

撰写回答