这是不合逻辑的 python 行为吗?
Is this inconsequent python behaviour?
所以,我在查看 pathlib 源代码时注意到一些 os lib 函数被合并到 pathlib classes 中。我必须承认,我花了一点时间才理解它是如何工作的。
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')
此 class 定义将 os 库的 listdir、join 和 walk 函数添加为 Foo class 上的方法。 Foo class 被识别为 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
class 实现了 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
作为隐式第一个参数。
所以,我在查看 pathlib 源代码时注意到一些 os lib 函数被合并到 pathlib classes 中。我必须承认,我花了一点时间才理解它是如何工作的。
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')
此 class 定义将 os 库的 listdir、join 和 walk 函数添加为 Foo class 上的方法。 Foo class 被识别为 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
class 实现了 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
作为隐式第一个参数。