在Python中为静态方法选择的语法如何?

我一直在使用Python一段时间,我发现将方法声明为静态的语法是特殊的。

将会声明一个常规方法:

def mymethod(self, params)
   ...
   return

声明了一个静态方法:

def mystaticethod(params)
   ...
   return
mystaticmethod = staticmethod(mystaticmethod)

如果你不添加静态方法行,编译器会抱怨自己失踪。

这是一种非常简单的非常复杂的方式,在其他语言中只需使用关键字和声明语法即可。 任何人都可以告诉我这个语法的演变吗? 这仅仅是因为课程被添加到现有的语言中?

由于我可以将静态方法行移到课程后面,这也表明解析器在簿记上工作特别辛苦。

请注意,我知道稍后添加的装饰器语法,我很想知道从语言设计角度来看原始语法是如何产生的。 唯一我能想到的是staticmethod应用程序调用一个将函数对象转换为静态方法的操作。


静态方法在类之后很长时间被添加到Python中(类很早就加入了,可能甚至在1.0之前;静态方法直到某个时候才出现在2.0左右)。 它们是作为普通方法的修改而实现的 - 您从函数创建静态方法对象以获取静态方法,而编译器默认生成实例方法。

就像Python中的很多东西一样,静态方法被引入并随着人们使用它们而改进,并希望更好的语法。 最初的一轮是引入语义的一种方式,不需要为语言添加新的语法(并且Python对语法的改变非常有抵抗力)。 我不是Guido,所以我不确定他脑子里发生了什么,这是有点投机的,但是Python随着他们获得更多经验而趋于缓慢地移动,渐进地发展并且改进事物(特别是,他们不喜欢增加一些东西,直到他们找到了正确的方式去做。这可能就是为什么从一开始就没有特别的静态方法的语法)。

正如mjv指出的,现在有一种更简单的方法,通过2.2或2.3中添加的一些语法糖称为“装饰器”:

@staticmethod
def mystaticmethod(params)
    ...
    return

@staticmethod语法是在方法定义之后放置mystaticmethod = staticmethod(mystaticmethod)糖。


voyager和adurdin在他们之间做了一个很好的工作来解释发生了什么:随着Python 2.2中引入新的类和描述符,出现了新的和深层的语义可能性 - 最明显有用的例子(静态方法,类方法,属性)由内置的描述符类型支持,没有任何新的语法(一旦新的描述符已经充分证明了它们的真实世界的有用性,则修饰器的语法@foo被添加了几次发布。 我并没有真正的资格去引导Guido(当你需要他的时候Tim Peters在哪里 - ),但我当时已经是一个Python提交者并且参与了这些发展,我可以证实这确实是发生了什么事情。

旅行者对这件事的观察让他想起C是正确的:我一直声称,Python比任何模仿C语法的语言都更能抓住“C的精神”(括号,if / while后面的括号等)。 “C的精神”实际上是在ISO C标准的(非规范性)原理部分中描述的,它包含五个原则(其中没有一个需要花括号!),我声称Python匹配4.5(有几个视频我在“Python for Programmers”上发表的介绍我的网站,如果你对此感兴趣的话,我会介绍它)。

特别是,C的精神“只提供一种操作方式”与Python的Zen的“应该有一个 - 并且最好只有一个 - 明显的方式来做到这一点” - 以及C和Python,我相信,是唯一明确采用统一和非冗余设计理念的两种广泛语言(这是理想的,不能明智地达到100% - 例如,如果a和b是整数,a + b和b +一个更好的是两个同样明显的方法来获得他们的总和!) - 但是这是一个目标! - )。


python中的静态方法可以追溯到Python 2.2中所谓的“新风格类”的引入。 在此之前,类中的方法只是普通的函数,作为属性存储在类中:

class OldStyleClass:
    def method(self):
        print "'self' is just the first argument of this function"

instance = OldStyleClass()
OldStyleClass.method(instance) # Just an ordinary function call
print repr(OldStyleClass.method) # "unbound method..."

对实例的方法调用被特别处理以自动将实例绑定到函数的第一个参数:

instance.method() # 'instance' is automatically passed in as the first parameter
print repr(instance.method) # "bound method..."

在Python 2.2中,许多类系统被重新思考并重新设计为“新风格的类” - 继承自object 。 新风格类的一个特点是“描述符”,它本质上是一个类中的对象,负责描述,获取和设置类的属性。 描述符有一个__get__方法,它传递了类和实例,并且应该返回类或实例的请求属性。

描述符使得使用单个API来实现类属性的复杂行为成为可能,例如属性,类方法和静态方法。 例如, staticmethod描述符可以像这样实现:

class staticmethod(object):
    """Create a static method from a function."""

    def __init__(self, func):
        self.func = func

    def __get__(self, instance, cls=None):
        return self.func

将此与一个普通方法的假设纯Python描述符进行比较,默认情况下,这些方法在类属性中的所有普通函数中使用(这不正是从实例中查找方法时发生的情况,但它处理自动'self'论据):

class method(object):
    """Create a method from a function--it will get the instance
    passed in as its first argument."""

    def __init__(self, func):
        self.func = func

    def __get__(self, instance, cls=None):
        # Create a wrapper function that passes the instance as first argument
        # to the original function
        def boundmethod(*args, **kwargs):
            return self.func(self, *args, **kwargs)
        return boundmethod

所以当你编写method = staticmethod(method) ,你实际上正在创建一个新的描述符,它的任务是不改变地返回原始函数,并将这个描述符存储在类的“method”属性中。

如果这似乎有很多工作要做,只是为了获得原始功能 - 这是对的。 但是由于普通的方法调用是默认的方法调用,所以静态方法和类方法需要分开实现,描述符通过一个简单的API提供了启用这些和其他复杂行为的方法。

正如其他人已经指出的那样,Python 2.4中引入的装饰器语法提供了一种更方便的声明静态方法的方法,但它仅仅是一种语法方便,并没有改变任何静态方法的工作方式。

请参阅http://www.python.org/doc/2.2.3/whatsnew/sect-rellinks.html和http://users.rcn.com/python/download/Descriptor.htm了解更多关于新风格的细节类和描述符。

链接地址: http://www.djcxy.com/p/54175.html

上一篇: How was the syntax chosen for static methods in Python?

下一篇: How to find the most common words using spacy?