正如@Jan-PhilipGehrcke 指出的那样,pythonic
很难量化。对我来说这意味着:
- 易于阅读
- 易于维护
- 简单胜于复杂胜于复杂
- 等等,等等(查看
Zen of Python
完整列表,您可以通过import this
在解释器中输入来获得)
因此,最 Pythonic 的解决方案取决于您必须为每个受支持的初始化程序做什么,以及您拥有多少个初始化程序。我会说,如果你只有少数几个,并且每一个都可以通过几行代码来处理,那么使用isinstance
and __init__
:
class MyClass(object):
def __init__(self, initializer):
"""
initialize internal data structures with 'initializer'
"""
if isinstance(initializer, dict):
for k, v in itit_dict.items():
# do something with k & v
setattr(self, k, v)
elif isinstance(initializer, (list, tuple)):
for item in initializer:
setattr(self, item, None)
另一方面,如果您有许多可能的初始化程序,或者其中任何一个需要大量代码来处理,那么您将希望classmethod
为每种可能的初始化类型都有一个构造函数,最常见的用法是__init__
:
class MyClass(object):
def __init__(self, init_dict={}):
"""
initialize internal data structures with 'init_dict'
"""
for k, v in itit_dict.items():
# do something with k & v
setattr(self, k, v)
@classmethod
def from_sequence(cls, init_list):
"""
initialize internal data structures with 'init_list'
"""
result = cls()
for item in init_list:
setattr(result, item, None)
return result
这使每个可能的构造函数都简单、干净且易于理解。
附带说明:使用可变对象作为默认值(就像我在上面__init__
所做的那样)需要小心;原因是默认值只评估一次,然后无论结果如何,都将用于每次后续调用。只有当您在函数中修改该对象时,这才是一个问题,因为这些修改将在每个后续调用中看到——除非您想要创建一个可能不是您正在寻找的行为的缓存。这对我的示例来说不是问题,因为我没有修改init_dict
,只是迭代它(如果调用者没有替换它,因为它是空的,这是一个无操作)。