Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 29, 2009 23:20:31

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

Базовый синтаксис: почему циклится?

Не могу понять, почему программа циклится

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.



Офлайн

#2 Июнь 30, 2009 06:28:40

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Базовый синтаксис: почему циклится?

У Вас ничего не “циклится”, функция 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 ####################################



Офлайн

#3 Июнь 30, 2009 07:48:28

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

Базовый синтаксис: почему циклится?

Ваш код работает через консоль нормально, а Eric почему-то выдаёт ошибку “str object is not callable” в цикле, в последнем элементе. При этом если делаю
print , вижу, что все объекты - типа SqlString.

Мой скрипт как раз и задумывался с рекурсией. Только почему-то она начинает идти вглубь бесконечно.



Офлайн

#4 Июнь 30, 2009 07:52:15

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

Базовый синтаксис: почему циклится?

Даже вот такой скрипт зацикливается:

def implode(values):
if isinstance(values, (list, tuple)) :
return ', '.join([v.Sql() for v in values if isinstance(v, (SqlComb, SqlString))])
else :
return ''
Что я делаю не так?



Офлайн

#5 Июнь 30, 2009 08:55:02

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

Базовый синтаксис: почему циклится?

Блин, жоская штука удав :] Проблема была в том, что _select был свойством класса, то есть общим для всех экземпляров. Поэтому когда я добавлял объект a в b._select, он добавлялся и в a._select, т.е. получалась циклическая ссылка. Полчаса разбирались вместе с опытным питонистом.

http://zephyrfalcon.org/labs/python_pitfalls.html (№4)



Офлайн

#6 Июнь 30, 2009 10:04:35

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Базовый синтаксис: почему циклится?

я же Вам сразу написал: переменная _select объявлена у вас как переменная класса :)



Офлайн

#7 Июнь 30, 2009 10:27:20

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Базовый синтаксис: почему циклится?

eki-attar
Полчаса разбирались вместе с опытным питонистом.
Так долго? Значит он не опытный…:-)



Офлайн

#8 Июнь 30, 2009 18:07:15

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

Базовый синтаксис: почему циклится?

Я эту фразу читал, но мне она ничего не говорила :)



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version