Я читаю некоторые данные, из которых я хочу создать классы - это делается во время загрузки. Классы сгруппированы в класс Special
, который может быть создан только с использованием информации времени выполнения. Классы зависят от этого Special
класса, поэтому они могут быть полезны только после его создания. Вот некоторый упрощенный код, который показывает, как я хочу, чтобы он работал, используя random
вместо фактической информации времени выполнения:
import random
def make_foo(param1, param2):
class Foo:
def __init__(self, special):
self.param1 = param1
self.param2 = param2
self.special = special
def do(self):
print "%s is doing" % self
def __str__(self):
return "Foo<%s,%s with %s>" % (self.param1, self.param2,
self.special)
return Foo
def make_bar(foo):
class Bar:
def __init__(self, special):
self.foo = foo(special)
def do(self):
print "%s is doing" % (self,)
def __str__(self):
return "Bar<%s>" % self.foo
return Bar
def make_grouper(foobars):
class Grouper:
def __init__(self, special):
self.foobars = [foobar(special) for foobar in foobars]
return Grouper
def make_special(howtomake, groups):
class Special:
def __init__(self):
self.important = random.choice(howtomake)
self.groups = [group(self) for group in groups]
def __str__(self):
return "Special<%s>" % self.important
return Special
Foo10_20 = make_foo(10, 20)
Foo30_40 = make_foo(30, 40)
Bar = make_bar(Foo10_20)
Grouper1 = make_grouper([Foo10_20, Foo30_40])
Grouper2 = make_grouper([Bar, Bar])
Special = make_special("IMPORTANTINFO", [Grouper1, Grouper2])
s = Special()
s.groups[0].foobars[0].do()
s.groups[0].foobars[1].do()
s.groups[1].foobars[0].do()
s = Special()
s.groups[0].foobars[0].do()
s.groups[0].foobars[1].do()
s.groups[1].foobars[0].do()
Пример вывода:
Foo<10,20 with Special<O>> is doing
Foo<30,40 with Special<O>> is doing
Bar<Foo<10,20 with Special<O>>> is doing
Foo<10,20 with Special<I>> is doing
Foo<30,40 with Special<I>> is doing
Bar<Foo<10,20 with Special<I>>> is doing
Это можно резюмировать как необходимость создания набора классов, которые должны быть связаны с аргументом special
(поэтому все конструкторы, когда классы завершены, просто принимают аргумент special
). Можно ли сделать это более элегантно, используя мета-классы, или этот код в порядке?