def check_classes(cls):
if len(cls.__bases__) == 0:
return []
else:
test_list = []
for x in range(len(cls.__bases__)):
test_list += [cls] + check_classes(cls.__bases__[x])
for x in cls.__bases__:
return test_list + [x]
我目前有一个递归函数,该函数将一个类作为其参数并返回所有基类的列表。这可以正常工作,但是列表中有许多重复的类。我想返回一个集合而不是一个列表,并且想知道如何更改代码来做到这一点。
答案 0 :(得分:3)
Python具有内置的background-image:
url(../images/background/large/static.png),
url(../images/background/large/repeat.png);
background-repeat:
no-repeat,
repeat-y;
background-position:
0px top,
600px top;
类型,可消除重复项:
set
此代码已经避免了首先添加许多重复项。但是,def get_bases(obj):
bases = {obj} # new set including only obj
if not(obj.__bases__): # technically redundant - iter is a noop on empty collections
return bases
else:
for x in obj.__bases__:
bases.update(get_bases(x)) # update set - automatically eliminates duplicates
return bases
仍然可以消除多重继承情况下的重复项。
set
Python是Python,已经有一些方法可以做到这一点:
class A: ...
class B1(A): ...
class B2(A): ...
class C(B1, B2): ...
print(get_bases(C))
# {<class '__main__.C'>, <class '__main__.B1'>, <class 'object'>, <class '__main__.B2'>, <class '__main__.A'>}
如果您只关心基础,请使用>>> C.__mro__
(__main__.C, __main__.B1, __main__.B2, __main__.A, object)
。它的顺序还表示如何在多个碱基之间进行查找。
这种搜索的一种略有不同的方法是使用__mro__
来跟踪重复项,而使用set
来存储 元素:>
list
这使用def get_bases(obj, _dupes=None):
_dupes = _dupes if _dupes is not None else set()
bases = [obj] # new list including only obj
_dupes.add(obj)
for x in obj.__bases__:
if x not in _dupes:
bases.extend(get_bases(x, _dupes)) # update set - automatically eliminates duplicates
return bases
检查您是否已经上过课。无需消除添加两次的类,而是仅将它们添加一次。给定许多元素,此检查_dupes: set
比set
更快。但是,您需要list
才能保留顺序。
答案 1 :(得分:2)
您的功能是多余的,可以用cls.__mro__
代替:
>>> class Base: pass
...
>>> class Foo(Base): pass
...
>>> class Bar(Base): pass
...
>>> class Baz(Foo, Bar): pass
...
>>> Baz.__mro__
(<class '__main__.Baz'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.Base'>, <class 'object'>)
最大的问题是您的实现将类添加到列表两次中,一次是在递归调用中,一次是在当前调用中。仅将 current 类添加到列表中。将__bases__
列表检查为空也是多余的,因为如果序列为空,则for
循环已经不执行任何操作。
这足够了:
def check_classes(cls):
result = [cls]
for base in cls.__bases__:
result += check_classes(base)
return result
但这仍然会重复多次包含在层次结构中的基类:
>>> check_classes(Baz)
[<class '__main__.Baz'>, <class '__main__.Foo'>, <class '__main__.Base'>, <class 'object'>, <class '__main__.Bar'>, <class '__main__.Base'>, <class 'object'>]
请注意,由于多重继承,Base
和object
出现了两次。您可以使用一组来避免这种情况:
def check_classes(cls):
result = set([cls])
for base in cls.__bases__:
result.update(check_classes(base))
return result
这时我们会失去订购,但这可能足以满足您的需求:
>>> check_classes(Baz)
{<class '__main__.Bar'>, <class '__main__.Foo'>, <class '__main__.Base'>, <class 'object'>, <class '__main__.Baz'>}
但是,您只需使用set(cls.__mro__)
并完成操作即可:
>>> check_classes(Baz) == set(Baz.__mro__)
True