Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 14, 2007 18:50:57

lukke
От:
Зарегистрирован: 2007-01-01
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

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



Офлайн

#2 Дек. 14, 2007 19:21:30

Jenyay
От:
Зарегистрирован: 2007-08-10
Сообщения: 173
Репутация: +  1  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Спасибо!



Офлайн

#3 Ноя. 7, 2009 16:54:00

Стас Агарков
От:
Зарегистрирован: 2009-11-07
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

А можно ли создать в locals() переменную со своим именем, переданным в качестве строки?



Офлайн

#4 Ноя. 7, 2009 17:07:43

crchemist
От:
Зарегистрирован: 2008-07-09
Сообщения: 379
Репутация: +  0  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

[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
>>>



Офлайн

#5 Ноя. 7, 2009 17:58:13

Стас Агарков
От:
Зарегистрирован: 2009-11-07
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Большое спасибо! То, что нужно.



Офлайн

#6 Ноя. 7, 2009 19:03:08

ZAN
От:
Зарегистрирован: 2007-06-10
Сообщения: 403
Репутация: +  10  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Не то, что нужно, т.к. присваимвание можно сделать только через 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



Офлайн

#7 Ноя. 7, 2009 19:10:48

Стас Агарков
От:
Зарегистрирован: 2009-11-07
Сообщения: 12
Репутация: +  0  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Вы хотите сказать, что в случае с классами не сработает?



Офлайн

#8 Ноя. 7, 2009 22:14:37

ZAN
От:
Зарегистрирован: 2007-06-10
Сообщения: 403
Репутация: +  10  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Немного отклонюсь от вопроса и расскажу о том, как устроены области видимости в питоне и что будет, если использовать конструкцию 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 довольно неочевидная штука, и я бы его не использовал без крайней нужды



Офлайн

#9 Авг. 27, 2010 08:18:42

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

class Daemon:
def prop(self):
pass


name = ‘Daemon’


# вернет класс Daemon
eval(name)



Офлайн

#10 Авг. 27, 2010 12:32:22

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Преобразование строки в имя класса

Isem
# вернет класс Daemon
eval(name)
Не учите людей плохому. Оно конечно вернет, но это сильно зависит от того, откуда пришло это самое name.
Там ведь можно написать любой код и еvil(это не опечатка) его выполнит.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version