Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 2, 2016 22:22:18

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

1) Подскажите как можно передать переменные основной программы (если их прилично много) в собственный модуль который нуждается в тех переменных ?

В модуле всего одна функция и она требует переменных из главного файла.
Как я понял можно сделать так:

function(par1, par2, par3, par4...]
# что делать если параметров 15 ?

Как то стразу можно определить что бы переменные из основной программы использовались в собственном импортируемом модуле, кроме примера выше ?

2) чем отличается directiry от Python package ? или откуда правильно импортировать модуль на выполнение ?

3)
основной файл:
from gfx.stars import stars
файл __init__.py в папке gfx:
import gfx.stars
основной файл:
stars(distanceBetweenTheStar, 10)
# с ошибкой:
Traceback (most recent call last):
  File "C:/PycharmProjects/kosmos/main.py", line 36, in <module>
    stars(distanceBetweenTheStar, 10)
4) Так же не могу использовать стандартный модуль random в импортируемом модуле, импортируя random из собственного модуля или из основной программы приводит к одному и тому же:
NameError: global name 'random' is not defined
Скорее всего и импорт pygame приведет к такой же ошибке, где бы я его не импортировал.

Если скопировать содержимое собственного модуля в основную программу - то все прекрасно работает, изначально так и было - решил сделать функцию отдельным модулем.

Собственно вот код программы целиком, из которой функцию stars я хочу сделать импортируемым модулем:
import pygame
import random
pygame.init()
res = pygame.display.list_modes()
width, height = res[0]
screen = pygame.display.set_mode(([width, height]), pygame.FULLSCREEN, 32)
pygame.display.toggle_fullscreen()
font = pygame.font.Font(None, 50)
clock = pygame.time.Clock()
distanceBetweenTheStar = 1      # расстояние в пикселах между предыдущей и следующей печати звезд
white = (255, 255, 255)         # цвет звезд
lime = (0, 255,   0)            # цвет букв
black = (0, 0, 0)               # фоновый цвет
fps = 60                        # кадров в секунду
allStars = []                   # создаем пустой список для всех звезд
# функция просчета и печати звезд на экран
def stars(distanceBetweenTheStar, speed):
    # печатаем новые звезды с переодичность заданной в distanceBetweenTheStar
    if distanceBetweenTheStar == 0:
        sumStars = random.randint(1, 4)     # получаем кол-во звезд в пределах 1-4
        preparationStars = []               # создаем пустой список подготовки блока вида [[],[],[]]preparation
        newStars = []                       # создаем пустой список получнех координат для полученых звезд
        # задаем координаты по Y для полученого блока звезд
        for i in range(0, sumStars):
            # в блок заносим случайную координату Y для всех звезд одного блока
            newStars.append(random.randint(0, height))
        # добовляем полученые координаты из блока звезд в список подготовки preparation
        preparationStars.append(newStars)
        # добавляем координату X которая идентична для всех звезд всех вновь созданных блоков
        # и равна правому краю экрана width
        preparationStars.append([width])
        # добавляем 
        speedBlock = random.randint(1, speed)
        preparationStars.append([speedBlock])
        # кидаем все в общий список звезд [координаты Y полученых звезд] [координата X] [скорость]
        allStars.append(preparationStars)
    starsCounter = 0
    for block in allStars:
        # вытаскиваем координату звезд блока Y
        oldCoor = block.pop(1)
        # отнимаем от координаты Y скорость speed
        subSpeed = oldCoor[0] - block[1][0]
        newCoor = subSpeed
        # вставляем измененную координату Y обратно в блок
        block.insert(1, [newCoor])
        if subSpeed >= 0:
            # печатаем звезды из изменненого блока
            for xCor in block[0]:   # берем все координаты по Х из текущего блока
                pygame.draw.rect(screen, white,[newCoor, xCor, 1, 1], 1)
                starsCounter = starsCounter + 1
        else:
            allStars.remove(block)
    starCountInScreen = font.render("Stars in screen = " + str(starsCounter), True, lime)
    screen.blit(starCountInScreen, (400, 400))
running = True
distance = distanceBetweenTheStar
while running:
    if distanceBetweenTheStar == 0:
        distanceBetweenTheStar = distance
    else:
        distanceBetweenTheStar = distanceBetweenTheStar - 1
    screen.fill(black)
    stars(distanceBetweenTheStar, 10)
    pygame.display.flip()
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            running = False
pygame.quit()

Выход из программы: ПРОБЕЛ

То есть тут получается что такие глобальные переменные как width, height и прочие работают в вызываемой функции, а сделав функцию модулем в папке эти переменные уже не видны.

при печати 15 000 - 18 000 точек, точки двигаются уже довольно смазано, то есть быстродействие падает - это особенности pygame или самого python`а ?

python 3.2

Отредактировано vito-Z80 (Апрель 2, 2016 22:44:07)

Офлайн

#2 Апрель 2, 2016 22:51:45

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

1 когда переменных много смотрят в сторону ООП. те группируют переменные в классах.
2

vito-Z80
directiry от Python package ?
Вообще не знаю слова directiry. Дайте ссылку что это.
3 Таких трейсбеков насколько я знаю не бывает. Приведите его как он есть.
vito-Z80
импортируя random из собственного модуля
Так вы свой модуль приведите. Перед этим упростите его чтобы осталось только то что вызывает ошибку.
vito-Z80
из которой функцию stars я хочу сделать импортируемым модулем
Функция никогда не может стать модулем. Вы можете вынести функцию в модуль и импортировать оттуда
vito-Z80
модулем в папке эти переменные уже не видны.
Сделайте еще модуль с этими переменными и импортируйте его в main и в stars



Офлайн

#3 Апрель 2, 2016 23:04:33

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

doza_and
1 когда переменных много смотрят в сторону ООП. те группируют переменные в классах.2

1) с ООП у меня чет проблемы… а класс можно сделать модулем с функцией как я понял и принимать глобальные переменные ?
2) Directory & Python package - в PyCharm - создание папок в проекте - чем отличаются не знаю, вот и спросил.
3) Что привести я не понял - выше листинг всего кода полностью, из которого я хочу выдрать функцию в отдельный файл отдельной папки, что бы основная программа имела меньший визуальный вид и вызывать import`ом эту функцию - что бы она работала:
import dir.stars 
#или 
from dir.stars import stars
stars(distanceBetweenTheStar, 10)
# или
stars.stars(distanceBetweenTheStar, 10)

Сделайте еще модуль с этими переменными и импортируйте его в main и в stars
тут я вообще потерялся


Еще тут вопрос нарисовался, как узнать сколько памяти жрет исполняемая программа ?


Вообщем вот так работает:
main.py
import pygame
from gfx.stars import stars
pygame.init()
res = pygame.display.list_modes()
width, height = res[0]
screen = pygame.display.set_mode(([width, height]), pygame.FULLSCREEN, 32)
pygame.display.toggle_fullscreen()
font = pygame.font.Font(None, 50)
clock = pygame.time.Clock()
distanceBetweenTheStar = 1      # расстояние в пикселах между предыдущей и следующей печати звезд
distance = distanceBetweenTheStar
white = (255, 255, 255)         # цвет звезд
lime = (0, 255,   0)            # цвет букв
black = (0, 0, 0)               # фоновый цвет
fps = 60                        # кадров в секунду
allStars = []                   # создаем пустой список для всех звезд
running = True
while running:
    if distanceBetweenTheStar == 0:
        distanceBetweenTheStar = distance
    else:
        distanceBetweenTheStar = distanceBetweenTheStar - 1
    screen.fill(black)
    stars(distanceBetweenTheStar, 10,width, height, allStars, screen, font, white, lime)
    pygame.display.flip()
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            running = False
pygame.quit()
gfx/stars
import random
import pygame
def stars(distanceBetweenTheStar, speed,width, height, allStars, screen, font, white, lime):
    # печатаем новые звезды с переодичность заданной в distanceBetweenTheStar
    if distanceBetweenTheStar == 0:
        sumStars = random.randint(1, 4)     # получаем кол-во звезд в пределах 1-4
        preparationStars = []               # создаем пустой список подготовки блока вида [[],[],[]]preparation
        newStars = []                       # создаем пустой список получнех координат для полученых звезд
        # задаем координаты по Y для полученого блока звезд
        for i in range(0, sumStars):
            # в блок заносим случайную координату Y для всех звезд одного блока
            newStars.append(random.randint(0, height))
        # добовляем полученые координаты из блока звезд в список подготовки preparation
        preparationStars.append(newStars)
        # добавляем координату X которая идентична для всех звезд всех вновь созданных блоков
        # и равна правому краю экрана width
        preparationStars.append([width])
        # добавляем
        speedBlock = random.randint(1, speed)
        preparationStars.append([speedBlock])
        # кидаем все в общий список звезд [координаты Y полученых звезд] [координата X] [скорость]
        allStars.append(preparationStars)
    starsCounter = 0
    for block in allStars:
        # вытаскиваем координату звезд блока Y
        oldCoor = block.pop(1)
        # отнимаем от координаты Y скорость speed
        subSpeed = oldCoor[0] - block[1][0]
        newCoor = subSpeed
        # вставляем измененную координату Y обратно в блок
        block.insert(1, [newCoor])
        if subSpeed >= 0:
            # печатаем звезды из изменненого блока
            for xCor in block[0]:   # берем все координаты по Х из текущего блока
                pygame.draw.rect(screen, white,[newCoor, xCor, 1, 1], 1)
                starsCounter = starsCounter + 1
        else:
            allStars.remove(block)
    starCountInScreen = font.render("Stars in screen = " + str(starsCounter), True, lime)
    screen.blit(starCountInScreen, (400, 400))

Но при таком раскладе мне приходится передавать: по мимо того что кучу параметров, так еще и при каждом вызове модуля:
def stars(distanceBetweenTheStar, speed,width, height, allStars, screen, font, white, lime):
мне приходится импортировать:
import random
import pygame
а это я так понимаю ни есть хорошо, падает производительность.. да и вообще так не должно быть как я понимаю.

методом тыка дошло, что можно random с pygame`ом так-же передать в вызываемую функцию.
stars(distanceBetweenTheStar, 10,width, height, allStars, screen, font, white, lime, random, pygame)
но опять же не знаю, хорошо это или плохо ?

Отредактировано vito-Z80 (Апрель 3, 2016 00:35:14)

Офлайн

#4 Апрель 3, 2016 09:39:53

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

vito-Z80
а класс можно сделать модулем с функцией как я понял и принимать глобальные переменные ?
Модуль это модуль, функция это функция, а класс это класс. И никаким образом одно другим не станет.
Представьте модуль это корзинка. Функция это пистолет. Функция может выполнять действия - стрелять например. Можно положить пистолеты в корзинку но положить пистолеты в пистолеты нельзя, также как и стрелять корзинкой.
Модули это корзинки для хранения функций и других объектов. С ними работают оператором import А import никаким образом к классам или функциям не применим.
vito-Z80
из которого я хочу выдрать функцию в отдельный файл
Надо было привести как выдирали, что вы сейчас и сделали.
vito-Z80
так еще и при каждом вызове модуля:
Вы не освоились с терминологией сами путаетесь и всех путаете. Модуль нельзя вызвать. Вызвать можно функцию.
vito-Z80
мне приходится импортировать:
vito-Z80
а это я так понимаю ни есть хорошо, падает производительность.
Похоже Вы не понимаете разницу между модулем и функцией. Модуль это файл. Он выполняется Питоном при импорте не более одного раза. Функций может быть много в файле. Это куски кода которые вы по своему желанию выполняете сколько угодно раз. Поэтому никакого многократного импорта не будет. Его в принципе не бывает в питоне.
А глобальные аргументы вынесите в отдельный, третий модуль, как я вам уже советовал. Вообще иметь много глобальных переменных нехорошо. Трудно делать большие проекты, поскольку в разных частях начинают пересекаться имена.
vito-Z80
но опять же не знаю, хорошо это или плохо ?
Все это очень плохо. Прочитайте книжку вместо того чтобы делать программы методом тыка.



Отредактировано doza_and (Апрель 3, 2016 09:43:06)

Офлайн

#5 Апрель 3, 2016 10:38:38

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

doza_and
Я что то вообще запутался…

читаю книжку для детей)
Hello World! Computer Programming for Kids and Other Beginners Уоррен Сэнд, Картер Сэнд (еще в процессе)

Модуль нельзя вызвать. Вызвать можно функцию.
Модуль это файл. Он выполняется Питоном при импорте не более одного раза.
Честно сказать я путаюсь от подобного - если файл выполняется, в котором функция, разве это не считается его вызовом/выполнением/исполнением ?
Это куски кода которые вы по своему желанию выполняете сколько угодно раз. Поэтому никакого многократного импорта не будет. Его в принципе не бывает в питоне.
модуль выполняется питоном 1 раз
в модуле функции которые должны выполняться программой при вызове модуля
многократного импорта не будет
я реально не догоняю
почему не будет многократного вызова, если модуль (это подгружаемый файл) выполняется питоном 1 раз ?
А глобальные аргументы вынесите в отдельный, третий модуль, как я вам уже советовал.
то есть скажем создать в папке glob файл glob.py и в него засунуть глобальные переменные, что бы импортировать его в main.py & gfx/stars.py, я правильно понял ?

Отредактировано vito-Z80 (Апрель 3, 2016 10:46:46)

Офлайн

#6 Апрель 3, 2016 12:12:31

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

глобальные переменные в свой модуль

vito-Z80
то есть скажем создать в папке glob файл glob.py
Не нужна папка. Просто файл создайте “my_global_vars.py” рядом с вашими main.py и прочим.
from my_global_vars import * # дурной стиль но соответствует вашим целям.
Не называйте его glob.py. Так называется один из стандартных модулей питона

vito-Z80
если файл выполняется, в котором функция,
Когда питон видит определение функции (при импорте или если вы в интерактивной консоли набрали определение) он запоминает что она есть, но не выполняет ее. Как он ее выполнит? У него ведь аргументов передаваемых в функцию нет.

vito-Z80
разве это не считается его вызовом/выполнением/исполнением ?

Выполнение это команда в командной строке
python you_module.py
Или в интерпретаторе вызов ОС для выполнения файла
import subprocess as sp
sp.check_call("python you_module.py",shell=1)

Импорт это внутри вашего экземпляра питона выполнение инструкции
import you_module

При этом происходят похожие вещи, но не идентичные. Не надо их путать. Для ваших задач это важно.

vito-Z80
я реально не догоняю
почему не будет многократного вызова, если модуль (это подгружаемый файл) выполняется питоном 1 раз ?
А я не догоняю что вы имеете ввиду. Тут с логикой чтото.




Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version