Le code ci-dessous provient de la base de code de SCons. Nous travaillons sur le portage du code de sorte qu'il fonctionnera avec Python 2.7.x et 3.x.Comment créer une classe List like qui permet d'appeler des méthodes d'objets contenus sur des tranches qui fonctionnent à la fois avec py2 et py3
Le code ci-dessous fonctionne très bien sous 2.7.x python, mais lorsqu'il est exécuté en python 3.5 échoue comme suit:
python3.5 ~/tmp/blah123.py Traceback (most recent call last):
File "/home/bdbaddog/tmp/blah123.py", line 73, in print("stuff:%s"%nl[0:2].bar) AttributeError: 'list' object has no attribute 'bar'
Ce code est un peu à cœur la fonctionnalité de SCons. Toute aide serait la bienvenue. (Voir le code original ici: 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)
Merci! Cela couvrait presque tous les tests de la suite de tests complète. Un test unitaire échoue toujours. Si je peux suivre et simplifier, je vais ajouter à l'exemple de code ci-dessus. – bdbaddog
Ajout du test mis à jour ci-dessus voir "autre". Fix est en fait de supprimer le maximum de 8 dans les index.indices (8) ci-dessus. Et remplacez par index.indices (len (self.data)). Si vous modifiez ci-dessus, je marquerai comme réponse. – bdbaddog
@bdbaddog Super! Je suis content que ça marche :) – MSeifert