问题描述
所以,我查看了 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 相同的输出?
在我看来,join
和 walk
接受自我引用,但不知何故 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
作为隐式第一个参数。