2013-08-30 77 views
1

我有一个类装饰创建类

class Test: 
    name = "Test" 

我想创建一个装饰mc_me其中后:

@mc_me 
class Test: 
    name = "Test" 

会为我提供了三类完全一样,如果我写:

class Test: 
    name = "Test" 

class TestSuper: 
    name = "TestSuper" 

class TestExtra: 
    name = "TestExtra" 

所以基本上第一个棘手的部分是深层复制一个类,第二个是在调用者的作用域上分配三个变量。感觉好像应该有可能......

回答

3
import inspect 

def mc_me(cls): 
    main_locals = inspect.currentframe().f_back.f_locals 
    for suffix in ['Super', 'Extra']: 
     new_name = cls.__name__ + suffix 
     main_locals[new_name] = type(new_name,(), {'name': new_name}) 
    return cls 

小心,这不是编写的最佳途径。拥有权利的同时也被赋予了重大的责任。我鼓励你查看inspect方法的所有可能的缺点(Google是你的朋友)。

+2

生病而美丽! :)注意:“CPython实现细节:该函数依赖于解释器中的Python堆栈框架支持,并不保证在所有Python实现中都存在。” [inspect.currentframe](http://docs.python.org/2/library/inspect.html#inspect.currentframe) – neverlastn

+0

只适用于顶级或类别级别,我敢肯定你应该返回'cls'。 – user2357112

+0

忘了'返回cls',你是对的。我无法看到顶级限制的问题。 – gioi

0

不可能。制作3节课很简单。尽管将结果分配给3个变量?这违反了Python的范围规则。

@mc_me 
class Test: 
    name = "Test" 

相当于

class Test: 
    name = "Test" 
Test = mc_me(Test) 

有没有办法为装饰的说,它希望创建一些变量并分配给那些太。即使你以某种方式设法使它工作(可能只是在模块或类作用域,但是inspect疯狂),Python将无法知道对TestSuperTestExtra的引用应引用由修饰器在编译字节码时创建的变量。

+0

是的,确切地说,我正在考虑一些......'(Test,TestSuper,TestExtra)= mc_me(Test)'“让3个类很容易”你可以深刻复制和猴子补丁吗? (我知道这听起来像继承)。在任何情况下,下面应该是一个简单的替代 '类测试: 名称= “测试” TestSuper = mc_me(测试, “超级”) TestExtra = mc_me(测试, “额外”)' – neverlastn

+0

*的Python会无法知道对TestSuper或TestExtra的引用应该在编译字节码时引用装饰器创建的变量。字节码将不包含新创建的'TestSuper'和'TestExtra',但不包括创建它们的说明。事实上,它的工作原理。 – gioi

0

事实上,放弃装饰者的想法和使用返回元组的常规函数​​是最接近实现我想要的结果。

# Library code 
def mc_me(base): 
    class Sp(base): 
     name = base.name + "Super" 

    class Ex(base): 
     name = base.name + "Extra" 

    return (Sp, Ex) 

# Application code 
class Test: 
    name = "Test" 

(TestSuper, TestExtra) = mc_me(Test)