LINUX.ORG.RU

Глобальные переменные vs. Поля класса

 


0

2

Переписываю старинное легаси, узнаю как нельзя писать код))) Есть определенные скрипты, где большая связанность кода из-за использование глобальных переменных, которые можно заменить на поля класса, так ещё и удобнее станет. По типу:

class GlobalData:
    pass

f2():
    global i # не работает
    i += 1 
    GlobalData.counter += 1 # работает
    print(GlobalData.counter)

f1():
    i = 0
    GlobalData.counter = 0
    print(GlobalData.counter)
    f2()

f1()

Раньше как-то не задумывался как глобальные могут быть полезны, а теперь так и не понимаю зачем они вообще нужны. Может есть скоп задач где они лучше подходят?



Последнее исправление: Cirno (всего исправлений: 1)

В Метапрог вообще переменных нет, а сгенерированный сишный код содержит одни глобальные переменные …

anonymous
()

Откуда могут возникнуть такие избранные вопросы? Зачем нужны глобальные переменные? Например, для использования их в качестве констант. Констант в пхайтоне нет, но если не глобализировать глобальные переменные перед использованием в функциях и методах, то изменить их не получится (если не рукожоп), что позволяет сделать вид, что это константы.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)

Если вы «приверженец» использования глобальных переменных, то декларируйте одну глобальную переменную, которая является структурой.
А в нее поместите сколько вам угодно полей …

Владимир

anonymous
()
Ответ на: комментарий от Begemoth

Принципиально – ничем. Такой задачи и не ставилось. Нужно было просто портянки сделать в виде функций и модулей. Разумеется глобальные переменные этому мешали и нужно их было чем-то заменить.

Cirno
() автор топика

Переменную имеет смысл делать глобальной, если она используется в большинстве модулей проекта, но при этом остается неизменной большую часть времени. Первое условие очевидно, второе очень важно, иначе будет много функций (методов), имеющих побочные эффекты, что не хорошо.

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

hotpil ★★★★
()
Ответ на: комментарий от hotpil

Таким образом, размеры можно спокойно сделать глобальными переменными.

Потом самолетов становится два и привет.

Nervous ★★★★★
()
Ответ на: комментарий от hotpil

Но ведь можно такие глобальные переменные просто в config.py описать и усе. И делать импорты в модулях где использование происходит. Или хитрость есть?

Cirno
() автор топика
Последнее исправление: Cirno (всего исправлений: 2)
Ответ на: комментарий от Cirno

Разумеется глобальные переменные этому мешали и нужно их было чем-то заменить.

Ну и теперь ты просто не дергаешь global каждый раз чтоб записать значение. Фактически разницы никакой, у тебя как был код с глобальными переменными, так и остался, просто считай что у тебя теперь "глобальный объект". Если ты стараешься "просто портянки сделать в виде функций и модулей" то пиши чистые функции.

узнаю как нельзя писать код

Классы, в которых по сути один инит (ну и тупые присвоение и возврат значений, где хранящиеся данные не изменяются), так то тоже не являются примером хорошего кода. Ты вполне можешь в таком случае обойтись банальным словарем.

micronekodesu ★★★
()
Последнее исправление: micronekodesu (всего исправлений: 1)

если можно обойтись без глобальных переменных, лучше обойтись, если нельзя, лучше завернуть это в синглтон (это все еще по сути глобальная херня, но уже лучше), в питоне нет трединга в пределах языка, но он есть за его пределами c биндингами. Если он используется нужен код для огораживания.

anonymous
()
Ответ на: комментарий от Begemoth

Ну если отказ от пихания классов куда ни попадя вызывает зуд то да. Надо только не забыть что такой "код" перестает работать на питоне до 3.7, вмазать туда тайпхинтов, и получить тот же дебильный класс с одним инитом.

micronekodesu ★★★
()
Ответ на: комментарий от micronekodesu

С той лишь разницей, что с dataclass - это именно код, а не «скрипт» с дебильным словарем.

Begemoth ★★★★★
()
Ответ на: комментарий от dem

Я нынешний третий питон практически не знаю, тем более, как посмотрю, правильнее сказать «наконец-то есть». Но у ТС еще классы старого образца, так что он вероятнее всего на старом добром 2.7 сидит.

Virtuos86 ★★★★★
()
Ответ на: комментарий от micronekodesu

то пиши чистые функции.

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

хранящиеся данные не изменяются

Очень даже часто изменяются. Если бы они не менялись я бы конечно более удобную структуру выбрал.

Вообще вопрос в посте был про другое.

Cirno
() автор топика
Последнее исправление: Cirno (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Старого образца мне просто больше нравятся, а так 3.6

Cirno
() автор топика

Что то говнокод, что это.

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

Правильными будут следующие подходы (выбирать исходя из задачи):

  1. Функции, использующие общие переменные, выносятся в отдельный класс. Их общие переменные делаются его полями.

  2. Создается класс стейта, в который выносятся переменные. Функции принимают стейт и изменяют его.

Комбинированием этих подходов можно легко решить любую задачу.

Почему важно не использовать глобальные переменные в любом виде? Подумай о том, как ты свой код тестировать будешь. В подавляющем большинстве случаев, при использовании глобальных переменных, код превращается в окаменевший кусок говна. Это первый момент. Момент второй, работа с инкапсулированным состоянием позволяет держать несколько разных состояний или легко их сериализовывать/десериализовывать, управлять доступом (как правами, так и логиков при, например, многопоточном приложении).

Norgat ★★★★★
()

Глобальные переменные вообще нельзя использовать из за невозможности в будущем их рефакторить не сломав всё, что ими пользуется.

system-root ★★★★★
()
Ответ на: комментарий от Cirno

Нет никаких хитростей, можно по разному делать, но по сути это все равно глобальные переменные.

hotpil ★★★★
()
Ответ на: комментарий от system-root

Да тогда любые переменные нельзя использовать. Нет, глобальные это конечно зло, но иногда неизбежное. Я не видел ни одного реально крупного проекта без глобальных переменных.

hotpil ★★★★
()
Ответ на: комментарий от Norgat

Функции, использующие общие переменные, выносятся в отдельный класс. Их общие переменные делаются его полями.

Ну и что, это все равно по сути будет глобальная переменная, тольлко с областью видимости внутри класса.

Но область видимости можно ограничить и более простыми способами. Обычно глобальные помещаются в отдельный модуль. Куда он включается – там они видны, а куда нет – там их нет.

hotpil ★★★★
()
Ответ на: комментарий от Nervous

В данном примере самолетов не может стать два. Это код для одного самолета.

Очевидно, что далекл не любые изменения можно провести без радикального изменения проекта вне зависимости от стиля написания кода.

hotpil ★★★★
()
Ответ на: комментарий от hotpil

В данном примере самолетов не может стать два. Это код для одного самолета.

Все так думают. А потом становится нужно посчитать заправку в воздухе, и понеслась.

Nervous ★★★★★
()
Ответ на: комментарий от Cirno

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

vvn_black ★★★★★
()
Ответ на: комментарий от hotpil

Ну, «я не видел» такой себе аргумент.

Есть вещи, которые нужны много где, например hibernate или инстанс vertx, если применительно к java, но это объекты библиотек, к ним тема с рефакторингом не применима, только бамп версий. И то, они лежат в синглтонах, на всякий случай, а не импортятся из рандомного класса, где их первый раз определили.

Всё, больше, например, мы нигде глобальные переменные (считай паблик константы) не используем и это несложно, если просто это делать.

Нет ни одного кейса, когда это «необходимо» и нельзя по другому.

system-root ★★★★★
()
Ответ на: комментарий от RazrFalcon

Ну всеж динамика. Однако я точно знаю когда обсирается Го, а python живет и с растом тоже такое может быть… Угадай что я хотел написать?

dem ★★
()

можно заменить на поля класса, так ещё и удобнее станет

Поздравляю, ты изобрёл синглтон.

no-such-file ★★★★★
()
Ответ на: комментарий от Nervous

Потом у каждого самолета становится два набора параметров тяги, и снова привет. Проблема не в самих глобальных переменных, а в том, что в большинстве языков есть возможность размазать их по коду, и в итоге они не лежат в одном единственном месте, откуда легко вынуть часть и раскидать по инстансам, если потребуется. Если дать объявлять глобалы только в специализированных местах, никаких приветов не будет. С другой стороны синглтоны это и есть те места, так что можно просто запретить глобалы и юзать модульность. Выносить всё в инстансы сразу, как это выше по треду предлагали, это оверинжиниринг. Так можно и н/у плотность воздуха туда засунуть, и g, и c, и заряд электрона. В итоге софт для аэропорта преращается в софт для кластеров аэропортов на группах планет у различного типа звезд.

anonymous
()
Ответ на: комментарий от no-such-file

А ведь думал, что ООП ещё так далеко…

Cirno
() автор топика
Ответ на: комментарий от anonymous

Выносить всё в инстансы сразу, как это выше по треду предлагали, это оверинжиниринг

Может быть. Но я думаю, что когда параметры одного самолета лежат в одном неймспейсе с параметрами всего остального мира — это недоинжиниринг.

Nervous ★★★★★
()

Глобальные переменные vs. Поля класса

Глобальная переменная похожа на кошелек.
Попробуйте его оставить на лавочке возле подъезда …

anonymous
()
Ответ на: комментарий от hotpil

Их общие переменные делаются его полями.

Ну и что, это все равно по сути будет глобальная переменная, тольлко с областью видимости внутри класса.

Их область видимости — объект.

korvin_ ★★★★★
()

Не слушай никого.
Они тебе все завидуют и специально врут …
Используй глобальные переменные «на всю катушку» /сколько упоростости хватит/.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.