如何处理 Python 中的选项参数? (只能是一组值的参数)
How to handle option-arguments in Python? (arguments that can only be of a set of values)
由于我缺乏术语,我很难提出问题。我不是在询问具有默认值的关键字参数。我的问题是关于如何处理只能有一组值的参数值,以及如何优化代码可读性和防止重复。
例如看这个函数:
def foo(opt='something'):
if opt == 'something':
ret = dowhatever()
elif opt == 'somethingelse':
ret = dowhateverelse()
else:
raise UnrecognisedArgumentException(opt)
return ret
在我看来,这很丑陋。它基本上是 python 中不太好看的 java-switch 翻译。出现的一个问题是当案例在案例相关代码之间有公共代码(重复)时,我想避免这种情况。如果我要避免这种情况,我会写:
def foo(opt='something'):
if opt not in ['something', 'something_else']:
raise UnrecognisedArgumentException
if opt == 'something':
ret = do_whatever()
elif opt == 'something_else':
ret = do_whatever_else()
do_something_universal(ret)
if opt == 'something':
ret = do_whatever_afterwards()
elif opt == 'something_else':
ret = do_whatever_else_afterwards()
return ret
这个更丑。有没有更好的方式来编写这样的代码?
我正在重新打开这个问题(之前作为
)
为了解决两个之间有共同代码的具体问题
相关的类似案例的块。这涉及到上下文管理器的思想。
在这里,我们定义了两个不同的上下文管理器,并存储它们
在 dict
; case-statement-replacement 服务于 select
我们将使用哪个上下文管理器。
import contextlib
# Step 1: Define the context managers. Usingcontextlib.contextmanager for
# simplicity, but you can define a class with `__enter__` and `__exit__`
# methods as well.
@contextlib.contextmanager
def Something():
yield do_whatever()
do_whatever_afterwards()
@contextlib.contextmanager
def SomethingElse():
yield do_whatever_else()
do_whatever_else_afterwards()
# Step 2: Map your selectors to the context managers
cms = {
'something': Something,
'something_else': SomethingElse
}
# Step 3: Select a context manager and handle attempts to select a non-existent one
opt = ... # 'something' or 'something_else'
try:
cm = cms[opt]
except KeyError:
raise UnrecognisedArgumentException(opt)
# Step 4: Run your universal code in the correct context
with cm() as x:
do_something_universal(x)
由于我缺乏术语,我很难提出问题。我不是在询问具有默认值的关键字参数。我的问题是关于如何处理只能有一组值的参数值,以及如何优化代码可读性和防止重复。
例如看这个函数:
def foo(opt='something'):
if opt == 'something':
ret = dowhatever()
elif opt == 'somethingelse':
ret = dowhateverelse()
else:
raise UnrecognisedArgumentException(opt)
return ret
在我看来,这很丑陋。它基本上是 python 中不太好看的 java-switch 翻译。出现的一个问题是当案例在案例相关代码之间有公共代码(重复)时,我想避免这种情况。如果我要避免这种情况,我会写:
def foo(opt='something'):
if opt not in ['something', 'something_else']:
raise UnrecognisedArgumentException
if opt == 'something':
ret = do_whatever()
elif opt == 'something_else':
ret = do_whatever_else()
do_something_universal(ret)
if opt == 'something':
ret = do_whatever_afterwards()
elif opt == 'something_else':
ret = do_whatever_else_afterwards()
return ret
这个更丑。有没有更好的方式来编写这样的代码?
我正在重新打开这个问题(之前作为
dict
; case-statement-replacement 服务于 select
我们将使用哪个上下文管理器。
import contextlib
# Step 1: Define the context managers. Usingcontextlib.contextmanager for
# simplicity, but you can define a class with `__enter__` and `__exit__`
# methods as well.
@contextlib.contextmanager
def Something():
yield do_whatever()
do_whatever_afterwards()
@contextlib.contextmanager
def SomethingElse():
yield do_whatever_else()
do_whatever_else_afterwards()
# Step 2: Map your selectors to the context managers
cms = {
'something': Something,
'something_else': SomethingElse
}
# Step 3: Select a context manager and handle attempts to select a non-existent one
opt = ... # 'something' or 'something_else'
try:
cm = cms[opt]
except KeyError:
raise UnrecognisedArgumentException(opt)
# Step 4: Run your universal code in the correct context
with cm() as x:
do_something_universal(x)