默认方法python

问题描述:

有没有比使用inspect模块更清晰的方法来获取方法的默认值?我想这样做:默认方法python

class C(object): 
    def __init__(self,Type='generic',X=5,Y=500): 
     defaults=getDefaults() #not sure about this line 
     typeDefaults_X={'short':'1','long':'10'} 
     typeDefaults_Y={'large':2000,'small':100} 
     if X == defaults['X']: 
      X = typeDefaults_X.get(Type, defaults['X']) 
     if Y == defaults['Y']: 
      Y = typeDefaults_Y.get(Type, defaults['Y']) 

我知道我可以做到这一点:

defaults=dict(zip(inspect.getargspec(C.__init__).args[1:],inspect.getargspec(C.__init__).defaults)) 

但似乎如此可怕未Python的。

+0

有什么意义?你想做什么? – 2011-04-19 01:12:40

+1

你会想'=='而不是'is';例如注意'100000 + 1是100000 + 1'是假的,但是'100 + 1是100 + 1'是真的。 – ninjagecko 2011-04-19 01:32:48

+0

你的代码说的是“如果我们不为argN输入任何内容,将其设置为lookupTable [typeString];如果失败,将其设置为默认值”。不幸的是,这个接口没有意义,因为你只有1个typeString参数,但你的变量似乎都依赖于它,并且它们都有不同的键的单独查找表。你想做什么? – ninjagecko 2011-04-19 01:35:57

这不是真的我清楚你正在尝试做的。但是在该方法中,变量已经具有指定的默认值。但在我看来,在这种情况下你最好不要使用正式的默认参数。

class C(object): 

    def __init__(self, Type='generic', X=None, Y=None): 
     X = X or 5 
     Y = Y or 500 
     self.X, self.Y = { 
      "generic": (X, Y), 
      "short": (1, Y), 
      "long": (10, Y), 
      "large": (X, 2000), 
      "small": (X, 100), 
     }[Type] 

    def __str__(self): 
     return "X={0} Y={1}".format(self.X, self.Y) 


print(C()) 
print(C('short')) 
print(C('long')) 
print(C('large')) 
print(C('small')) 
print(C('small', 10)) 
print(C('small', 20, 20)) 

我觉得更清楚,但即使这样可能有点难以遵循。您可能会重新考虑您的界面。

+0

谢谢,我认为这可以工作。理想情况下,我想在这里保留正式的默认参数(带值)。我正在重新思考....也许孩子班? – 2011-04-19 18:04:51

+0

@亚当正是我在想什么。 :-)通常,如果您看到基于某个标志改变行为的方法,它应该被重构为子类。 – Keith 2011-04-19 18:49:14

它实际上比您想象的要糟糕。 Python区分位置参数与默认值和仅关键字参数。您的代码不仅会在您没有默认作为第二或第三个参数的情况下失败,而且如果您有可变长度的* args关键字,则代码也会失败。你也应该使用inspect.getfullargspec。

但是,根据help(inspect.getfullargspec),spec.defaults总是spec.args的最后一个元素。因此,你可以这样做:

import inspect 
def getDefaults(func): 
    spec = inspect.getfullargspec(func) 
    numDefaults = len(spec.defaults) 
    return dict(zip(spec.args[-numDefaults:], spec.defaults), **spec.kwonlydefaults) 

基本上,这正是你所做的,但更一般。

没有更好的办法。 (当然你可以使用func.__defaultsfunc.__kwdefaults__func.__code__.co_*,但这些都是真正的hackish,似乎一种内部的,检查是正确的做法。)

+0

附录:这似乎实际上是'pythonic'的定义:有一种方法可以做到这一点;这并不是说它不能大规模改善,仍然是'pythonic' – ninjagecko 2011-04-19 01:18:02