所以我有一个带有几个(普通)方法的类。根据我想要调用不同方法的值。选择方法的这种行为是静态的(对于类的所有实例化都是一样的。你会如何推荐这样做?
如果实例化的状态是常量并且在初始化后永远不会改变,那么答案会以最佳方式改变吗?
示例:
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)
答案 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
模块,该模块处理您以干净方便的方式定义的常量enum
,PLUS
和MINUS
。
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)
方法。