почему Python Exec определить класс не работает - PullRequest
0 голосов
/ 20 февраля 2012

Вот код, класс 'demo', определенный exec, не работает при создании демонстрационного экземпляра в _getTestObj ().

FileName: 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()    

Ответы [ 5 ]

1 голос
/ 20 февраля 2012

(1) У вас есть неопределенная строка

(2) Для этого не нужно использовать exec. class сам по себе является исполняемым оператором, который может появляться везде, где может любой другой оператор (кроме места, где требуется выражение выражения).

0 голосов
/ 08 марта 2013

Я мог бы немного опоздать на вечеринку, но я придумал что-то, что, кажется, работает хорошо. Он даже исправит тип из-за свойства настройки.

Я уверен, что все это ужасно нелепо, но я думаю, что это довольно забавно.

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__
0 голосов
/ 20 февраля 2012

Вы можете сделать что-то вроде этого:

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 голосов
/ 20 февраля 2012

Зачем вы это делаете? (кроме exec)
Почему вы пытаетесь сделать это с exec?

Кроме того, выполнение с exec будет:

  1. Не работает.
  2. Дайте разные результаты в python-2.x и в python-3.x.
* * Пример тысяча двадцать-один: * * 1 022
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.x, либо в python-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 метакласс или фабрика классов делает это, но вы уверены, что это действительно нужно?

0 голосов
/ 20 февраля 2012

Проблема не в определении класса через exec. Следующие работы по назначению:

exec 'class hi: pass'

Ваша проблема в том, что "глобальный" внутри оператора exec не имеет никакого эффекта вне его. Согласно документации на python для exec:

global - это директива для парсера. Он применяется только к коду, проанализированному одновременно с глобальным оператором. В частности, глобальный оператор, содержащийся в операторе exec, не влияет на блок кода, содержащий оператор exec, и на код, содержащийся в операторе exec, не влияют глобальные операторы в коде, содержащем оператор exec.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...