static method as default parameter to a class meth

2019-04-10 12:43发布

问题:

My question is about two answers to another question: Using class/static methods as default parameter values within methods of the same class.

I am trying to understand if there's really a difference between what the two answers do, and if so, what's the pros and cons of each.

Question: how to use a class method as a default parameter to a method in the same class.

Answer 1: use a function instead of a class method

class X:
    def default_func(x):
        return True

    def test(self, func = default_func):
        return func(self)

Answer 2: use a class method, but convert it to a function

def unstaticmethod(static):
    return static.__get__(None, object)

class X:
    @staticmethod
    def default_func(x):
        return True

    def test(self, func = unstaticmethod(default_func)):
        return func(self)

This was originally written in Python 2, but my summary is (hopefully) Python 3.

回答1:

The answer really depends on what other intentions you have for X.default_func. If you intend for X.default_func to be called outside of an instance of X, then you want it to be a static method (Answer 2).

# in other code...
some_object = "Bring out your dead"
X.default_func(some_object)

If, on the other hand, you don't expect that default_func will ever be called except within an instance of X (and of course used as the default for test), I would re-write Answer 1 to be a proper method (and use the convention of self).

class X:
    def default_func(self):
        return True

    def test(self, func = default_func):
        return func(self)

As a side note, I'd like to point out that you could have written Answer 2 differently to avoid the unstaticmethod:

class X:
    def default_func(x):
        return True

    def test(self, func = default_func):
        return func(self)

    default_func = staticmethod(default_func)

The reason that works is because class X isn't created (and default_func doesn't become a method of X) until after the entire block beneath class X: is processed (including the default argument for test(func)).