Как вы уже поняли, создать копию FilteredElementCollector
. Однако вы можете создать функционально идентичный, записав, какие методы вызываются в оригинале, и дублируя эти вызовы методов, когда вам нужно сделать копию. Класс ниже делает именно это:
class CopyableFilteredElementCollector(FilteredElementCollector):
def __init__(self, doc):
# Initialize the underlying FilteredElementCollector
FilteredElementCollector.__init__(self, doc)
# Save the document
self._doc = doc
# Calls to methods that constrain the FilteredElementCollector will be recorded here
self._log = []
def copy(self):
# Create a brand new instance
copy = CopyableFilteredElementCollector(self._doc)
# Replay the log on the new instance
for method_name, args in self._log:
getattr(copy, method_name)(*args)
# The copy now references the same document as the original,
# and has had the same methods called on it
return copy
Нам нужно переопределить каждый метод, который ограничивает элементы, возвращаемые FilteredElementCollector
, для записи его вызова в журнал. Самый простой способ сделать это - определить методы переопределения в теле класса следующим образом:
def OfCategory(self, category):
# Add an entry to the log containing the name of the method that was called
# and a tuple of its arguments that can be expanded with the splat operator
self._log.append(('OfCategory', (category,)))
# Call the original method
FilteredElementCollector.OfCategory(self, category)
# Return self just like the original method does
return self
Определение переопределения для каждого отдельного метода становится повторяющимся, поэтому давайте вместо этого воспользуемся метапрограммированием вуду:
# Methods of FilteredElementCollector that constrain which elements it returns
constraint_methods = [
'OfCategory',
'OfClass',
'WhereElementIsElementType',
'WhereElementIsNotElementType',
'WherePasses',
# et cetera
]
# A factory function that produces override methods similar to the one defined above
def define_method(method_name):
def method(self, *args):
self._log.append((method_name, args))
getattr(FilteredElementCollector, method_name)(self, *args)
return self
return method
# Create an override for each method and add it to the CopyableFilteredElementCollector class
for method_name in constraint_methods:
setattr(CopyableFilteredElementCollector, method_name, define_method(method_name))
Я не буду заходить так далеко, чтобы утверждать, что мой подход - хорошая идея, но это вариант, если ваш вариант использования требует создания копий FilteredElementCollector
, а не создания новых с нуля.
person
Nicholas Rawlings
schedule
03.07.2020
.OfCategory()
или.OfClass()
) в экземпляре сборщика, они возвращают измененную версию этого экземпляра. Таким образом, даже если вы сохраните более общий сборщик в переменной, все последующие вызовы методов фильтрации также изменят исходный сборщик. - person Ehsan Iran-Nejad   schedule 21.06.2020