下面的代码来自 SCons 的代码库。我们正在移植代码,以便它可以与 Python 2.7.x 和 3.x 一起使用。
下面的代码在 python 2.7.x 下运行良好,但是在 python 3.5 下运行失败如下:
python3.5 ~/tmp/blah123.py Traceback(最近一次调用最后):
文件“/home/bdbaddog/tmp/blah123.py”,第 73 行,在 print("stuff:%s"%nl[0:2 ].bar) AttributeError: 'list' 对象没有属性 'bar'
这段代码在某种程度上是 SCons 功能的核心。任何帮助都将受到欢迎。(请参阅此处的原始代码:src/engine/SCons/Util.py)
from __future__ import print_function
try:
from UserList import UserList
except ImportError as e:
from collections import UserList
class NodeList(UserList):
"""This class is almost exactly like a regular list of Nodes
(actually it can hold any object), with one important difference.
If you try to get an attribute from this list, it will return that
attribute from every item in the list. For example:
>>> someList = NodeList([ ' foo ', ' bar ' ])
>>> someList.strip()
[ 'foo', 'bar' ]
"""
def __nonzero__(self):
return len(self.data) != 0
def __bool__(self):
return self.__nonzero__()
def __str__(self):
return ' '.join(map(str, self.data))
def __iter__(self):
return iter(self.data)
def __call__(self, *args, **kwargs):
result = [x(*args, **kwargs) for x in self.data]
return self.__class__(result)
def __getattr__(self, name):
result = [getattr(x, name) for x in self.data]
return self.__class__(result)
# def __getitem__(self, index):
# return self.__class__(self.data[index])
# return self.data[index]
def __getitem__(self, index):
"""
This comes for free on py2,
but py3 slices of NodeList are returning a list
breaking slicing nodelist and refering to
properties and methods on contained object
"""
# return self.__class__(self.data[index])
if isinstance(index, slice):
# Expand the slice object using range()
# to a maximum of eight items.
return [self[x] for x in
range(*index.indices(8))]
else:
# Return one item of the tart
return self.data[index]
class TestClass(object):
def __init__(self, name, child=None):
self.child = child
self.bar = name
t1 = TestClass('t1', TestClass('t1child'))
t2 = TestClass('t2', TestClass('t2child'))
t3 = TestClass('t3')
nl = NodeList([t1, t2, t3])
print("stuff:%s"%nl[0:2].bar)
print("another:%s"%nl[1:].bar)
assert nl.bar == [ 't1', 't2', 't3' ], nl.bar
assert nl[0:2].child.bar == [ 't1child', 't2child' ], \
nl[0:2].child.bar
for f in nl:
print("->%s"%f.bar)