Python和自我参数

时间:2010-12-31 01:56:50

标签: python

我在使用self参数时遇到了一些问题,而Python中一些看似不一致的行为让我烦恼,所以我想我最好问一些知情人士。我有一个班级,Foo。这个类将有一堆方法m1,通过mN。对于其中一些,我将使用标准定义,如下面m1的情况。但对于其他人来说,直接分配方法名称更方便,就像我使用m2m3一样。

import os

def myfun(x, y):
    return x + y

class Foo():
    def m1(self, y, z):
        return y + z + 42

    m2 = os.access
    m3 = myfun

f = Foo()
print f.m1(1, 2)
print f.m2("/", os.R_OK)
print f.m3(3, 4)

现在,我知道os.access没有采用self参数(貌似)。它仍然没有这种类型的任务问题。但是,我不能对我自己的模块做同样的事情(想象myfun中定义的mymodule.myfun。运行上面的代码会产生以下输出:

3
True
Traceback (most recent call last):
  File "foo.py", line 16, in <module>
    print f.m3(3, 4)
TypeError: myfun() takes exactly 2 arguments (3 given)

问题在于,由于我所使用的框架,我至少无法避免使用类Foo。但是我想避免将我的mymodule内容放入虚拟课堂中。为了做到这一点,我需要做一些事情

def m3(self,a1, a2):
    return mymodule.myfun(a1,a2)

当你有20个人时,这是多余的。所以,问题是,或者我如何以完全不同的,明显更智能的方式做到这一点,或者我如何使我自己的模块像内置模块一样,所以它不会抱怨接收1个参数太多。

5 个答案:

答案 0 :(得分:4)

os.access()是一个内置函数,因为它是用C编写的扩展模块的一部分。当定义类时,Python不会将m2识别为方法,因为它是错误的类型 - 方法是Python函数,而不是C函数。但是,m3是一个Python函数,因此它被认为是一种方法并按此处理。

换句话说,m2在这里是例外,而不是m3

一种简单的方法就是让m3成为一种静态方法:

m3 = staticmethod(myfun)

现在,当解释器被称为Foo对象的myfun()方法时,解释器知道永远不会尝试传递self m3参数。

答案 1 :(得分:2)

我认为你正在寻找staticmethod()。请参阅文档here

m2 = staticmethod(os.access)
m3 = staticmethod(myfun)

至于为什么m2在你的例子中起作用而m3没有,那对我来说并不清楚。在原始示例中打印f.m2和f.m3表明f.m2是对内置函数os.access的直接引用,而f.m3是绑定方法(绑定到实例f)。

答案 2 :(得分:2)

我只想补充说,这种行为并不像卢克暗示的那样不一致。

试试以下

print Foo.__dict__
    {'__doc__': None,
     '__module__': '__main__',
     'm1': <function m1 at 0x02861630>,
     'm2': <built-in function access>,
     'm3': <function myfun at 0x028616F0>}

在这里你可以看到Python无法区分m1和m2。 这就是为什么两者都被评估为绑定方法的原因。

绑定方法类似于带有指向对象的附加第一个参数的方法:self.m(1, 2) -> m(self, 1, 2)

此绑定行为仅针对用户定义的方法实现。这解释了为什么self.m2("/", os.R_OK)未评估为m2(self, "/", os.R_OK)

最后一个演示:

print Foo.m1
    <unbound method Foo.m1>
print Foo.m2
    <built-in function access>
print f.m1
    <bound method Foo.m1 of <__main__.Foo instance at 0x02324418>>
print f.m2
    <built-in function access>

有关不同功能类型的更多信息,请访问:

http://docs.python.org/reference/datamodel.html

如前所述,使用 staticmethod描述符也可以防止这种绑定机制:

http://docs.python.org/library/functions.html#staticmethod

答案 3 :(得分:1)

在这种情况下,您应该使用staticmethod功能。编写静态类方法时,可以将其用作装饰器:

class A:
   def printValue(self,value):
       print value

   @staticmethod
   def staticPrintValue(value):
       print value

>>> A.printValue(5)
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    A.printValue(5)
TypeError: unbound method printValue() must be called with A instance as first argument (got int instance instead)

>>> A.staticPrintValue(5)
5

答案 4 :(得分:0)

一种方法是手动应用静态方法装饰器:

class Foo(object):
    m3 = staticmethod(mymodule.myfun)