方法的别名被视为成员函数

Alias to method is being treated as a member function

我正在尝试为 class 中的非成员函数设置别名,但我相信 Python 会将其视为成员函数。

def bar(a, b):
    print(a, b)

class Foo:

    baz = bar

f = Foo()
f.baz(1, 2)

TypeError: bar() takes 2 positional arguments but 3 were given

所以我放弃一个参数,我得到:

f.baz(1)

<__main__.Foo object at 0x0000026CD8279DD8> 1

为什么要将实例作为参数传递 a

如果我要为另一种方法起别名,比如来自模块:

class Foo:

    baz = bar.bar

其中 bar.bar 的定义完全相同,但在 bar 模块中,它可以正常工作。

所有 function 值的 class 属性都是实例方法,无论函数是在 class 语句内部还是外部定义的。

a.baza.bar 都会触发描述符协议,return 是 bar.__get__(a, A) 的结果,它是一个试图调用 bar 有两个参数。

事实上,您可以在不定义 任何 class 属性的情况下显式触发此方法行为。

def bar(a, b):
    print(f'"Object": {a}')
    print(f'Argument: {b}')

class Foo:
    pass

f = Foo()
bar.__get__(f, Foo)(2)

产生输出

Object: <__main__.Foo object at 0x108cb5e80>
Argument: 2

你想要的是一个静态方法,这样当你调用它时,底层函数不会被赋予任何隐式参数,只有那些传递给方法本身的参数。

class Foo:
    baz = staticmethod(bar)

f = Foo()
f.baz(1, 2)  # bar gets arguments 1 and 2, not f, 1, and 2.

staticmethod.__get__ 只是 return 底层函数本身,而不是包装函数的 method 对象。


关于 os.open 的不同行为,您必须认识到 os.opendef 语句创建的值的类型不同:

>>> import os
>>> def bar(): pass
...
>>> type(os.open)
<class 'builtin_function_or_method'>
>>> type(bar)
<class 'function'>

builtin_function_or_method 类型未实现 __get__,因此当您通过属性查找访问此类值时,"tricky" 不会发生任何事情。