【问题标题】:Python: pass string to be referenced in class (self.string)Python:传递要在类中引用的字符串(self.string)
【发布时间】:2014-05-13 18:16:15
【问题描述】:

我有一个 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"])

所以字典(“输入”)映射键盘敲击。根据按下的键,我需要编辑my_class的一些属性。

我要做的是:将需要根据击键编辑的值传递给 def controls(self, instructions)。因此,例如,如果用户按下“A”,那么我想将 self.arg1 从它现在拥有的任何值更改为 value1。同样,如果他按“S”,我想将另一个属性编辑到另一个,等等。

如果我这样做:

print instructions

我得到了按键“A”:

[self.arg1, value1]

因此,例如,如果用户按下了“A”、“S”和“D”,一旦所有这些都在这里解决,my_class 应该是这样的:

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

我做了各种尝试,但没有一个能够真正改变 self.argX 的值,它们要么给我一个错误,要么没有完成任何有用的事情。

我目前正在做一堆 If/elif ,但这越来越长了。

所以我的核心问题是:

如何作为参数传递 instruction[self.arg1, value1] 并让程序编辑我在 instruction[0] 中提供的任何属性并设置其值我在 my_class 的 instruction[1] 中给出的任何值?

编辑:在下面的 cmets 之后删除了与问题核心无关的细节。

【问题讨论】:

  • 很抱歉,您的代码或您的解释都没有多大意义……以至于我什至不知道该要求您改进什么。
  • 你能举例说明你想要的结果吗? some_other_args[] 应该是什么意思?
  • 我建议您退后一步,从更大的角度描述您要解决的问题。
  • 那么代码当前正在使用 If/elif(因此每个可能的按键对应于一个 If/elif 语句,然后执行结果为 True 的任何一个)。但我不喜欢它,因为它变得很长,很难看到按键的作用。同样在实际程序中,参数是列表,以这种方式放置可以更容易地循环它们,因为这样我只需在 def controls() 中编写一次 FOR 循环,它就会循环遍历我传递的任何内容一个参数并相应地设置值。

标签: python class dictionary


【解决方案1】:

我想你正在寻找这样的东西:

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接受一个字符串并将其视为此处编写的命令行 - 这可能会造成一些伤害!但我假设您正在寻找这样的解决方案......

【讨论】:

  • 我看不到退出的必要性,只有在绝对没有其他特别容易的方式时才应该使用退出。
  • 这就是我想做的,确实,它工作得很好,非常感谢!现在,我同意潜在的危害,但在程序中用户无法通过此输入诱导恶意代码。话虽这么说,这是要记住的。
【解决方案2】:

我不确定我的问题是否正确,但我认为您尝试做的事情只能通过以下方式之一来完成:

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

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

它是这样工作的:每个 setter 函数都用外部函数(装饰器创建函数)set_input() 返回的内容进行装饰:装饰器采用 func,将其包装到函数的另一层并将其放入字典。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 2010-12-24
    • 2010-11-19
    • 2018-12-07
    • 1970-01-01
    • 2016-04-09
    相关资源
    最近更新 更多