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-27 09:25 am (UTC)
From: [identity profile] dinozavrik.livejournal.com
А мне только-только питон начал нравится как скриптовалка-текстодробилка (на замену перлу).
Чем теперь заменить?

Date: 2006-08-27 09:33 am (UTC)
From: [identity profile] ormuz.livejournal.com
global ведь вроде нужно делать в блоке, где переменная используется.

типа

zhu=1
def a():
global zhu
zhu=zhu+1


тада работает.

Date: 2006-08-27 04:36 pm (UTC)
From: [identity profile] trivee.livejournal.com
Очень странная логика, Неч.

В обоих примерах с global оно используется неправильно. (При этом в качестве извинения приводится "лаконичность документации".)

Последний пример с import тоже не имеет никакого смысла. "Import ... defines a name or names in the local namespace ... From<>import ... binds the name to the object thus found." Наличие from A import g1 в модуле main вводит имя g1 в каталоге модуля main и связывает его с объектом из модуля A (в данном случае None).

Короче, надо читать документацию внимательно, перед тем как поднимать панику, что Питон вымрет.

Date: 2006-08-28 04:58 am (UTC)
From: [identity profile] klinok.livejournal.com
Imho питоновская система отступов - как раз великое благо. Уже за одно это питон можно выбирать на роль языка первоначального обучения программированию. Чтобы привыкали, сволочи, писать вложенные циклы не в один столбик. :)

Date: 2006-08-28 10:10 am (UTC)
From: [identity profile] virkony.livejournal.com
ты ещ вспомни вариант
def hehe(smiles=[]):
smiles.append(':)')
print " ".join(smiles)

hehe()
hehe()
hehe(["8-o"])
hehe()


просто он другой...
все привыкли декларировать локльные переменные явно, а из вышестоящего импортировать по дефолту
тут же на оборот локальные выделяются по умолчанию в случае присваивания, что очень удобно для некоторых (покрайней я за собой часто замечал постоянные декларации всяческих итераторов и временных)
по поводу управления доступом - это реализуется с помощью имен (аля __private - что вызовет пробразование в ____private или что-то в этом роде)

>...Только вопрос - из какой такой логики переменные можно читать (а заодно вызывать в них >методы, и вообще вытворять всё что угодно), но нельзя делать только одно - присвоение?
Немножко идеи: в питоне переменные - это ссылки, когда ты пишешь a = 'x' ты создаешь ссылку на самом ближайшем фрэйме на объект 'x', а обращатся к ней ты можешь откуда угодно если не перекрываешь идентификатор или же не пере определяешь на том же уровне.
А теперь с другой стороны к тому же: все цифры и строки (и прочие) immutable - это не переменные и x += 1 - значит найти сослать идентификатор x на цифру которая является результатом x+1, т.е. сослать на новый константный объект (мне эта идея очень нравится)

Последнее очень очевидное поведение, когда ты выделив в одном модуле ссылку g1 на None (и на том же уровне f1, ссылающуюся на объект который можно вызвать) переопредлил ее.
подобное позволят экономить многие вещи, например можно не делать кучу класов, а сразу на лету подменять методы классов (см. bind)

прим: чаще всего обращение к любому объекту в питоне делается через obj.attrname.

если целью является бодание с языком, то это все конечно "клинически дурная схема" а не попытка разтормошить закостенелые мозги C++'ников и perl'овиков, ну и других.

кстати, в Tcl'е есть аж три способа связать идентификатор с переменной variable, global, upvar
в perl'е я вообще не помню что бы можно было это делать.

P.S. Эх... Prolog должен войти в школьную программу обучения, причем не так как его преподают в КПИ'ях.

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 06:25 pm
Powered by Dreamwidth Studios