Python中的str的静态vs实例方法

时间:2009-07-24 21:41:33

标签: python string

所以,我已经知道字符串有一个中心方法。

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

然后我注意到我可以使用'str'对象做同样的事情,因为

>>> type(str)
<type 'type'>

使用这个'type'对象,我可以访问字符串方法,就像它们是静态函数一样。

>>> str.center('a',5)
'  a  '

唉!这违反了蟒蛇的禅宗。

应该有一个 - 最好只有一个 - 显而易见的方法。

即使这两种方法的类型也不同。

>>> type(str.center)
<type 'method_descriptor'>
>>> type('Ni!'.center)
<type 'builtin_function_or_method'>

现在,

  1. 这是一个如何设计python类的示例吗?
  2. 为什么类型不同?
  3. 什么是method_descriptor,我为什么要打扰?
  4. 感谢您的回答!

5 个答案:

答案 0 :(得分:17)

这就是Python中的类如何工作:

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

当您说o.method(1)时,您可以将其视为C.method(o, 1)的简写。 method_descriptor是使这项工作成功的机制的一部分。

答案 1 :(得分:9)

  

应该有一个 - 最好只有一个 - 显而易见的方法。

从哲学上讲, 只有一种显而易见的方法:'a'.center(3)。事实上有一种不明显的方式来调用任何方法(即前面的注释器o.method(x)和Type.method(o,x)),这在许多情况下很有用,这一点非常符合与蟒蛇的禅宗。

你的家庭作业是阅读Guido的Why the Explicit Self Has to Stay

答案 2 :(得分:5)

扩展RichieHindle的答案:

在Python中,类上的所有方法都是惯用的“self”参数。例如:

def method(self, arg): pass

“self”参数告诉Python调用该方法的类的实例。当您在类实例上调用方法时,通常会为您隐式传递:

o.method(1)

但是,您还可以选择使用Object类,并显式传入类实例:

C.method(o, 1)

要使用你的字符串示例,str.center是str对象上的一个方法:

"hi".center(5)

相当于:

str.center("hi", 5)

您正在将str实例“hi”传递给对象,显式执行通常隐含的操作。

答案 3 :(得分:2)

'a'.center(3) == str.center('a',3)

只有一种方法可以做到。

答案 4 :(得分:1)

方法描述符是具有__get____set____del__方法的普通类。

例如,当调用__get__时,会传递2或3个参数:

  • self,这是描述符类本身,
  • inst,这是应该绑定“描述”方法的调用者对象,
  • cls,可以是None

为了说明method_descriptor机器,让我举个例子:

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'

现在,当您致电Test.meth_2(t, 1,2,3,4)时,它将无效。