Python中有三种以上的方法吗?

pyl*_*ang 5 python methods

据我所知,Python中至少有3种方法具有不同的第一个参数:

  1. 实例方法 - 实例,即 self
  2. class方法 - 类,即 cls
  3. 静态方法 - 没什么

这些经典方法在Test下面的类中实现,包括常用方法:

class Test():

    def __init__(self):
        pass

    def instance_mthd(self):
        print("Instance method.")

    @classmethod
    def class_mthd(cls):
        print("Class method.")

    @staticmethod
    def static_mthd():
        print("Static method.")

    def unknown_mthd():
        # No decoration --> instance method, but
        # No self (or cls) --> static method, so ... (?)
        print("Unknown method.")
Run Code Online (Sandbox Code Playgroud)

在Python 3中,unknown_mthd可以安全地调用它,但它在Python 2中引发了一个错误:

>>> t = Test()

>>> # Python 3
>>> t.instance_mthd()
>>> Test.class_mthd()
>>> t.static_mthd()
>>> Test.unknown_mthd()

Instance method.
Class method.
Static method.
Unknown method.

>>> # Python 2
>>> Test.unknown_mthd()    
TypeError: unbound method unknown_mthd() must be called with Test instance as first argument (got nothing instead)
Run Code Online (Sandbox Code Playgroud)

这个错误表明这样的方法并不适用于Python 2.也许它的允许现在是由于在Python 3(REF 001)中消除了未绑定的方法.此外,unknown_mthd不接受指定参数时,它可以绑定到由像一个静态方法类调用Test.unknown_mthd().但是,它不是一个明确的静态方法(没有装饰器).

问题

  1. 在Python 3的设计中,有意这样的方法(没有args而没有明确地装饰为staticmethods)吗?更新
  2. 在经典方法类型中,有哪种方法unknown_mthd
  3. 为什么可以unknown_mthd在没有传递参数的情况下被类调用?

一些初步检查结果不确定:

>>> # Types
>>> print("i", type(t.instance_mthd))
>>> print("c", type(Test.class_mthd))
>>> print("s", type(t.static_mthd))
>>> print("u", type(Test.unknown_mthd))                             
>>> print()

>>> # __dict__ Types, REF 002
>>> print("i", type(t.__class__.__dict__["instance_mthd"]))
>>> print("c", type(t.__class__.__dict__["class_mthd"]))
>>> print("s", type(t.__class__.__dict__["static_mthd"]))
>>> print("u", type(t.__class__.__dict__["unknown_mthd"]))          
>>> print()

i <class 'method'>
c <class 'method'>
s <class 'function'>
u <class 'function'>

i <class 'function'>
c <class 'classmethod'>
s <class 'staticmethod'>
u <class 'function'>
Run Code Online (Sandbox Code Playgroud)

第一组类型检查建议unknown_mthd类似于静态方法.第二个建议它类似于实例方法.我不确定这种方法是什么,或者为什么它应该用于经典方法.如果能更好地检查和理解它,我将不胜感激.谢谢.

Bre*_*arn 5

一些背景:在Python 2中,"常规"实例方法可能会产生两种方法对象,具体取决于您是通过实例还是类访问它们.如果你做了inst.meth(这inst是类的一个实例),你得到一个绑定的方法对象,它跟踪它附加到哪个实例,并将其作为传递self.如果你做了Class.meth(Class类在哪里),你有一个未绑定的方法对象,它没有固定值self,但仍然进行检查以确保self在调用它时传递了适当的类.

在Python 3中,删除了未绑定的方法.这样做Class.meth,现在只是给你的"普通"函数对象,不带参数的检查都没有.

在Python 3的设计中是否有意这样做?

如果你的意思是,有意删除未绑定的方法,答案是肯定的.你可以在邮件列表上看到Guido的讨论.基本上,我们认为未绑定的方法增加了复杂性,但收益微乎其微.

在经典方法类型中,什么类型的方法是unknown_mthd?

它是一种实例方法,但却是一种破碎方法.当您访问它时,会创建一个绑定的方法对象,但由于它不接受任何参数,因此它无法接受该self参数并且无法成功调用.

为什么在没有传递参数的情况下,类可以调用unknown_mthd?

在Python 3中,删除了未绑定的方法,因此Test.unkown_mthd只是一个普通的函数.没有包装来处理self参数,因此您可以将其称为不接受任何参数的普通函数.在Python 2中,Test.unknown_mthd是一个未绑定的方法对象,它有一个检查,强制传递self适当类的参数; 因为,该方法再次接受不参数,此检查失败.