我正在阅读一些我希望创建类的数据 - 这是在加载时完成的。这些类被分组为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
参数) 。这可以使用元类更优雅地完成,或者这个代码是否很好?
答案 0 :(得分:3)
由于我通常更喜欢Python中的闭包类,所以我在这里使用工厂类,并且完全避免使用动态创建的类。例如:
class Foo:
def __init__(self, param1, param2, 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)
class FooFactory:
def __init__(self, param1, param2):
self.param1 = param1
self.param2 = param2
def __call__(self, special):
return Foo(self.param1, self.param2, special)
foo_factory = FooFactory(1, 2)
foo = foo_factory(3)
FooFactory
的替代方案是使用functools.partial()
。如果Foo
定义如上,则可以执行
FooSpecialised = functools.partial(Foo, param1, param2)
并使用
创建Foo
的实例
FooSpecialised(special)
答案 1 :(得分:2)
这不是一个严格的答案(或者可能是),但我认为蒂姆·彼得斯引用的引用(MarkLutz,学习python 4 ed)可能很有趣:
从中借用一句话 由退伍军人编写的comp.lang.python新闻组 Python核心开发人员Tim Peters(谁 也是着名的作者 “导入这个”Python座右铭):
[Metaclasses]比魔法更深刻 99%的用户应该担心。 如果你想知道你是否需要它们, 你没有(实际的人 需要他们肯定地知道 他们需要它们,而且不需要它们 解释为什么)。
答案 2 :(得分:0)
我最终创建了一个基类:
class Base(object):
@classmethod
def bind_init(cls, *args, **kwargs):
def init(special):
return cls(special, *args, **kwargs)
return init
Foo et。人。现在是一个看起来很正常的非动态类:
class Foo(Base):
def __init__(self, special, param1, param2):
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)
它们按如下方式使用:
Foo10_20 = Foo.bind_init(10, 20)
Foo30_40 = Foo.bind_init(30, 40)
Bar = Bar.bind_init(Foo10_20)
Grouper1 = Grouper.bind_init([Foo10_20, Foo30_40])
Grouper2 = Grouper.bind_init([Bar, Bar])
Special = Special.bind_init("IMPORTANTINFO", [Grouper1, Grouper2])
这可以最大限度地减少代码重复(不必制作大量的工厂类),而且我也比工厂更喜欢这种语言。