Форум сайта python.su
Не могу понять, почему программа циклится
import string
class SqlString:
_str = ''
def __init__(self, param):
if type(param).__name__ == 'str':
self._str = param
else:
return false
def getSql(self):
return self._str
class SqlComb:
"""A SQL parser"""
_select = []
_from = []
def __init__(self, tableName):
self._from.append(tableName)
def select(self, fields):
if type(fields).__name__ == 'str':
fields = SqlString(fields)
if type(fields).__name__ == 'instance':
self._select.append(fields)
if type(fields).__name__ == 'list':
for v in fields:
self.select(v)
def getSql(self):
r = 'SELECT ' + implode(self._select)
return r
def implode(values):
print values[0], values[1:] # возвращает < 'instance' of SqlString>, [<instance ... >, <instance >]
r = v = values[0]
if type(v).__name__ == 'instance':
r = v.getSql()
if len(values) == 1:
return r
return r + ', ' + implode(values[1:])
a = SqlComb('aaa')
a.select(['b', 'c, d, e'])
print a.getSql() # тут всё нормально, выводит то, что ожидаю
b = SqlComb('bbb')
b.select(a)
print b.getSql()
Офлайн
У Вас ничего не “циклится”, функция implode рекурсивно вызывает саму себя, отсюда и такой вывод
переменная _select? объявлена у вас как переменная класса.
Политически более правильно написать следующим образом (не придираясь к алгоритму)
class SqlString (object) :
def __init__ (self, param) :
self._str = ''
if isinstance(param, str) :
self._str = param
@property
def Sql (self) :
return self._str
class SqlComb (object) :
"""A SQL parser"""
def __init__ (self, tableName) :
self._select = []
self._from = [tableName,]
def select (self, fields) :
if isinstance(fields, str) :
fields = SqlString(fields)
if isinstance(fields, (SqlString, SqlComb)) :
self._select.append(fields)
if isinstance(fields, list) :
for v in fields :
self.select(v)
@property
def Sql (self) :
r = 'SELECT ' + implode(self._select)
return r
##___________________________________________________________________________________
def implode (values) :
if isinstance(values, (list, tuple)) :
return ", ".join([v.Sql for v in values if isinstance(v, (SqlString, SqlComb))])
else : return ""
#####################################################################################
if "__main__" == __name__ :
a = SqlComb('aaa')
a.select(['b', 'c, d, e', "f", "h"])
print(a.Sql) # тут всё нормально, выводит то, что ожидаю
b = SqlComb('bbb')
b.select(a)
print(b.Sql)
#################################### End Of File ####################################
Офлайн
Ваш код работает через консоль нормально, а Eric почему-то выдаёт ошибку “str object is not callable” в цикле, в последнем элементе. При этом если делаю
print , вижу, что все объекты - типа SqlString.
Мой скрипт как раз и задумывался с рекурсией. Только почему-то она начинает идти вглубь бесконечно.
Офлайн
Даже вот такой скрипт зацикливается:
def implode(values):
if isinstance(values, (list, tuple)) :
return ', '.join([v.Sql() for v in values if isinstance(v, (SqlComb, SqlString))])
else :
return ''
Офлайн
Блин, жоская штука удав :] Проблема была в том, что _select был свойством класса, то есть общим для всех экземпляров. Поэтому когда я добавлял объект a в b._select, он добавлялся и в a._select, т.е. получалась циклическая ссылка. Полчаса разбирались вместе с опытным питонистом.
http://zephyrfalcon.org/labs/python_pitfalls.html (№4)
Офлайн
я же Вам сразу написал: переменная _select объявлена у вас как переменная класса :)
Офлайн
eki-attarТак долго? Значит он не опытный…:-)
Полчаса разбирались вместе с опытным питонистом.
Офлайн
Я эту фразу читал, но мне она ничего не говорила :)
Офлайн