Найти - Пользователи
Полная версия: Преобразование строки в имя класса
Начало » Python для экспертов » Преобразование строки в имя класса
1 2 3
lukke
mymodule.py


import os
import sys
from xml.dom.minidom import Node, Element

class A(object):
pass
class B(object):
pass
class C(object):
pass
def func_1():
pass
def func_2():
pass
val = 0
vol = 1


module test.py


import mymodule

lstClasses =
for i in dir(mymodule):
attr = getattr(mymodule, i)
try:
issubclass(attr, object)
lstClasses.append(attr)
except:
pass
for i in lstClasses:
print i

Results:

<class ‘mymodule.A’>
<class ‘mymodule.B’>
<class ‘mymodule.C’>
xml.dom.minidom.Element
xml.dom.minidom.Node
Jenyay
Спасибо!
Стас Агарков
А можно ли создать в locals() переменную со своим именем, переданным в качестве строки?
crchemist
[crchemist@205-154-179-94 tmp]$ python
Python 2.6 (r26:66714, Jun 8 2009, 16:07:26)
[GCC 4.4.0 20090506 (Red Hat 4.4.0-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
>>> locals()['h'] = 34
>>> h
34
>>>
Стас Агарков
Большое спасибо! То, что нужно.
ZAN
Не то, что нужно, т.к. присваимвание можно сделать только через globals(), но не locals().
PEP 227:
locals() / vars()

These functions return a dictionary containing the current scope's
local variables. Modifications to the dictionary do not affect
the values of variables. Under the current rules, the use of
locals() and globals() allows the program to gain access to all
the namespaces in which names are resolved.

An analogous function will not be provided for nested scopes.
Under this proposal, it will not be possible to gain
dictionary-style access to all visible scopes.
В примере выше такой трюк сработал, т.к. в области видимости модуля не создается local namespace, но функция просто возвращает globals()

#одно и то же:
print locals() is globals()

class A:
def meth(self):
locals()['a'] = 1
#не сработает =(
print a

a1 = A()
a1.meth()
python run.py
True
Traceback (most recent call last):
File "a.py", line 9, in <module>
a1.meth()
File "a.py", line 6, in meth
print a
NameError: global name 'a' is not defined
Стас Агарков
Вы хотите сказать, что в случае с классами не сработает?
ZAN
Немного отклонюсь от вопроса и расскажу о том, как устроены области видимости в питоне и что будет, если использовать конструкцию locals = value в разных ситуациях
Всего в питоне есть только три вида областей видимости - модуля (глобальный namespace), класса и функций (локальные).
Все, что определено на уровне модуля (вне классов и функций) - очевидно принадлежит области видимости модуля. Этот namespace является самым верхним в иерархии и для него locals == globals.
>>> globals() is locals()
True
Как следствие - выражение locals = 12 изменит глобальный namespace

Функции и методы.
Поиск переменной работает здесь по такому принципу - если в теле функции есть инициализация переменной, то она считается локальной и поиск ведется только в locals(), если инициализации нет (или явно указано global varname) - в globals(), а затем в __builtin__. Проверка, будет ли инициализирована переменная в теле функции, происходит до выполнения кода функции.
>>> a = 1
>>> def meth():
... print a
... a = 2
...
>>> meth()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in meth
UnboundLocalError: local variable 'a' referenced before assignment
Обойтись без рантайма здесь можно потому, что инициализировать переменную можно только:
#1. Присваиванием
a = 1

#2. Импортированием
import time

#3. Определением нового класса
class A: pass

#4. Определением функции
def fun(): pass

#5. Другими языковыми конструкциями, которые
#(будучи преобразованными в AST) на самом деле
#тоже включают в себя присваивание, точно такое
#же, как и в п. 1:
try:
pass
except Exception, e:
#присваивание переменной e
pass

>>> a = ast.parse("""
... try:
... pass
... except Exception, e:
... pass""")

>>> name_node = a.body[0].handlers[0].name
>>> print name_node, name_node.id
<_ast.Name object at 0x7f35f6f18b10> e
#присваивание здесь есть и можно посмотреть, что имя переменной == 'e'

for i in xrange(10):
#присваивание переменной i
pass
[i for i in xrange(10)]
Во всех этих случаях имя переменной известно зарание, поэтому и нет особых проблем с разбором модуля на области видимости до выполнения кода. Но если вдруг разрешить присваивание locals() = ‘asdf’, то такая проблема возникнет.


Переменные в области видимости класса определяют его тип - когда интерпретатор встречает объявление класса, он создает новую область видимости, выполняет пошагово тело класса, а затем, когда этот namespace готов, связывает его с ClassName.__dict__ (для классов нового типа ClassName.__dict__ - это не настоящий dict, а dictproxy object, но последовательность та же и изменяя locals() также будет менятся соотвествующий атрибут ClassName.attr).
>>> class A:
... global d
... d = locals()
...
>>> d is A.__dict__
True
>>> class A(object):
... locals()['a'] = 1
...
>>> A.a
1
Причем у классов разрешение переменных на локальные и глобальные происходит в рантайме:
>>> a = 1
>>> class A:
... print a
... a = 2
...
1
Я к тому, что выражение locals() = value довольно неочевидная штука, и я бы его не использовал без крайней нужды
Isem
class Daemon:
def prop(self):
pass


name = ‘Daemon’


# вернет класс Daemon
eval(name)
Ed
Isem
# вернет класс Daemon
eval(name)
Не учите людей плохому. Оно конечно вернет, но это сильно зависит от того, откуда пришло это самое name.
Там ведь можно написать любой код и еvil(это не опечатка) его выполнит.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB