开发者

defaults of method python

开发者 https://www.devze.com 2023-02-26 07:42 出处:网络
Is there a cleaner way to get the defaults of a method than using the inspect module? I\'d like to do this:

Is there a cleaner way to get the defaults of a method than using the inspect module? I'd like to do this:

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(T开发者_如何学Pythonype, defaults['Y'])

I know that I could do this by:

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

but it seems so terribly un-pythonic.


It's not really clear to me what you are trying to do. But in the method, variable already has the specified default value. But it seems to me that you would be better off not using formal default arguments in this case.

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))

Is clearer I think, but even this can be a little hard to follow. You might rethink your interface.


It's actually slightly worse than you think. Python distinguishes between a positional arg with defaults and a keyword-only arg. Your code fail not only in cases where you don't have a default as your second or third arguments, but also if you have a variable-length *args keyword. You should also use inspect.getfullargspec.

However, according to help(inspect.getfullargspec), the spec.defaults are always the last elements of the spec.args. Thus you can do this:

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

Basically, this is exactly what you did, but a bit more general.

There is no better way. (Well you could use func.__defaults, func.__kwdefaults__, func.__code__.co_*, but those are really hackish and seem to kind of internals. Inspect is the right way.)

0

精彩评论

暂无评论...
验证码 换一张
取 消