python类中的classmethod和helper函数

时间:2014-10-06 18:44:09

标签: python oop decorator

我的目标是减少我创建的类中的一些冗余。我已将问题简化为一个非常简单的例子

我目前的班级

class BigNumbers(object):
      def __init__(self, big_number):
            self.number = big_number

      @classmethod
      def make_with_sums(cls, sum_to):
            fin_num = 0

            for i in range(1, sum_to):
                  fin_num += i

            return cls( fin_num )

      @classmethod
      def make_with_product(cls, mul_to):
            fin_num = 1

            for i in range(1, mul_to):
                  fin_num *= i

            return cls( fin_num )

我想要的班级(DNRY)

class dnryNumbers(object):
      def __init__(self, big_number):
            self.number = big_number

      @classmethod
      def _make_with_helper(cls, make_meth, fin_num):
            method_dict = {'sum': lambda x, y: x + y,
                           'prod': lambda x, y: x * y
                           }
            var = 0
            for i in range(1, fin_num):
                  var = method_dict[make_meth](var, i)

            return cls( var )

      def make_with_sums(self, sum_to):

            return self._make_with_helper( 'sum', sum_to )

      def make_with_product(self, mul_to):

            return self._make_with_helper('prod', mul_to )

我的目标是使用与使用BigNumbers类时相同的函数调用,例如:

In [60]: bn = BigNumbers.make_with_product(10)

In [61]: bn.number
Out[61]: 362880

- 或 -

In [63]: bn = BigNumbers.make_with_sums(10)

In [64]: bn.number
Out[64]: 45

但目前的功能不起作用:

In [65]: bn = dnryNumbers.make_with_product(10)
TypeError: unbound method make_with_product() must be called with dnryNumbers instance as first argument (got int instance instead)

2 个答案:

答案 0 :(得分:1)

简单的答案:make_with_sumsmake_with_products是类方法,而不是实例方法,因此需要声明它们。另请注意,_make_with_helper也需要将起始值作为参数;将var初始化为0将使{{​​1}}返回make_with_product,无论其参数是什么。

无论将哪些输入传递给cls(0)

method_dict都是相同的字典,所以它应该是一个类变量:

_make_with_helper

但是现在,class dnryNumbers(object): def __init__(self, big_number): self.number = big_number method_dict = {'sum': lambda x, y: x + y, 'prod': lambda x, y: x * y } @classmethod def _make_with_helper(cls, make_meth, fin_num, starting_value): var = starting_value for i in range(1, fin_num): var = dnryNumbers.method_dict[make_meth](var, i) return cls( var ) @classmethod def make_with_sums(cls, sum_to): return cls._make_with_helper('sum', sum_to, 0) @classmethod def make_with_product(cls, mul_to): return cls._make_with_helper('prod', mul_to, 1) 只是添加了一个你不需要的额外的间接层。由于函数不打算在类之外使用,只需将它们定义为“私有”方法,并直接使用它们。

method_dict

@classmethod         def make_with_sums(cls,sum_to):             return cls._make_with_helper(dnryNumbers._sum,sum_to,0)

class dnryNumbers(object):
    def __init__(self, big_number):
        self.number = big_number

    @staticmethod
    def _sum(x, y):
        return x + y

    @staticmethod
    def _prod(x, y):
        return x * y

    @classmethod
    def _make_with_helper(cls, make_meth, fin_num, starting_value):        
        var = starting_value
        for i in range(1, fin_num):
              var = make_meth(var, i)
        return cls(var)

最后,值得指出的是,除非您的真实代码比此处显示的示例更复杂, @classmethod def make_with_product(cls, mul_to): return cls._make_with_helper(dnryNumbers._prod, mul_to, 1) 已作为_sum提供,operator.add仅为_prodoperator.mul只是_make_with_helper内置(或reduce,如果是Python 3)的重新实现。

functools.reduce

答案 1 :(得分:0)

解决方案1:

bn = dnryNumbers(5)
bn.make_with_product(10)

解决方案2:

@classmethod
def make_with_product(cls, mul_to):
    return cls._make_with_helper('prod', mul_to )