Python, best way to return/handle complex data from a method
I need to handle a bunch of similar but exclusively ca开发者_如何学Golled function from a single method. e.g. (maybe not a great example)
class Util(object):
def method1(self):
return "method1", [1,2,3]
def method2(self):
return "method2", {"1":4, "2":5, "3":6}
def method3(self):
return [1,2,3], "method3", {"1":4, "2":5, "3":6}
def call_method(self, method_func):
if method_func.__name__ == "method1":
(name, dict_values) = self.method_func()
if method_func.__name__ == "method2":
(name, list_values) = self.method_func()
if method_func.__name__ == "method3":
(list_values, name, dict_values) = self.method_func()
# How best to manage a return for 3 optional, but not inter-dependent values?
return name, dict_values, list_values
if __name__ = "__main__":
u = Util()
(name, dict_values, list_values) = u.call_method(Util.method1)
The call_method() return is what I'm trying to visualize here. I've got a bunch of exclusive sub-calls I need to make and I need to massage them into something that can be returned.
Would it be easier to just stuff them into Util class member variables? And whoever implements u.call_method() will simply need to know what to look for?
Before anyone complains about the design in the first place, it's not mine. I simply need to expose a consistent API and an interested to hear opinons on how to handle a return like this. It's not easily normalized, and though a missing trailing return value will pass the Runtime, a leading one won't.
Any tips would be great! Thank you.
namedtuple is very Pythonic alternative for returning "nameless" tuples
http://docs.python.org/library/collections.html#collections.namedtuple
This way the caller does not need to extract all tuple members if it needs read only some of them.
If you need to group several values often an approach is using a dictionary... i.e. changing your code to:
...
def method1(self):
return {"name": "method 1",
"list": [1, 2, 3]}
Something that is possible in Python is to use an object instead of a dictionary to make the code nicer to read:
class Bunch:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
...
def method1(self):
return Bunch(name="method1",
list=[1, 2, 3])
so that the caller can use result.name
instead of result["name"]
.
Another option that recently got standardized in Python is the NamedTuple.
If you can modify the methods:
class Util(object):
def method1(self):
return "method1", [1,2,3], None
def method2(self):
return "method2", None, {"1":4, "2":5, "3":6}
def method3(self):
return "method3", [1,2,3], {"1":4, "2":5, "3":6}
def call_method(self, method_func):
return method_func(self)
if __name__ == "__main__":
u = Util()
(name, dict_values, list_values) = u.call_method(Util.method1)
# better:
print u.method1()
And if you can not change:
class Util(object):
def method1(self):
return "method1", [1,2,3]
def method2(self):
return "method2", {"1":4, "2":5, "3":6}
def method3(self):
return "method3", [1,2,3], {"1":4, "2":5, "3":6}
def call_method(self, method_func):
results = method_func(self)
name = list_ = dict_ = None
for obj in results:
if isinstance(obj, string):
name = obj
elif isinstance(obj, list):
list_ = obj
elif isinstacne(obj, dict):
dict_ = obj
return name, dict_, list_
if __name__ == "__main__":
u = Util()
(name, dict_values, list_values) = u.call_method(Util.method1)
精彩评论