[py] забавно
Куда хоть собеседование было? И на какую должность?
Да не было никакого, просто такая вроде бы простая вещь:
есть у питона внутреннее представление, и там он не совсем скриптовый.
А простую вещь где еще спрашивать
P.S. То бишь сам нашел
есть у питона внутреннее представление, и там он не совсем скриптовый.
А простую вещь где еще спрашивать

P.S. То бишь сам нашел
foo = 'a'
def fn:
print foo
global foo
foo = 'b'
fn
Сработает... А что такое "не совсем скриптовый"?
Сработает
Да я знаю как сработает. Проблема не в "как написать"

Если
def main:
foo = True
def fn:
foo = False
fn
И global не поможет, поможет [True], например. Тут дело становится в типе и связывании.
global еще и некошерный
Не совсем скриптовый — значит "вперед" подсматривает. Обычно же в документации рассказывают про line физические и логические, мол скрипт по строкам выполняется.
Ну, это вопрос скорее области видимости и closures. Вроде бы везде "обсосан" 
А про скриптовость... думаю, большинство байткодовых скриптовых языков такие

А про скриптовость... думаю, большинство байткодовых скриптовых языков такие
Ну, это вопрос скорее области видимости и closures.
def first:
foo = True
def fn:
foo = False
fn
print foo
def second:
foo = [True]
def fn:
foo[0] = False
fn
print foo
области видимости отличаются?
большинство байткодовых скриптовых языков такие
Я не знал
Ну и пример простой, мне понравился.
Ну, проблема касается именно локальных переменных. Поэтому область видимости. А проблема в оптимизации локальных переменных на этапе генерации байткода. Проблема известна давно, еще в python warts описана.
А проблема в оптимизации локальных переменных на этапе генерации байткода.Не вижу тут проблемы в оптимизации локальных переменных на этапе генерации байткода
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.Это не проблема, это типа так язык устроен.
If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.
The following constructs bind names: ... and targets that are identifiers if occurring in an assignment, for loop header, or in the second position of an except clause header.
Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block).
типа вот:
>>> dis.dis (first)
...
3 6 LOAD_CONST 1 (<code object fn at 0x8a673c8, file "<pyshell#4>", line 3>)
9 MAKE_FUNCTION 0 # сделали функцию без параметров
12 STORE_FAST 1 (fn)
5 15 LOAD_FAST 1 (fn)
18 CALL_FUNCTION 0
21 POP_TOP
...
>>> dis.dis (second)
2 0 LOAD_GLOBAL 0 (True)
3 BUILD_LIST 1
6 STORE_DEREF 0 (foo)
3 9 LOAD_CLOSURE 0 (foo)
12 BUILD_TUPLE 1 # типа одна свободная переменная
15 LOAD_CONST 1 (<code object fn at 0x8a72188, file "<pyshell#7>", line 3>)
18 MAKE_CLOSURE 0 # сделали замыкание без параметров
21 STORE_FAST 0 (fn)
...
>>>
оптимизация не при чем, вроде.
Называй как хочешь. Я это называю оптимизацией, так как байт-код компилятор делает предположения на основе анализа всего блока кода, даже того, который к моменту выполнения определенных команд еще не выполнится.
Python's source-to-bytecode compiler tries to optimize accesses to local variables. It decides that a variable is local if it's ever assigned a value in a function. Without the assignment i = i + 1, Python would assume that i is a global and generate code that accessed the variable as a global at the module level. When the assignment is present, the bytecode compiler generates different code that assumes i is a local variable; local variables are assigned consecutive numbers in an array so they can be retrieved more quickly.
Вы вроде про разное, ты про первый кусочек кода говоришь, а — про последний.
Эти кусочки про разное:
первый про разбор кода функции, про который как раз я не знал, и про что ты привел цитату
второй про naming, который как раз везде разбирается и рассказывается.
Эти кусочки про разное:
первый про разбор кода функции, про который как раз я не знал, и про что ты привел цитату
второй про naming, который как раз везде разбирается и рассказывается.
Продолжение (это правда совсем для детского сада):
Что выдаст:
и что
~/test fvv$ cat foo.py
import bar
print 'foo'
~/test fvv$ cat bar.py
import foo
print 'bar'
Что выдаст:
~/test fvv$ python foo.py
и что
~/test fvv$ python
>>> import foo
Ты злодей! 
Я уж было решил, что чего-то не знаю и запустил интерпретатор проверить. И через пару минут обнаружил, что все я знаю
В общем, в тему треда "забавно" не попрет

Я уж было решил, что чего-то не знаю и запустил интерпретатор проверить. И через пару минут обнаружил, что все я знаю
В общем, в тему треда "забавно" не попрет

А объясни или дай ссылку на объяснение того, почему так, пожалуйста!
Если запускаешь скрипт из командной строки, то у него __name__ == "__main__".
При импорте модуль много раз не импортируется, интерпретатор хранит список импортированных модулей и импортирует только если в списке модуля еще нет.
В первом случае в списке нет foo, есть __main__, вот он foo и импортирует второй раз.
Во втором случае оба модуля нормальным образом оказываются в списке, импортируются по одному разу.
Как-то так
При импорте модуль много раз не импортируется, интерпретатор хранит список импортированных модулей и импортирует только если в списке модуля еще нет.
В первом случае в списке нет foo, есть __main__, вот он foo и импортирует второй раз.
Во втором случае оба модуля нормальным образом оказываются в списке, импортируются по одному разу.
Как-то так

class ClassAddMixin:А почему вот эта штука не работает?
def _add(self, other):
self.__dict__.update(other.__dict__)
return self
__add__ = classmethod(_add)
class A(ClassAddMixin):
def f(self):
print "A.f"
class B(ClassAddMixin):
def g(self):
print "B.g"
AB = A + B
# AB = A.__add__(B)
ab = AB
ab.f
ab.g
TypeError: unsupported operand type(s) for +: 'classobj' and 'classobj'Если сложение убрать и раскомментировать следующую строку, то все ок. Есть какие-то особенности перегрузки операторов в classobj?
Если ты хочешь складывать классы оператором +, объяви __add__ в их метаклассе.
мое до исправления:
На самом деле:
Для каждого модуля есть понятие import time code - код, работающий при импорте. Сюда
входит все, что описано вне классов/функций + создание классов/функций по их описаниям. Этот код выполняется единожды при первом импорте модуля. В случае запуска модуля как скрипта, импорт этого модуля не выполняется. Поэтому там по два вывода при импорте в интерпретаторе и три при запуске как скрипт. А порядок вывода определяется порядком первого импорта и вложенностью. Ну банально, короче.
На самом деле:
Для каждого модуля есть понятие initialization code. Сюда входит все, что описано вне классов/функций. Этот код выполняется единожды при первом импорте модуля. В случае запуска модуля как скрипта, импорт этого модуля не выполняется.В последнем предложении я могу быть не прав. Я так и не смог выяснить, можно ли назвать создание __main__ модуля импортом. Впрочем, как мне уже намекнули, это религиозный вопрос.
Оставить комментарий
pilot
Что-то такое имхо можно спрашивать на собеседовании:Не запуская, сказать:
Что выдаст такой скрипт?
Что выдаст такой скрипт, если раскомментировать строчку? (И главное, где
Для меня было новостью