为什么我们在Python中命名staticomethod?

时间:2017-04-02 23:28:17

标签: python static-methods

class A(object):
    def __init__(self, val):
        self.val = A.plus_one(val)

    @staticmethod
    def plus_one(val):
        return val + 1

我们可以在类中定义静态方法并在任何地方使用它。我的问题是,为什么我们必须命名静态方法,即使我们在这个类中使用这个静态方法,也就是在方法名称之前添加A.

我的想法是,我们是否可以简单地更改机制,以便类中的静态方法名称不必像以下那样是名称空间:(尽管Python现在不支持它):

class A(object):
    def __init__(self, val):
        self.val = plus_one(val)

    @staticmethod
    def plus_one(val):
        return val + 1

我的直觉是,既然我们在课堂上打电话,班级成员的优先级应该高于全局职能,因此不会有任何歧义。为什么Python强迫我们命名它呢?

1 个答案:

答案 0 :(得分:1)

除了直接在类命名空间中运行的代码(不在另一个方法内部)之外,通过裸名称无法访问类中定义的方法。如果要调用方法,通常需要在某种对象(实例或类本身)上查找它。对于不同类型的查找,不同类型的方法在行为方式上有所不同。

class Test(object):
    def normal_method(self, foo):
        print("normal_method", self, foo)
        # none of the method names are valid here as bare names, only via self or Test
        try:
            class_method(type(self), foo) # raises NameError
        except NameError:
            pass

        self.class_method(foo) # this works
        Test.class_method(foo) # so does this

    @classmethod
    def class_method(cls, foo):
        print("class_method", cls, foo)
        # from a class method, you can call a method via the automatically provided cls
        cls.static_method(foo)

    @staticmethod
    def static_method(foo):
        print("static_method", foo)
        # a static method can only use the global class name to call other methods
        if isinstance(foo, int) and foo > 0:
            Test.static_method(foo - 1)

    # Class level code is perilous.
    #normal_method('x', 2) # could work in Python 3 (Python 2 checks the type of self)
                           # but it probably won't be useful (since self is not an instance)
    #class_method('x', 2) # Won't work. A classmethod descriptor isn't directly callable
    #staticmethod(2)      # Nor is a staticmethod

# Top level code (these are all valid)
Test().normal_method(2) # also could be Test.normal_method(Test(), 2)
Test.class_method(2)  # could also be Test().class_method(2) (type of the instance is used)
Test.static_method(2) # could also be Test().static_method(2) (instance is ignored)