[py] забавно


Куда хоть собеседование было? И на какую должность?
есть у питона внутреннее представление, и там он не совсем скриптовый.
А простую вещь где еще спрашивать

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.
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, который как раз везде разбирается и рассказывается.
~/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

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

В общем, в тему треда "забавно" не попрет

А объясни или дай ссылку на объяснение того, почему так, пожалуйста!
При импорте модуль много раз не импортируется, интерпретатор хранит список импортированных модулей и импортирует только если в списке модуля еще нет.
В первом случае в списке нет 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
Что-то такое имхо можно спрашивать на собеседовании:Не запуская, сказать:
Что выдаст такой скрипт?
Что выдаст такой скрипт, если раскомментировать строчку? (И главное, где
Для меня было новостью