netch: (Default)
[personal profile] netch
Если Питон вымрет, то самым толстым гвоздём в крышку гроба будет не система отступов, к которой привыкнуть - дело пары часов, не динамическая типизация и не отсутствие ограничения видимости при инкапсуляции, а клинически неестественная схема видимости переменных.

Простейший пример:


def main():
  p += 1
if __name__ == '__main__':
  p = 0
  main()


Оно отвечает:


Traceback (most recent call last):
  File "1.py", line 6, in ?
    main()
  File "1.py", line 3, in main
    p += 1
UnboundLocalError: local variable 'p' referenced before assignment


А теперь если убрать назначение p всё будет работать:


def main():
  print p
if __name__ == '__main__':
  p = 0
  main()


Но если мы после 'print p' добавим инкремент - всё снова сломается, и не выполнится даже print:


def main():
  print p
  p += 1
if __name__ == '__main__':
  p = 0
  main()


будет ошибка дословно повторяющая первый случай, 'print p' не сработает.

Смотрим как это сказано в описании языка (пункт 4.1, 'Naming and binding'):

Each occurrence of a name in the program text refers to the binding of that name established in the innermost function block containing the use.

Ну да, если внимательно вчитаться (и с поправкой далее сказанной очень туманно) что function block это и уровень модуля - да, поведение соответствует описанию. Только вопрос - из какой такой логики переменные можно читать (а заодно вызывать в них методы, и вообще вытворять всё что угодно), но нельзя делать только одно - присвоение?

Как для меня вывод однозначен - результат бессмысленной экономии на (в терминах перла) my и local.

global в использующем блоке это лечит (thx2 ormuz, я как-то пропустил из-за чрезмерной лаконичности документации). Но только по отношению к глобальным переменным (тем что в globals). И логика этого действия противоположна тому что принимается в более нормальных средствах - когда надо явно объявить переменную какая она (local, global, из внешнего блока) при жёстком контроле. Проверки компилятора и pychecker'а слабоваты.

Более скрытая вариация на ту же тему:


$ tail +1 main.py A.py
==> main.py <==
#!/usr/bin/env python
import A
from A import g1
if __name__ == '__main__':
    g1 = {}
    print id(g1), A.f1()
    A.g1 = g1
    print id(g1), A.f1()

==> A.py <==
## module A
g1 = None
def f1():
    return id(g1)


Запустив получаем:


136034476 135227424
136034476 136034476


Опять g1 оказалось локальным только потому что ему есть хотя бы одно присвоение. 'global g1' не помогло.

UPDATED (12:56) UPDATED(28.08 18:16)

Date: 2006-08-28 06:16 am (UTC)
From: [identity profile] geovit.livejournal.com
Увидев в первый раз подобный вариант:

from A import g1
A.g1 = {чтототам}

поставил в голове птичку (v) Питон - НЕ МОДУЛА-2
дальше разбираться нужды пока не было.

Date: 2006-08-28 02:58 pm (UTC)
From: [identity profile] trivee.livejournal.com
Здесь обсуждают аналогичную проблему.

Date: 2006-08-28 04:43 pm (UTC)
From: [identity profile] trivee.livejournal.com
Эрлангом кто-то для чего-то пользуется? Ужас :)

Популярность языка программирования, как известно, обеспечивается:

(1) понятностью программ, написанных на этом языке

(2) рекламой языка и культуры

(3) техническими достоинствами

Перл выигрывает по критериям (2) и (3) (но читать код на перле нельзя), питон - (1) и (3) (но рекламы в мейнстриме ему явно не хватает).

Profile

netch: (Default)
netch

December 2023

S M T W T F S
     12
3456789
10111213141516
171819 20212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 22nd, 2026 03:14 pm
Powered by Dreamwidth Studios