전역 변수가 왜 나쁜가요? [닫은]


121

나는 global파이썬에서 (그리고 일반적으로 프로그래밍에서) 의 사용 이 나쁜 습관으로 간주되는 이유를 찾으려고합니다 . 누군가 설명 할 수 있습니까? 더 많은 정보가있는 링크도 감사하겠습니다.


재 개설 투표-질문을 편집하여 설명에 초점을 맞추고 오프 사이트 리소스에서 멀어졌습니다. (나는 그것이 폐쇄 된 이유의 가정,하지만 단지의 경우 나쁜 관행에 대한 질문이되고 함께 할 수있는 그것의 무언가가 여전히 열려있는 나쁜 관행에 대한 이러한 다른 질문 비교 : eval, import *, 문자열 연결 , 변수id , 속성 그림자 )
wjandrea

답변:


156

이것은 파이썬과 관련이 없습니다. 전역 변수는 모든 프로그래밍 언어에서 좋지 않습니다.

그러나 전역 상수 는 개념적으로 전역 변수 와 동일하지 않습니다 . 전역 상수는 완벽하게 무해합니다. 파이썬에서 둘 사이의 구별은 순전히 관례에 따라 : CONSTANTS_ARE_CAPITALIZEDand globals_are_not.

전역 변수가 나쁜 이유는 함수가 부작용을 숨겨서 (명백하지 않고, 놀랍고, 감지하기 어렵고, 진단하기 어렵게하여) 복잡성을 증가시켜 잠재적으로 Spaghetti 코드로 이어질 수 있기 때문 입니다.

그러나 알고리즘 최적화, 복잡성 감소, 캐싱 및 메모 화 또는 주로 명령형 코드베이스에서 시작된 포팅 구조의 실용성을 위해 함수 프로그래밍에서도 전역 상태의 정상적인 사용이 허용됩니다 (로컬 상태 및 가변성).

대체로 귀하의 질문에 여러 가지 방법으로 답변 할 수 있으므로 가장 좋은 방법은 Google "전역 변수가 왜 나쁜지"라는 것입니다. 몇 가지 예 :

더 깊이 들어가서 부작용이 왜 전부인지, 그리고 다른 많은 계몽적인 것들을 알고 싶다면 함수형 프로그래밍을 배워야합니다.


35

예, 이론적 으로 글로벌 (및 일반적으로 "상태")은 악합니다. 실제로 파이썬의 패키지 디렉토리를 살펴보면 대부분의 모듈이 전역 선언으로 시작한다는 것을 알 수 있습니다. 분명히 사람들은 그들에게 아무런 문제가 없습니다.

특히 파이썬의 경우 전역의 가시성은 모듈로 제한됩니다. 따라서 전체 프로그램에 영향을 미치는 "진정한"전역이 없으므로 덜 해 롭습니다. 또 다른 요점은 없습니다 const. 따라서 상수가 필요할 때 전역을 사용해야합니다.

내 실습에서 함수에서 전역을 수정하면 global기술적으로 필요하지 않더라도 항상 다음과 같이 선언합니다 .

cache = {}

def foo(args):
    global cache

    cache[args] = ...

이것은 전역의 조작을 추적하기 쉽게 만듭니다.


3
여러면에서 파이썬의 모듈은 싱글 톤 클래스와 유사하고 모듈 전역은 클래스 속성과 유사합니다.
Corley

9
@CorleyBrigman : 싱글 톤 클래스는 실제로 일반적으로 글로벌에 기인하는 동일한 문제로 고통받습니다. :)
Erik Kaplun

4
파이썬 모듈의 가시성은 모듈에 국한되지 않습니다. 전체 통역사에서 사용할 수 있으며 (여기에서 중요한 사항) 변경 사항이 전체 통역사에 영향을 미칩니다. 인스턴스를 만드는 것은 문자열이 아닙니다. 모든 문자열 인스턴스를 수정하는 것과 같습니다. 원숭이 패치 냄새.
graffic

2
대부분의 모듈은 상수를 제외하고 전역을 정의하는 것으로 시작하지 않습니다 . 전역이 나쁘다는 것은 상수가 아닌 변수 / 전역 상태를 의미 합니다 .
BlackJack

2
전역을 사용하는 것은 끔찍한 생각입니다. 한 가지 이유는 "어딘가에"존재하는 임의의 사전을 업데이트하는 함수를 제대로 테스트 할 수 없기 때문일 수 있습니다. 전역이있는 코드베이스는 실제로 작동한다는 것을 증명할 수 없습니다.
Tomasz Sosiński 2017

10

이 주제에 대한 개인적인 의견은 함수 논리에서 전역 변수를 사용한다는 것은 다른 코드가 해당 함수의 논리와 예상 출력을 변경하여 디버깅을 매우 어렵게 만들고 (특히 대규모 프로젝트에서) 테스트를 더 어렵게 만들 수 있음을 의미한다는 것입니다. 게다가.

또한, 다른 사람들이 여러분의 코드를 읽는 것을 고려한다면 (오픈 소스 커뮤니티, 동료 등) 전역 변수가 설정되는 위치, 변경된 위치 및 반대되는이 전역 변수에서 무엇을 기대해야하는지 이해하는 데 어려움을 겪을 것입니다. 함수 정의 자체를 읽어 그 기능을 결정할 수있는 격리 된 함수로.

(아마) 순수 함수 정의 위반

깨끗하고 (거의) 버그가없는 코드는 가능한 한 순수한 함수를 가져야한다고 생각합니다 ( 순수 함수 참조 ). 순수 함수는 다음과 같은 조건을 가진 함수입니다.

  1. 함수는 항상 동일한 인수 값이 주어지면 동일한 결과 값을 평가합니다 . 함수 결과 값은 프로그램 실행이 진행되는 동안 또는 프로그램의 다른 실행간에 변경 될 수있는 숨겨진 정보 또는 상태에 의존 할 수 없으며 I / O 장치의 외부 입력 (일반적으로 아래 참조)에 의존 할 수도 없습니다.
  2. 결과 평가는 변경 가능한 객체의 변형 또는 I / O 장치로의 출력과 같이 의미 론적으로 관찰 가능한 부작용이나 출력을 유발하지 않습니다 .

전역 변수를 갖는 것은 외부 코드로 둘 다 아닌 경우 위 중 하나 이상을 위반하면 예상치 못한 결과가 발생할 수 있습니다.

순수 함수의 또 다른 명확한 정의 : "순수 함수는 모든 입력을 명시 적 인수로 취하고 모든 출력을 명시 적 결과로 생성 하는 함수입니다 ." [1] . 전역 변수를 갖는 것은 입력과 출력 중 하나 (전역 변수)가 명시 적으로 제공되거나 반환되지 않기 때문에 순수 함수의 개념을 위반합니다.

(아마) 단위 테스트 FIRST 원칙 위반

당신이 단위 테스트 및 첫 번째 원칙을 고려하는 경우 또한 그에, ( F의 AST 검사, I ndependent 테스트, R의 epeatable을, S 엘프 - 검증 및 T imely)는 독립적 인은 (원칙적으로 테스트 위반 아마되는 테스트 의존하지 않는 방법 서로).

전역 변수 (항상 그런 것은 아님)가 있지만 대부분의 경우 (적어도 지금까지 본 것 중)은 결과를 준비하고 다른 함수에 전달하는 것입니다. 이것은 또한이 원칙에 위배됩니다. 전역 변수가 그런 방식으로 사용 되었다면 (즉, 함수 X에서 사용되는 전역 변수가 먼저 함수 Y에서 설정되어야 함) 단위 테스트 함수 X에 대해 테스트 / 실행 함수 Y를 먼저 실행해야 함을 의미합니다.

상수로서의 전역

다른 한편으로 다른 사람들이 이미 언급했듯이 전역 변수가 "상수"변수로 사용되면 언어가 상수를 지원하지 않기 때문에 약간 더 나을 수 있습니다. 그러나 저는 항상 클래스로 작업하고 "상수"를 클래스 멤버로 사용하고 전역 변수를 전혀 사용하지 않는 것을 선호합니다. 두 개의 다른 클래스가 전역 변수를 공유해야하는 코드가있는 경우 솔루션을 리팩터링하고 클래스를 독립적으로 만들어야합니다.

나는 글로벌이 사용되어서는 안된다고 믿지 않습니다. 그러나 그들이 사용된다면 저자는 더 깨끗하고 거의 버그가없는 코드를 위해 몇 가지 원칙 (위에서 언급 한 것들과 다른 소프트웨어 엔지니어링 원칙과 모범 사례)을 고려해야합니다.


1
나는 "상수가 문제이기 때문에 전역을 좋아한다"... OO 디자인을하고 있다면 ... 정말 그렇기 때문이다. IdCreator 클래스 외에 다른 사람이 ID_LEN을 알아야하는 이유는 무엇입니까?
Erik Aronesty 2018 년

3

그것들은 필수적이며 화면이 좋은 예입니다. 그러나 다중 스레드 환경에서 또는 많은 개발자가 참여하는 경우 실제로 질문이 자주 발생합니다. 누가 (비정상적으로) 설정하거나 지웠습니까? 아키텍처에 따라 분석 비용이 많이 들고 자주 필요할 수 있습니다. 전역 var를 읽는 것은 괜찮을 수 있지만, 쓰기는 예를 들어 단일 스레드 또는 threadsafe 클래스에 의해 제어되어야합니다. 따라서 글로벌 변수는 자신이 악하다고 간주되는 결과로 인해 가능한 높은 개발 비용에 대한 두려움을 일으 킵니다. 따라서 일반적으로 전역 변수 수를 낮게 유지하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.