Найти - Пользователи
Полная версия: Базовый синтаксис: почему циклится?
Начало » Python для новичков » Базовый синтаксис: почему циклится?
1
eki-attar
Не могу понять, почему программа циклится
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()
Почему последняя команда циклит программу? Вывод я смотрел, но всё равно не понимаю, почему print печатает сначала
<instance>
<instance>,
<instance>,
а затем снова то же самое.


Использую Eric 4, Python 2.6.
pyuser
У Вас ничего не “циклится”, функция 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 ####################################
eki-attar
Ваш код работает через консоль нормально, а Eric почему-то выдаёт ошибку “str object is not callable” в цикле, в последнем элементе. При этом если делаю
print , вижу, что все объекты - типа SqlString.

Мой скрипт как раз и задумывался с рекурсией. Только почему-то она начинает идти вглубь бесконечно.
eki-attar
Даже вот такой скрипт зацикливается:
def implode(values):
if isinstance(values, (list, tuple)) :
return ', '.join([v.Sql() for v in values if isinstance(v, (SqlComb, SqlString))])
else :
return ''
Что я делаю не так?
eki-attar
Блин, жоская штука удав :] Проблема была в том, что _select был свойством класса, то есть общим для всех экземпляров. Поэтому когда я добавлял объект a в b._select, он добавлялся и в a._select, т.е. получалась циклическая ссылка. Полчаса разбирались вместе с опытным питонистом.

http://zephyrfalcon.org/labs/python_pitfalls.html (№4)
pyuser
я же Вам сразу написал: переменная _select объявлена у вас как переменная класса :)
Александр Кошелев
eki-attar
Полчаса разбирались вместе с опытным питонистом.
Так долго? Значит он не опытный…:-)
eki-attar
Я эту фразу читал, но мне она ничего не говорила :)
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