我有一个Python类,我们将其命名为MyClass
,它带有几个绑定方法。我需要一种称为.dynamic_method()
的方法的行为,这取决于对象创建过程中参数集的值。 dynamic_method
会有少量变体,它们之间将共享很少的代码,因此将它们定义为单独的函数/方法而不是将其定义为具有许多选项和条件的单个大型方法是有意义的。创建对象后,我不需要更改此方法的行为,可以在__init__()
期间进行所有设置。
作为参考,MyClass
管理数据集,.dynamic_method
处理此数据的某些IO方面,这些方面随数据集和上下文而变化。
这在技术上并不难实现,但是我想出的所有方法都不完全正确:
__init__()
期间使用此处描述的方法之一将它们之一作为绑定方法附加:Adding a Method to an Existing Object Instance。对我来说,这似乎是最自然的选择,但是该主题中的许多答案都强烈建议不要使用此模式。.dynamic_method_a
,.dynamic_method_b
等,并设置一个选项/别名,以便MyClass.dynamic_method()
调用正确的方法。这将导致很长的类定义,并且每个对象都有许多未使用的方法。.dynamic_method()
仅将self
作为第一个参数来调用正确的函数。感觉是对方法概念的故意滥用,会破坏掉毛。什么被认为是实现此行为的最“ Pythonic”方式?以上方法之一,还是我想念的明显替代方法?
答案 0 :(得分:3)
我认为您使这个问题过于复杂了。
如果您没有重要的理由来更改method属性(第一个选项),那么我会在glControl = new GLControl(new OpenTK.Graphics.GraphicsMode(32, 24, 0, 8));
中编写一个不错的if-else来调用其他函数(第三个选项),或者我真的很想像我要像这样dynamic_method()
做一个临时的开关盒:
dict
答案 1 :(得分:1)
我建议工厂,确实会增加复杂性,但是我要指出一些优点。
代码示例:
class DataStruct:
def __init__(self, input_: str):
self.Field = input_
class MyClass:
def __init__(self, data: DataStruct):
self.Data: DataStruct = data
def dynamic_method(self):
# Abstract Method
pass
def __str__(self):
return self.Data.Field
class MyClassFunctionalityOne(MyClass):
def __init__(self, data: DataStruct):
super().__init__(data)
def dynamic_method(self):
self.Data.Field = self.Data.Field.upper()
class MyClassFunctionalityTwo(MyClass):
def __init__(self, data: DataStruct):
super().__init__(data)
def dynamic_method(self):
self.Data.Field = "and now for something completely different"
class MyClassFactory:
def __init__(self):
pass
@classmethod
def manufacture(cls, input_: DataStruct) -> MyClass:
#replace this if..elif chain to contain the tests on the data you need for determine the right method
if input_.Field.count('one') > 0:
obj: MyClass = MyClassFunctionalityOne(input_)
elif input_.Field.count('two')> 0:
obj: MyClass = MyClassFunctionalityTwo(input_)
else:
obj = None
return obj
# script starts here
received_data = DataStruct('This kind of data should result in functionality one')
object1 = MyClassFactory.manufacture(received_data)
received_data = DataStruct('This kind of data should result in functionality two')
object2 = MyClassFactory.manufacture(received_data)
print (type(object1))
print (type(object2))
print ('*'*5, 'objects before dynamic_method', '*'*5)
print (object1)
print (object2)
object1.dynamic_method()
object2.dynamic_method()
print ('*'*5, 'objects after dynamic_method', '*'*5)
print (object1)
print (object2)
输出:
<class '__main__.MyClassFunctionalityOne'>
<class '__main__.MyClassFunctionalityTwo'>
***** objects before dynamic_method *****
This kind of data should result in functionality one
This kind of data should result in functionality two
***** objects after dynamic_method *****
THIS KIND OF DATA SHOULD RESULT IN FUNCTIONALITY ONE
and now for something completely different
答案 2 :(得分:1)
我宁愿选择选项3,因为我发现它更干净,但这取决于您需要多少个实现变体。选项4(使用工厂)也不错,但是它将生成更多代码。另一方面,选项4更具可扩展性和可维护性。
因此,由于您想更改dynamic_method()
中__init__()
的行为,因此可以这样做:
class MyClass(object):
def __init__(self, param=None):
self.dynamic_method = {
"a": self.dynamic_a,
"b": self.dynamic_b,
"c": self.dynamic_c}[param]
def dynamic_a(self):
print("a functionality")
def dynamic_b(self):
print("b functionality")
def dynamic_c(self):
print("c functionality")
>> m = MyClass("b")
>> m.dynamic_method()
b functionality