2012-02-20 54 views
0

這裏是代碼,由exec定義的類'demo'在_getTestObj()中創建演示實例時不起作用。爲什麼python exec定義類不工作

文件名:test.py

class runOneIni(): 
    def _getTestObj(self): 
     demo(self.tcName,secSetup,doc) 



def start(): 
    #implicit define 'demo' class by exec is not working, get error in runOneIni->_getTestObj, Error is : 
    # NameError: name 'demo' is not defined 
    a='global demo' 
    exec(a) 

    str="class demo(tInvokeMethod.tInvokeMethod): pass' 
    exec(str) 

    #Explict define demo class is working 
    #global demo 
    #class demo(tInvokeMethod.tInvokeMethod): pass 


if __name__ == '__main__': 
    start()  

回答

1

(1)您有一個未終止字符串

(2)它是不需要使用exec做到這一點。 class本身就是一個可執行語句,它可以出現在任何其他語句的任何地方(除了需要表達式語句的地方)。

0

問題不在於通過exec定義類。以下按預期工作:

exec 'class hi: pass' 

您的問題是,exec語句中的「全局」在其外部沒有任何效果。根據執行的Python文檔:

全局是解析器的指令。它僅適用於與全局語句同時分析的代碼。特別是,包含在exec語句中的全局語句不會影響包含exec語句的代碼塊,並且包含在exec語句中的代碼不會受包含exec語句的代碼中的全局語句的影響。

0

你爲什麼這樣做?(exec除外)
你爲什麼試圖用exec來做到這一點?

而且,與exec這樣做會:

  1. 不起作用。
  2. python-2.xpython-3.x中給出不同的結果。

例子:

class demo: 
    a = 'a' 

print(demo.a) 

def start(): 
    global demo 
    class demo: b = "b" 

    try: 
     print(demo.a) 
    except AttributeError: 
     print(demo.b) 

if __name__ == '__main__': 
    start() 

    try: 
     print(demo.a) 
    except AttributeError: 
     print(demo.b) 

,要麼在python-2.xpython-3.x會給:

a 
b 
b 

現在,讓我們嘗試用exec

class demo: 
    a = 'a' 

print(demo.a) 

def start(): 
    exec('global demo', globals(), locals()) 

    exec('class demo: b = "b"', globals(), locals()) 

    try: 
     print(demo.a) 
    except AttributeError: 
     print(demo.b) 

if __name__ == '__main__': 
    start() 

    try: 
     print(demo.a) 
    except AttributeError: 
     print(demo.b) 

輸出python2.7

a 
b 
a 

輸出python3.2

a 
a 
a 

問:如何爲「動態創建類的?

由於kindall已經告訴過你,exec不是這樣做的。

A metaclassclass factory這樣做,但你確定你確實需要嗎?

+0

我想要做的就是動態創建類,本例中名爲'demo'的類,但類名不固定,它是可變的。所以我的想法是使用字符串來組裝創建類語句,即exec字符串。 – brike 2012-02-20 15:54:03

+0

那麼,動態地創建這個類,你幾乎不需要'exec'來做到這一點! – kindall 2012-02-20 15:55:23

+0

如何'動態創建類'? – brike 2012-02-20 16:22:10

0

你可以做這樣的事情:

class SomeBaseClass(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 

def make_new_class(name): 
    class TemplateClass(SomeBaseClass): 
     def __init__(self): 
      SomeBaseClass.__init__(self) 
      self.a = 3 
    return type(name, (TemplateClass,), {}) 

o1 = SomeBaseClass() 
print o1.a, o1.b 

NewClass = make_new_class('NewClass') 
o2 = NewClass() 
print o2.a, o2.b 

結果:

1 2 
3 2 
0

我可能是有點遲到了,但我想出了,似乎工作沒關係。由於設置屬性,它甚至會更正類型。

我敢肯定,這是所有可怕的unpythonic,但我認爲它有點兒有趣。

def generateClass(propertyNames,propertyTypes): 


    string = 'class generatedClass(object):\n def __init__(self):\n' 

    for pN in propertyNames: 
     string += '  self._m' + pN + ' = None\n' 


    string += ' \n \n' 

    i = 0 
    for pN in propertyNames: 
     string += ' @property\n' \ 
      ' def ' + pN + '(self):\n' \ 
      '  return self._m' + pN + '\n' \ 
      ' @' + pN + '.setter' +'\n' \ 
      ' def ' + pN + '(self,a'+ pN + '):\n' \ 
      '  if a' + pN + ':\n'\ 
      '   self._m'+ pN + ' = ' + propertyTypes[i] + '(a' + pN + ')\n'\ 
      '  \n' 
     i += 1 

    exec(string) 
    return generatedClass() 

if __name__ == '__main__': 
    c = generateClass(['SomePropertyName'],['str']) 
    print c.__dict__ 
    setattr(c,'SomePropertyName','some string') 
    print c.__dict__ 
相關問題