Class method differences in Python: bound, unbound and static

后端 未结 13 1107
日久生厌
日久生厌 2020-11-22 08:54

What is the difference between the following class methods?

Is it that one is static and the other is not?

class Test(object):
  def method_one(self)         


        
相关标签:
13条回答
  • 2020-11-22 09:22

    Bound method = instance method

    Unbound method = static method.

    0 讨论(0)
  • 2020-11-22 09:26

    that is an error.

    first of all, first line should be like this (be careful of capitals)

    class Test(object):
    

    Whenever you call a method of a class, it gets itself as the first argument (hence the name self) and method_two gives this error

    >>> a.method_two()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: method_two() takes no arguments (1 given)
    
    0 讨论(0)
  • 2020-11-22 09:30

    In Python, there is a distinction between bound and unbound methods.

    Basically, a call to a member function (like method_one), a bound function

    a_test.method_one()
    

    is translated to

    Test.method_one(a_test)
    

    i.e. a call to an unbound method. Because of that, a call to your version of method_two will fail with a TypeError

    >>> a_test = Test() 
    >>> a_test.method_two()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: method_two() takes no arguments (1 given) 
    

    You can change the behavior of a method using a decorator

    class Test(object):
        def method_one(self):
            print "Called method_one"
    
        @staticmethod
        def method_two():
            print "Called method two"
    

    The decorator tells the built-in default metaclass type (the class of a class, cf. this question) to not create bound methods for method_two.

    Now, you can invoke static method both on an instance or on the class directly:

    >>> a_test = Test()
    >>> a_test.method_one()
    Called method_one
    >>> a_test.method_two()
    Called method_two
    >>> Test.method_two()
    Called method_two
    
    0 讨论(0)
  • 2020-11-22 09:32

    Methods in Python are a very, very simple thing once you understood the basics of the descriptor system. Imagine the following class:

    class C(object):
        def foo(self):
            pass
    

    Now let's have a look at that class in the shell:

    >>> C.foo
    <unbound method C.foo>
    >>> C.__dict__['foo']
    <function foo at 0x17d05b0>
    

    As you can see if you access the foo attribute on the class you get back an unbound method, however inside the class storage (the dict) there is a function. Why's that? The reason for this is that the class of your class implements a __getattribute__ that resolves descriptors. Sounds complex, but is not. C.foo is roughly equivalent to this code in that special case:

    >>> C.__dict__['foo'].__get__(None, C)
    <unbound method C.foo>
    

    That's because functions have a __get__ method which makes them descriptors. If you have an instance of a class it's nearly the same, just that None is the class instance:

    >>> c = C()
    >>> C.__dict__['foo'].__get__(c, C)
    <bound method C.foo of <__main__.C object at 0x17bd4d0>>
    

    Now why does Python do that? Because the method object binds the first parameter of a function to the instance of the class. That's where self comes from. Now sometimes you don't want your class to make a function a method, that's where staticmethod comes into play:

     class C(object):
      @staticmethod
      def foo():
       pass
    

    The staticmethod decorator wraps your class and implements a dummy __get__ that returns the wrapped function as function and not as a method:

    >>> C.__dict__['foo'].__get__(None, C)
    <function foo at 0x17d0c30>
    

    Hope that explains it.

    0 讨论(0)
  • 2020-11-22 09:35

    Please read this docs from the Guido First Class everything Clearly explained how Unbound, Bound methods are born.

    0 讨论(0)
  • 2020-11-22 09:35

    The definition of method_two is invalid. When you call method_two, you'll get TypeError: method_two() takes 0 positional arguments but 1 was given from the interpreter.

    An instance method is a bounded function when you call it like a_test.method_two(). It automatically accepts self, which points to an instance of Test, as its first parameter. Through the self parameter, an instance method can freely access attributes and modify them on the same object.

    0 讨论(0)
提交回复
热议问题