静态成员的引用方法

时间:2015-07-03 06:45:33

标签: python

所以我有一个带有几个(普通)方法的类。根据我想要调用不同方法的值。选择方法的这种行为是静态的(对于类的所有实例化都是一样的。你会如何推荐这样做?

如果实例化的状态是常量并且在初始化后永远不会改变,那么答案会以最佳方式改变吗?

示例:

PLUS = 0
MINUS = 1
OPERATIONS = [PLUS, MINUS]

class Generator(object):

    operations = {
        PLUS: self.plus,    # Not possible
        MINUS: self.minus,
    }

    def __init__(self, state):
        self._state = state

    def plus(self, a, b):
        # Depends on state
        return a + b

    def minus(self, a, b):
        return a - b if self._state else b - a

    def generate(self):
        a, b = give_me_numbers()
        for op in OPERATIONS:
            print self.operations[op](a, b)

4 个答案:

答案 0 :(得分:1)

一种选择是将操作转换为方法:

    def operations(self, op):
        dictMethods = {
            "PLUS" : self.plus
            "MINUS" : self.minus
        }
        return dictMethods[op]

然后称之为:

self.operations(op)(a, b)

答案 1 :(得分:1)

PLUS = 0
MINUS = 1
OPERATIONS = [PLUS, MINUS]

class Generator:
    operations = {}

    def __init__(self, state):
        self._state = state

    @classmethod
    def init_operations(cls):
        cls.operations = {
            PLUS:  cls.plus,    
            MINUS:  cls.minus
        }

    def plus(self, a, b):
        # Depends on state
        return a + b

    def minus(self, a, b):
        return a - b if self._state else b - a


    def generate(self):
        a, b = 5, 10
        for op in self.operations:
            print( self.operations[op](self, a, b) )

gen = Generator(1)
gen.init_operations()
gen.generate()

为了让operations存储类定义的函数,它不能像你所做的那样在类的顶部完成。这是因为解析器找不到你所引用的函数,因为它还没有解析它们。所以我添加了一个'静态'init_operations()。

注意这些操作存储为未绑定的方法(因为它是从静态内部调用的);因此,在调用这些函数时,必须包含self变量作为第一个参数。

答案 2 :(得分:1)

您想要做的事情实际上是有效的(不需要更复杂的解决方案),但您必须(1)正确地编写operations的字典定义(使用:而不是{ {1}})和(2)在可以理解时定义它的定义(在它所引用的方法定义之后):

=

附注:

  • 请注意Python 3中的PLUS = 0 MINUS = 1 OPERATIONS = [PLUS, MINUS] class Generator(object): def __init__(self, state): self._state = state def plus(self, a, b): # Depends on state return a + b def minus(self, a, b): return a - b if self._state else b - a def generate(self): a, b = give_me_numbers() for op in OPERATIONS: print operations[op](a, b) operations = { # plus and minus are defined, at this point PLUS: plus, MINUS: minus } 语法(不是Generator(object)) - 或简称Generator()

  • 您可能需要查看Generator模块,该模块处理您以干净方便的方式定义的常量enumPLUSMINUS

PS :正如PM 2Ring所指出的那样,使用OPERATIONS中的值可以通过operations完成。我个人会self.operations[op](self, a, b),因为Generator.operations[op](self, a, b)并非特定于任何实例,而是与operations类相关联的字典。

答案 3 :(得分:1)

这是对Richard代码的轻微修改,该代码会在您第一次实例化init_operations时自动调用Generator方法。

class Generator:
    def __init__(self, state):
        self._state = state
        if not hasattr(self, 'operations'):
            self.init_operations()

    @classmethod
    def init_operations(cls):
        cls.operations = {
            PLUS: cls.plus,
            MINUS: cls.minus,
        }

    def plus(self, a, b):
        # Depends on state
        return a + b

    def minus(self, a, b):
        return a - b if self._state else b - a

    def generate(self):
        a, b = give_me_numbers()
        for op in self.operations:
            print self.operations[op](self, a, b)

这是使operations成为普通实例属性的替代方案。这浪费了一点空间,但这意味着您在调用操作时不需要显式传递self

class Generator(object):
    def __init__(self, state=False):
        self._state = state
        self.operations = {
            PLUS: self.plus,
            MINUS: self.minus
        }

    def plus(self, a, b):
        # Depends on state
        return a + b

    def minus(self, a, b):
        return a - b if self._state else b - a

    def generate(self):
        a, b = give_me_numbers()
        for op in OPERATIONS:
            print self.operations[op](a, b)

最后,此变体使用方法名称来识别操作而不是整数。

#!/usr/bin/env python

from random import seed, randint

def give_me_numbers():
    a, b = randint(1, 99), randint(1, 99)
    print 'a=%d, b=%d' % (a, b)
    return a, b


OPERATIONS = ('plus', 'minus')

class Generator(object):
    def __init__(self, state=False):
        self._state = state

    def plus(self, a, b):
        # Depends on state
        return a + b

    def minus(self, a, b):
        return a - b if self._state else b - a

    def operations(self, op):
        return getattr(self, op)

    def generate(self):
        a, b = give_me_numbers()
        for op in OPERATIONS:
            #print getattr(self, op)(a, b)
            print self.operations(op)(a, b)    

seed(42)

g1 = Generator(False)
g1.generate()

g2 = Generator(True)
g2.generate()

<强>输出

a=64, b=3
67
-61
a=28, b=23
51
5

相反,您可以直接致电operations。 OTOH,如果你想从课堂外调用它, 更清洁,可以提供getattr(self, op)(a, b)方法。