Static vs instance methods of str in Python

后端 未结 5 1166
鱼传尺愫
鱼传尺愫 2020-12-06 07:03

So, I have learnt that strings have a center method.

>>> \'a\'.center(3)
\' a \'

Then I have noticed that I can do the same thing

相关标签:
5条回答
  • 2020-12-06 07:23

    To expand on RichieHindle's answer:

    In Python, all methods on a class idiomatically take a "self" parameter. For example:

    def method(self, arg): pass
    

    That "self" argument tells Python what instance of the class the method is being called on. When you call a method on a class instance, this is typically passed implicitly for you:

    o.method(1)
    

    However, you also have the option of using the class Object, and explicitly passing in the class instance:

    C.method(o, 1)
    

    To to use your string example, str.center is a method on the str object:

    "hi".center(5)
    

    is equivalent to:

    str.center("hi", 5)
    

    You are passing in the str instance "hi" to the object, explicitly doing what's normally implicit.

    0 讨论(0)
  • 2020-12-06 07:35

    There should be one-- and preferably only one --obvious way to do it.

    Philosophically speaking, there is only one obvious way to do it: 'a'.center(3). The fact that there is an unobvious way of calling any method (i.e. the well-explained-by-previous-commentors o.method(x) and Type.method(o, x)) which is useful in many contexts is perfectly in line with the zen of python.

    Your homework assignment is to read Guido's Why the Explicit Self Has to Stay.

    0 讨论(0)
  • 2020-12-06 07:39

    That's simply how classes in Python work:

    class C:
        def method(self, arg):
            print "In C.method, with", arg
    
    o = C()
    o.method(1)
    C.method(o, 1)
    # Prints:
    # In C.method, with 1
    # In C.method, with 1
    

    When you say o.method(1) you can think of it as a shorthand for C.method(o, 1). A method_descriptor is part of the machinery that makes that work.

    0 讨论(0)
  • 2020-12-06 07:40
    'a'.center(3) == str.center('a',3)
    

    There is only one way to do it.

    0 讨论(0)
  • 2020-12-06 07:43

    Method descriptor is a normal class with __get__, __set__ and __del__ methods.

    When, e.g., __get__ is called, it is passed 2 or 3 arguments:

    • self, which is the descriptor class itself,
    • inst, which is the caller objet to which the "described" method should be bound,
    • cls, which can be None.

    To illustrate method_descriptor machinery, let me give this example:

    class Descriptor(object):
        def __init__(self, m):
        self._meth=m
    
        def __get__(self, inst, cls=None):
            if cls is None: cls=type(inst)
            delattr(cls,self._meth.func_name)
            def _inst_meth(*a):
                return self._meth(inst,*a)
            return _inst_meth
    
    def instanceonlymethod(f):
        return Descriptor(f)
    
    class Test(object):
        def meth_1(self,*a):
            return '-'.join(str(i) for i in a)
    
        @instanceonlymethod
        def meth_2(self,*a):
            return '-'.join(str(i) for i in a)
    
    t=Test()
    print t.meth_1(2,3,4,5) #returns: 2-3-4-5
    print Test.meth_1(t,1,2,3,4) #returns: 1-2-3-4
    print t.meth_2(2,3,4,5) #returns: 2-3-4-5
    try:
        print Test.meth_2(t,1,2,3,4)
    except Exception, why: #for 2.6, see changes
        print why #returns: type object 'Test' has no attribute 'meth_2'
    

    Now, when you call Test.meth_2(t, 1,2,3,4), it won't work.

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