最后添加的使用上下文
我经常想要操作像列表这样的抽象对象。 e.g。
def list_ish(thing):
for i in xrange(0,len(thing)):
print thing[i]
现在这是合适的,如果是一个列表,但如果事物是一个字典,那将会失败。什么是pythonic为什么要问“你表现得像一个列表?”
注:
hasattr('__getitem__') and not hasattr('keys')
这适用于我能想到的所有情况,但我不喜欢负面定义鸭子类型,因为我预计可能存在它无法捕获的情况。
我真正想要的是问 “嘿,你按照我希望列表的方式对整数指标进行操作吗?” e.g。
thing[i], thing[4:7] = [...], etc.
注意:我不想简单地在大型try / except中执行我的操作,因为它们具有破坏性。在这里尝试失败并不酷......
使用上下文 - “点列表”是一个类似列表的东西,它包含类似字母的东西作为其元素。 - “矩阵”是类似列表的东西,包含类似列表的东西
- 我有一个函数库,可以在点列表上运行,也可以在类似矩阵的事物上运行。
- 例如,从用户的角度来看,像“电子表格式”操作“列切片”这样的破坏性操作可以同时对矩阵对象和点列表对象进行操作 - 结果事情就像原始的一样,但只有指定的列。
- 由于这个特殊的操作是破坏性的,所以进行就好像一个物体是一个矩阵,只是为了通过操作找到部分方式,它实际上是一个点列表或者没有 - 上方。
- 我希望我的'is_matrix'和'is_point_list'测试具有高效性,因为它们有时会出现在内部循环中。因此,我会对仅测试元素零的测试感到满意。
- 我更喜欢不涉及构造临时对象的测试,只是为了确定一个对象的类型,但也许这不是python方式。
总的来说,我发现整个鸭子打字的东西有点混乱,充满了虫子和缓慢,但也许我还没想到真正的Pythonista
很高兴喝更多的kool-aid ......答案 0 :(得分:3)
你可以做的一件事,就是应该在正常的list
上快速工作而在正常dict
上失败,就是从正面采取零长度切片:
try:
thing[:0]
except TypeError:
# probably not list-like
else:
# probably list-like
切片在dict
上失败,因为切片不可清除。
但是,str
和unicode
也通过了此测试,并且您提到您正在进行破坏性编辑。这意味着您可能还想检查__delitem__
和__setitem__
:
def supports_slices_and_editing(thing):
if hasattr(thing, '__setitem__') and hasattr(thing, '__delitem__'):
try:
thing[:0]
return True
except TypeError:
pass
return False
我建议您根据问题中的要求,明确地为您的输入组织您的要求,以及您希望功能处理的可能输入范围。如果您真的只想处理list
和dict
,那么您是否正在使用isinstance
,对吗?也许您的方法所做的只能删除项目,或者只替换项目,因此您不需要检查其他功能。记录这些要求以供将来参考。
答案 1 :(得分:1)
处理内置类型时,您可以使用Abstract Base Classes。在您的情况下,您可能希望针对collections.Sequence
或collections.MutableSequence
进行测试:
if isinstance(your_thing, collections.Sequence):
# access your_thing as a list
在2.6(包括)2.6之后的所有Python版本中都支持此功能。
如果您使用自己的类来构建your_thing
,我建议您也从这些抽象基类继承(直接或间接)。这样,您可以确保正确实现序列接口,并避免所有打字混乱。
对于第三方库,如果第三方类没有从内置类型继承,则没有简单的方法来检查序列接口或抽象类。在这种情况下,您必须检查您将要使用的每个界面,并且仅您使用的界面。例如,您的list_ish
函数使用了__len__
和__getitem__
,因此只检查这两种方法是否存在。 __getitem__
(例如dict)的错误行为应该引发异常。
答案 2 :(得分:1)
也许他们在这里不是理想的pythonic答案,所以我提出了一个' hack'解决方案,但是不太了解python的类结构,知道我是否正确:
def is_list_like(thing):
return hasattr(thing, '__setslice__')
def is_dict_like(thing):
return hasattr(thing, 'keys')
我在这里的目标是简单地进行高性能测试:
编辑:来自@DanGetz
的想法