У меня есть приложение, которое работает на Postgres и Mysql. Каждая программа проверяет базу данных, а затем импортирует либо postgres_db как db_util, либо mysql_dt как db_util. Все работает хорошо, когда код в main ссылается на db_util, но если класс импортируется, ссылка на db_util не определяется.
Я создал следующие классы и main, чтобы проверить проблему и обнаружил еще один интересный побочный эффект. Классы B и C ссылаются на класс A в различных случаях импорта. B и C идентичны, за исключением того, что B находится в основном, а C импортируется.
ClassX.py
class ClassA(object):
def print_a(self):
print "this is class a"
class ClassC(object):
def ref_a(self):
print 'from C ref a ==>',
xa=ClassA()
xa.print_a()
def ref_ca(self):
print 'from C ref ca ==>',
xa=ca()
xa.print_a()
test_scope.py
from classes.ClassX import ClassA
from classes.ClassX import ClassA as ca
from classes.ClassX import ClassC as cb
class ClassB(object):
def ref_a(self):
print 'from B ref a ==>',
xa=ClassA()
xa.print_a()
def ref_ca(self):
print 'from B ref ca ==>',
xa=ca()
xa.print_a()
print 'globals:',dir()
print 'modules','ca:',ca,'cb:',cb,'CA:',ClassA
print ''
print 'from main'
xb=ClassB()
xb.ref_a()
xb.ref_ca()
print ''
print 'from imports'
xbs=cb()
xbs.ref_a()
xbs.ref_ca()
И результаты:
globals: ['ClassA', 'ClassB', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'ca', 'cb']
modules ca: <class 'classes.ClassX.ClassA'> cb: <class 'classes.ClassX.ClassC'> CA: <class 'classes.ClassX.ClassA'>
from main
from B ref a ==> this is class a
from B ref ca ==> this is class a
from imports
from C ref a ==> this is class a
from C ref ca ==>
Traceback (most recent call last):
File "test_scope.py", line 32, in <module>
xbs.ref_ca()
File "R:\python\test_scripts\scope\classes\ClassX.py", line 13, in ref_ca
xa=ca()
NameError: global name 'ca' is not defined
Press any key to continue . . .
Из моего теста я вижу, что объект ca (импортированный как) недоступен для ClassC, однако доступен модуль ClassA (импортированный без as).
- Почему разница между импортом и импортом как поведением? Я не понимаю, почему основные глобальные переменные недоступны для основного импорта классов.
- Каков хороший подход к динамическому определению соответствующего модуля db_util для импорта и доступности его для других импортированных классов?
Обновление: после прочтения еще одного сообщения о пространствах имен: "Видимость глобальных переменных из импортированных модулей", я понимаю, что в моем примере выше причина, по которой класс A доступен для ClassC, заключается в том, что A и C находятся в одном и том же импортированном файл, таким образом, одно и то же пространство имен.
Итак, оставшийся вопрос - это вопрос дизайна:
если у меня есть такой код:
if db == 'MySQL':
from mysql_db import db_util
elif db == 'Postgres'
from postgres_db import db_util
Каков хороший способ сделать db_util доступным для всех импортируемых модулей?
ОБНОВЛЕНИЕ:
из ответа Blckknght я добавил код
cb.ca =ca
к сценарию scope_test. Это требует, чтобы вызов класса xa=ca() был изменен на xa=self.ca(). Я также думаю, что добавление объектов в класс извне, хотя Python это и позволяет, не является хорошей методологией проектирования и превратит отладку в кошмар.
Однако, поскольку я считаю, что модули и классы должны быть автономными или специально объявлять свои зависимости, я собираюсь реализовать класс таким образом, используя приведенный выше пример кода.
разбейте ClassA и ClassC на отдельные модули и в верхней части ClassC, перед определением класса, сделайте импорт
from ClassA import ClassA
from ClassA import ClassA as ca
class ClassB(object):
и в моей реальной ситуации, когда мне нужно импортировать модуль db_util в несколько модулей
ci.py #новый модуль для выбора класса для соответствующей БД
if db == 'MySQL':
from mysql_db import db_util
elif db == 'Postgres'
from postgres_db import db_util
в каждом модуле, нуждающемся в классе db_util
import ci
db_util=ci.db_util #add db_util to module globals
class Module(object):
Одна проблема с этим заключается в том, что каждый модуль, использующий db_util, должен импортировать его, но он делает известными зависимости.
Я закрою этот вопрос и хочу поблагодарить Blckknght и Armin Rigo за их ответы, которые помогли мне прояснить этот вопрос. Буду признателен за любые отзывы, связанные с дизайном.