这是无关紧要的python行为吗?

问题描述

所以,我查看了 pathlib 源代码,我注意到一些 os lib 函数被合并到了 pathlib 类中。我必须承认,我花了一点时间才明白这是如何工作的。

import os

class Foo:
    listdir = os.listdir
    join = os.path.join
    walk = os.walk

    def __init__(self,name):
        self.name = name

    def __fspath__(self):
        return self.name

curr = Foo('.')
pipo = Foo('pipo')

这个类定义在 Foo 类上添加了 os 库的 listdir、join 和 walk 函数作为方法。 Foo 类被识别为 PathLike 对象,因为它也有 __fspath__ 方法

curr.join('bar')调用时,它会加入 curr 的名字,'.',和 'bar'。下面的代码显示了这种确切的行为,结果是我所期望的。

$ tree
.
├── pipo
│   └── clown
└── test.py

1 directory,2 files
$

>>> curr.join("baz") 
./baz
>>>
>>> pipo.join("baz")
pipo/baz
>>>
>>> [x for x in curr.walk()]
[('.',['pipo'],['test.py']),('./pipo',[],['clown'])]
>>>
>>> [x for x in pipo.walk()]
[('pipo',['clown'])]
>>>

然后我尝试了 listdir 函数......但它失败。 listdir 函数显示不同的行为,我很困惑为什么?

>>>
>>> os.listdir()
['pipo','test.py']
>>>
>>> curr.listdir()
['pipo','test.py']
>>>
>>> os.listdir("pipo")
['clown']
>>>
>>> pipo.listdir()
['pipo','test.py']
>>> 

pipo 上的 listdir 方法显示与 curr 上的 listdir 相同的输出

在我看来,joinwalk 接受自我引用,但不知何故 listdir 不接受。为什么会这样?

解决方法

function 类实现了 descriptor protocol,允许 os.path.join 作为实例方法。 os.listdir 不是 function 的实例;它是 builtin_function_or_method 的一个实例,它没有实现描述符协议。

curr.join(...) 等价于 Foo.join.__get__(curr,Foo)(...)curr.listdir() 等价于 Foo.listdir()curr.listdir 不存在,Foo.listdir 只是调用 listdir,而不是不存在的 listdir.__get__注意传递 curr 作为隐式第一个参数。