我正在尝试使用
pathlib.Path
mixin 创建一个枚举,MCVE:
import enum, pathlib
class Test(pathlib.Path, enum.Enum):
path1 = pathlib.Path('/path1')
path2 = pathlib.Path('/path2')
这给出了一个完全神秘的错误:
1 import enum, pathlib
----> 2 class Test(pathlib.Path, enum.Enum):
3 path1 = pathlib.Path('/path1')
4 path2 = pathlib.Path('/path2')
File ~/anaconda3/envs/main/lib/python3.9/enum.py:288, in EnumMeta.__new__(metacls, cls, bases, classdict, **kwds)
286 enum_member._value_ = value
287 else:
--> 288 enum_member = __new__(enum_class, *args)
289 if not hasattr(enum_member, '_value_'):
290 if member_type is object:
File ~/anaconda3/envs/main/lib/python3.9/pathlib.py:1082, in Path.__new__(cls, *args, **kwargs)
1080 if cls is Path:
1081 cls = WindowsPath if os.name == 'nt' else PosixPath
-> 1082 self = cls._from_parts(args, init=False)
1083 if not self._flavour.is_supported:
1084 raise NotImplementedError("cannot instantiate %r on your system"
1085 % (cls.__name__,))
File ~/anaconda3/envs/main/lib/python3.9/pathlib.py:707, in PurePath._from_parts(cls, args, init)
702 @classmethod
703 def _from_parts(cls, args, init=True):
704 # We need to call _parse_args on the instance, so as to get the
705 # right flavour.
706 self = object.__new__(cls)
--> 707 drv, root, parts = self._parse_args(args)
708 self._drv = drv
709 self._root = root
File ~/anaconda3/envs/main/lib/python3.9/pathlib.py:700, in PurePath._parse_args(cls, args)
695 else:
696 raise TypeError(
697 "argument should be a str object or an os.PathLike "
698 "object returning str, not %r"
699 % type(a))
--> 700 return cls._flavour.parse_parts(parts)
File ~/anaconda3/envs/main/lib/python3.9/enum.py:429, in EnumMeta.__getattr__(cls, name)
427 return cls._member_map_[name]
428 except KeyError:
--> 429 raise AttributeError(name) from None
AttributeError: _flavour
我做错了什么?
这里有两个问题——一是当你混入一个类时,成员定义行的内容应该是混入的参数;二是当你混入一个类时,成员定义行的内容应该是混入的参数;换句话说,而不是
path1 = pathlib.Path('/path1')
你应该有
path1 = '/path1'
此时您遇到了第二个问题,该问题可以在
Path
实现中找到:
if cls is Path:
cls = WindowsPath if os.name == 'nt' else PosixPath
且
cls
为 Test
,因此既不选择 WindowsPath
也不选择 PosixPath
。
最简单的解决方案是事先从
WindowsPath
或 PosixPath
继承,并在枚举头中使用它:
BasePath = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath
class Test(BasePath, enum.Enum):
path1 = '/path1'
使用中:
>>> Test
<enum 'Test'>
>>> list(Test)
[<Test.path1: PosixPath('/path1')>]
披露:我是 Python stdlib
Enum
、enum34
backport 和 Advanced Enumeration (aenum
) 库的作者。