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 10:47 am (UTC)
From: [identity profile] virkony.livejournal.com
A.py:
  g1=1
  g2=[1]

B.py:
  import A
  from A import g1, g2
  g1+=1
  g2+=[2]
  print A.g1, g1
  print A.g2, g2

python B.py:
1 2
[1, 2] [1, 2]

Не думай об идентификаторах как о ячейках, это просто ссылки и если в процессе работы ты поменяешь ссылку на другой объект, то так значит и надо.
Не забывай, что ты сам можешь вполне сделать всяческие MutableInt и MutableString.

Date: 2006-08-28 11:05 am (UTC)
From: [identity profile] virkony.livejournal.com
class mumap:
    def __init__(self, proc, seq):
        self.__proc = proc
        self.__seq = seq
        self.__len__ = seq.__len__

    def __contains__(self, y):
        for val in self.__seq:
            if self.__proc(val) == y: return True
        return False

    def __eq__(self, y):
        if len(self) != len(y): return False
        i = iter(self.__seq)
        j = iter(y)
        try:
            if self._proc(i.next()) != j.next(): return False
        except StopIteration:
            return True

    def __getitem__(self, y): return self.__proc(self.__seq[y])
    def __getslice__(self, i, j): return mumap(self.__proc, self.__seq[i:j])
    def __iter__(self):
        i = iter(self.__seq)
        while True: yield self.__proc(i.next())
    def __str__(self): return ", ".join(self)


x = ["a","b"]

y = mumap(lambda x: x+"z", x)
print y
x[0]="g"
print y

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 08:49 pm
Powered by Dreamwidth Studios