LINUX.ORG.RU

[django][точнее, python] Как забегать вперёд по коду?

 


0

0

Нужно иметь связь двух объектов вида:

class Origin(models.Model):
    firm = models.ForeignKey(Firm)

class Firm(models.Model):
    origin = models.ForeignKey(Origin)

В Питоне, в отличии от многих других языков, как я понимаю, «забегать вперёд» нельзя. Я не могу использовать класс Firm, пока он не описан.

Как быть в этой ситуации?

★★★★★

Ответ на: комментарий от anonymous

>Python - ересь.

Мнения бывают разные :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от du_hast

ну тогда OneToOneField?

А чем оно идеологически от ForeignKey отличается? Всё равно же нельзя ссылаться на ещё не объявленный тип.

А так - нашёл уже в документации решение:

If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself:

class Car(models.Model):
    manufacturer = models.ForeignKey('Manufacturer')

Но всё равно не понимаю, нафига такое ограничение в Питоне сделали.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Но всё равно не понимаю, нафига такое ограничение в Питоне сделали.

Оно само получилось. И ограничение довольно условное:

class Origin(models.Model): 
    firm = None # потом присвоим 
 
class Firm(models.Model): 
    origin = models.ForeignKey(Origin) 

Origin.firm = models.ForeignKey(Firm)
tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Оно само получилось.

Типа, поленились делать более хитрую трансляцию (в случае однопроходности).

...

Обычно больше всего бесит такое в обычном коде. Привык уже всю высокоуровневую логику писать в начале файла, чтобы сразу при открытии в глаза бросалось, а всю вспомогательную мелочь - в конец. Удобнее. А тут приходится main() пихать в конец...

И ограничение довольно условное:


Всё равно костыль выходит :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

почему человек с таким богатым словарным запасом, замысловатым ником и количеством звезд задает такие глупые вопросы уже в который раз? скоро количество созданных глупых топиков привысит количество туторов с 99% информации о django *^^*...

trashymichael ★★★
()

Как быть в этой ситуации?

эммм, может так?

class Origin(models.Model): 
    firm = None
 
class Firm(models.Model): 
    origin = None

а по ходу балета присвоить им нужные ссылки

и да, а зачем такое нужно?

shty ★★★★★
()

и да, какой там питон? если 3-й, то можно на класс повесить декораторы, они связываются позже, так что должно прокатить

shty ★★★★★
()
Ответ на: комментарий от KRoN73

> Типа, поленились делать более хитрую трансляцию (в случае однопроходности).

Нет. В Питоне определения классов - выполняемые операторы, так что никакая трансляция не помогла бы.

tailgunner ★★★★★
()
Ответ на: комментарий от friday

>А не проще ли тогда объединить их в одну модель?

Нет, потому что логически это разные сущности и не каждый Origin - это Firm, как и не каждая Firm - это Origin :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от trashymichael

>почему человек с таким богатым словарным запасом, замысловатым ником и количеством звезд задает такие глупые вопросы

Так в чём глупость вопроса?

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

>В Питоне определения классов - выполняемые операторы

А, понятно.

так что никакая трансляция не помогла бы.


Почему же? Резервировать в описании место под неизвестный тип и ссылку на него в бэк-список. При нахождении нужного типа при компиляции - пропись по списку всюду, где нужно. Если к концу компиляции ничего не нашлось - ошибка. Не так и сложно.

...

Главная беда для меня тут именно в функциональной логике файлов, а не в классах. Всё же, main() в начале файла искать всегда проще, чем прыгать в его конец и потом на сколько-то отматывать назад :) Это ещё при наличии IDE с переходом по определениям. А без неё - совсем труба.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

> Резервировать в описании место под неизвестный тип и ссылку на него в бэк-список.

Это противоречит принятой политике name binding.

Всё же, main() в начале файла искать всегда проще, чем прыгать в его конец и потом на сколько-то отматывать назад :)

main должен быть именно в конце, вообще-то :) И ы любом случае, функция может быть определена и до определения классов, которые она использует.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>main должен быть именно в конце, вообще-то :)

Кто сказал? Питон, потому что по-другому не умеет? :) Я предпочитаю всякую шушеру в конец файла сваливать, а крупные определения - сверху. Хотя Форт я тоже люблю :D

И ы любом случае, функция может быть определена и до определения классов, которые она использует.


Так тут не про классы вопрос, а про вызовы функций до их определения.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>> main должен быть именно в конце, вообще-то :)

Кто сказал? Питон, потому что по-другому не умеет? :)

Это привычка из Си.

Я предпочитаю всякую шушеру в конец файла сваливать, а крупные определения - сверху.

Странно, обычно крупные вещи тяжелее и идут на дно под собственным весом %)

тут не про классы вопрос, а про вызовы функций до их определения.

В данном случае - без разницы. Вызывать функции до их определения вполне можно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Это привычка из Си.

От плохих привычек нужно быстро отучиваться :) Я на Си более 7 лет программил, но отучился очень быстро :D Точнее, переучился на более удобное.

Странно, обычно крупные вещи тяжелее и идут на дно под собственным весом %)


Когда пишешь крупную систему с нуля - да. Но я сейчас (в т.ч. на Питоне) всё больше всякие компоненты пишу для уже имеющихся систем. Их удобнее писать «сверху вниз». От общей концепции к детализации. Так что сперва main(), потом используемые в main() функции, потом функции, используемые в этих функциях, потом со всей этой фигнёй взлетаешь :)

Если пишешь сверху вниз, приходится main() «написать» в уме и держать там, пока пишешь всю мелочёвку, или писать сперва main(), а потом _надписывать_ над ней функции. И первое и второе - утомительно :)

В данном случае - без разницы. Вызывать функции до их определения вполне можно.


Да, но с хитростями. Так что проще уж тогда «надписывать» функции, чем я и занимаюсь. Но не могу не замечать, что производительность при таком подходе падает :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>>Это привычка из Си.

От плохих привычек нужно быстро отучиваться :)

Это хорошая привычка.

Я на Си более 7 лет программил, но отучился очень быстро :D

10 лет и продолжаю :)

В данном случае - без разницы. Вызывать функции до их определения вполне можно.

Да, но с хитростями.

С какими?

Так что проще уж тогда «надписывать» функции, чем я и занимаюсь

Штоето?

tailgunner ★★★★★
()
Ответ на: комментарий от antony986

ответ на твой вопрос - http://stackoverflow.com/questions/524714/does-python-have-class-prototypes-o...

Почему-то мне не кажется, что ответ правильный.

class C: pass

....

class C:
  def foo(self): pass

дает нам 2 разных класса, причем первый C теряет имя, как только исполняется определение второго C.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ну это я предложил как бы вообще

а касательно django про OneToOneField с названием модели в строке уже сказали

antony986
()
Ответ на: комментарий от KRoN73

>А чем оно идеологически от ForeignKey отличается?

Conceptually, this is similar to a ForeignKey with unique=True, but the «reverse» side of the relation will directly return a single object.

antony986
()

class Foo это сахар для присваивания foo результата трёхаргументного вызова type.

Sphinx ★★☆☆
()
Ответ на: комментарий от KRoN73

ну в контексте сабжа ничем, а так по Питеру Чену бывает связь один-к-одному, это типа как отражает такую связь, я так это понимаю

antony986
()
Ответ на: комментарий от KRoN73

Всё же, main() в начале файла искать всегда проще, чем прыгать в его конец и потом на сколько-то отматывать назад :)


def main: pass
...

if __name__==«__main__»:
main()

dimon555 ★★★★★
()

gишите в ковычках названия классов

class Origin(models.Model): firm = models.ForeignKey('Firm') class Firm(models.Model): origin = models.ForeignKey('Origin')

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.