是否有任何惯用的方法在Python中添加对象的方法?

时间:2015-05-18 07:38:51

标签: javascript python idioms

例如,我必须使用一些基本的数学运算来计算:

class Power_calc():
    def calculate(self, exp):
        self.srt = exp.split(" ")
        self.x = float(self.srt[0])
        self.y = float(self.srt[2])
        operand = self.srt[1]
        if operand == '+':
            return self.summ(self.x, self.y)
        elif operand == "-":
            return self.minus(self.x, self.y)

    def summ(self, a, b):
        return a + b

    def minus(self, a, b):
        return a - b

calc1 = Power_calc()
print calc1.calculate("3.2 + 6.0")

有没有办法在字典中对所有计算器方法进行分组,就像在Javascript中完成一样(例如下面的代码):

function powerCalculator() {
var methods = { //adding all methods here
    '+': function(a, b) {
        return a + b;
    },
    '-': function(a, b) {
        return a - b;
    }
};
this.calculate = function(expression) {
    var arr = expression.split(' '),
    a = +arr[0],
    b = +arr[2],
    operand = arr[1]
    return methods[operand](a, b);
}

2 个答案:

答案 0 :(得分:2)

是的,你可以这样做。 Python函数是第一类对象,因此您可以像在JavaScript中一样将它们存储在字典中。

如果要在线定义函数,可以使用lambdas:

methods = {
    '+': lambda a, b: a + b,
    # ...
}

或以其他方式仅引用外部函数:

def plus(a, b): return a + b

methods = {
    '+': plus,
    # ...
}

请注意,方法只是包装函数(存储self引用);您可以在字典中使用self.summself.minus来存储绑定的方法:

class Power_calc():
    def calculate(self, exp):
        methods = {
            '+': self.summ,
            '-': self.minus,
        }

        self.srt = exp.split(" ")
        self.x = float(self.srt[0])
        self.y = float(self.srt[2])
        operand = self.srt[1]
        return methods[operand](self.x, self.y)

    def summ(self, a, b):
        return a + b

    def minus(self, a, b):
        return a - b

更简单的是,您可以在operator module处使用预定义的操作函数:

import operator

methods = {
    '+': operator.add
    # ...
}

答案 1 :(得分:0)

您在JS中所做的不是添加方法,它只是创建从名称到函数的映射,然后您可以在calculate方法中明确使用。你可以在Python中完成同样的事情(并且使用较少的样板,来启动):

class PowerCalculator(object):
    methods = {
        '+': (lambda a, b: a + b),
        '-': (lambda a, b: a - b)
    }
    def calculate(self, expression):
        arr = expression.split(' ')
        a = float(arr[0])
        b = float(arr[2])
        op = arr[1] # note that this is the operator, not the operand
        return self.methods[op](a, b)

这与你在JS中所做的完全完全相同,但它非常接近。在JS中,您创建了一个范围,其中定义了methods变量,然后将原型的calculate方法定义为该范围内的闭包。虽然您可以在Python中执行此操作,但您不必这样做,因为您拥有class语句,该语句创建专门用于定义方法和其他类属性的范围,因此您可以正常定义methods并将其作为属性进行访问。

如果您确实要将summminus定义为方法,而不是将lambda定义为内联函数,则可以。但是,您可能希望它们为@staticmethod - 毕竟,他们不会对self做任何事情。

如果你真的希望它们成为常规方法,你甚至可以这样做。但是你在dict中的内容将是未绑定的方法,这意味着你必须明确地传递self来调用它们。像这样:

class PowerCalculator(object):
    def summ(self, a, b):
        return a + b

    def minus(self, a, b):
        return a - b

    methods = {
        '+': summ,
        '-': minus
    }

    def calculate(self, expression):
        arr = expression.split(' ')
        a = float(arr[0])
        b = float(arr[2])
        op = arr[1] # note that this is the operator, not the operand
        return self.methods[op](self, a, b)

但添加这种额外的复杂性确实没有优势。