Python: предварительное определение функций
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Python: предварительное определение функций
Столкнулся с этим при написании GUI приложения на Python с использованием модуля tkinker, использующего графику Tcl/Tk ... код полный здесь: Python - графика.
А проблема в том, что если использовать глобальные переменные (а при использовании GUI пакетов это частая практика), или, например, глобальных флагов для управления потоками (а поток threading нельзя принудительно завершить другим способом извне) - то приходится перемежать код главного приложения и определения используемых функций. Потому как функции могут использовать только ранее определённые переменные, а операторы главного приложения могут вызывать только ранее определённые функции.
По Интернет, особенно зарубежном, англоязычном, задают множество раз этот вопрос... Наверное, в русскоязычном пространстве обучают языку Python лучше - знают, что нет в Python способа (или нет способа без фокусов, не знаю) вызвать из кода Python позже описанную функцию.
А проблема в том, что если использовать глобальные переменные (а при использовании GUI пакетов это частая практика), или, например, глобальных флагов для управления потоками (а поток threading нельзя принудительно завершить другим способом извне) - то приходится перемежать код главного приложения и определения используемых функций. Потому как функции могут использовать только ранее определённые переменные, а операторы главного приложения могут вызывать только ранее определённые функции.
По Интернет, особенно зарубежном, англоязычном, задают множество раз этот вопрос... Наверное, в русскоязычном пространстве обучают языку Python лучше - знают, что нет в Python способа (или нет способа без фокусов, не знаю) вызвать из кода Python позже описанную функцию.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
Моделирую проблему простейшим кодом (о его осмысленности не говорим ... осмысленный код иллюстрирующий ситуацию - в полном GUI приложении здесь: Python - графика):Olej писал(а): Потому как функции могут использовать только ранее определённые переменные, а операторы главного приложения могут вызывать только ранее определённые функции.
Код: Выделить всё
#!/usr/bin/python3
a = 1
def fun1():
global a
a += 1
return a
b = fun1()
def fun2():
global b
return b + 1
a = fun2()
print( a, b )
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ ./n0.py
3 2
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
Но вот такой номер уже не проходит:Olej писал(а):Моделирую проблему простейшим кодом (о его осмысленности не говорим ...Olej писал(а): Потому как функции могут использовать только ранее определённые переменные, а операторы главного приложения могут вызывать только ранее определённые функции.
Код: Выделить всё
#!/usr/bin/python3
if __name__ == '__main__':
a = 1
b = fun1()
a = fun2()
print( a, b )
def fun1():
global a
a += 1
return a
def fun2():
global b
return b + 1
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ ./n0-2.py
Traceback (most recent call last):
File "./n0-2.py", line 5, in <module>
b = fun1()
NameError: name 'fun1' is not defined
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
В других, компилируемых языках программирования эта проблема известна и решают её по-разному...Olej писал(а): А проблема в том, что если использовать глобальные переменные (а при использовании GUI пакетов это частая практика), или, например, глобальных флагов для управления потоками (а поток threading нельзя принудительно завершить другим способом извне) - то приходится перемежать код главного приложения и определения используемых функций.
Одни из старых языков - C и C++ - используют предварительное описание функций и требуют обязательного предварительного описания:
Код: Выделить всё
#include <stdio.h>
int a = 1;
int fun1( void ) {
a += 1;
return a;
}
int fun2( void ); // предварительное описание fun2
int b;
int main() {
b = fun1();
a = fun2();
printf( "%d %d\n", a, b );
}
int fun2( void ) {
return b + 1;
}
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ gcc n1.c -o n1_c
olej@ACER:~/2019_WORK/own.WORK/python$ ./n1_c
3 2
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
Один из новых языков Go (и ряд других тоже), используя отрицательный опыт предшественников C/C++, допускает прямое использование позже описанных функций, за счёт того, что компилятор просматривает исходный код в несколько проходов (во времена создания C на скорости обработки приходилось сильно экономить, а C++ вынужден был поддерживать синтаксическую совместимость с C):Olej писал(а): Одни из старых языков - C и C++ - используют предварительное описание функций и требуют обязательного предварительного описания:
Код: Выделить всё
package main
var a int = 1
func fun1() int {
a += 1
return a
}
var b int
func main() {
b = fun1()
a = fun2()
print( a, " ", b, "\n" );
}
func fun2() int {
return b + 1
}
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ gccgo n1.go -o n1_go
olej@ACER:~/2019_WORK/own.WORK/python$ ./n1_go
3 2
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ go build -o n1_gl n1.go
olej@ACER:~/2019_WORK/own.WORK/python$ ./n1_gl
3 2
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
Всё это достаточно понятно ... потому что программа Python, точнее переменные (объекты) программы Python - это словарь, содержащий пары имя:значение, где имя является ключом словаря. Это хорошо видно, если чуть расширить начальное приложение:Olej писал(а): Но вот такой номер уже не проходит:
Код: Выделить всё
#!/usr/bin/python3
import sys
def pg():
own = {}
for key, val in zip( globals().keys(), globals().values() ):
if key.find( '_' ) < 0: own[ key ] = val
del own[ sys._getframe().f_code.co_name ], own[ 'sys' ]
print( own )
a = 1
pg()
def fun1():
global a
a += 1
return a
pg()
b = fun1()
pg()
def fun2():
global b
return b + 1
pg()
a = fun2()
print( a, b )
Вот как наполняется словарь по ходу выполнения:
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ ./n1.py
{'a': 1}
{'a': 1, 'fun1': <function fun1 at 0x7fb2a38a5d08>}
{'a': 2, 'fun1': <function fun1 at 0x7fb2a38a5d08>, 'b': 2}
{'a': 2, 'fun1': <function fun1 at 0x7fb2a38a5d08>, 'b': 2, 'fun2': <function fun2 at 0x7fb2a38a56a8>}
3 2
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
Зато вот такой проходит:Olej писал(а): Но вот такой номер уже не проходит:
Код: Выделить всё
#!/usr/bin/python3
def fun1():
global a
a += 1
return a
def fun2():
global b
return b + 1
a = 1
b = fun1()
a = fun2()
print( a, b )
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ ./n0-1.py
3 2
Но только и этот способ не разрешает все проблемы для более сложных и объёмных случаев кода.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Python: предварительное определение функций
А вот способ, которым можно всегда снять этот вопрос - затолкайте свой код в объект класса, пусть даже совершенно формальный:Olej писал(а):Но только и этот способ не разрешает все проблемы для более сложных и объёмных случаев кода.
Код: Выделить всё
#!/usr/bin/python3
class my():
a = 1
def __init__( self ):
self.b = self.fun1()
self.a = self.fun2()
print( self.a, self.b )
def fun1( self ):
self.a += 1
return self.a
def fun2( self ):
return self.b + 1
x = my()
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/python$ ./n2.py
3 2
И почему - это тоже понятно: к моменту создания объекта класса словарь имён уже дополнен полным описанием класса и именами его методов.
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей