>  기사  >  백엔드 개발  >  지역 변수와 전역 변수를 시작으로 Python의 변수 범위를 종합적으로 분석합니다.

지역 변수와 전역 변수를 시작으로 Python의 변수 범위를 종합적으로 분석합니다.

不言
不言원래의
2018-04-27 15:31:151579검색

클래스 기반 객체지향 프로그래밍이든, 간단한 함수 내에서 변수를 정의하든, 변수의 범위는 Python 학습에서 항상 이해하고 숙달해야 하는 연결 고리입니다. Python에서 변수에 대한 포괄적인 분석부터 시작하겠습니다. 지역변수와 전역변수에 대해서는

전역변수와 지역변수 이해하기
1를 참고하세요. 지역 변수로 정의된 것으로 간주됩니다. 이 경우, 전역 변수에서 변수 이름을 사용하는지 여부와 관계없이 함수에서는 로컬 변수를 사용합니다. 예:

  num = 100
  def func():
    num = 123
    print num
  func()

출력 결과는 123입니다. 함수에 정의된 변수명 num은 지역변수이고 전역변수를 포괄한다는 점을 설명한다. 또 다른 예:

  num = 100
  def func():
    num += 100
    print num
  func()

출력 결과는 다음과 같습니다. UnboundLocalError: 할당 전에 지역 변수 'num'이 참조되었습니다. 오류 메시지: 할당 전에 지역 변수 num이 적용되었습니다. 즉, 변수를 정의하지 않고 잘못 사용하고 있는 것입니다. 이는 여기에 정의된 내용이 전역 변수가 아닌 지역 변수임을 다시 한 번 증명합니다.

2. 함수 내부에 변수명이 처음 나타나고, = 기호 뒤에 나타나며, 이전에 전역 변수로 정의된 적이 있다면 여기서는 전역 변수를 참조하게 됩니다. 예:

  num = 100
  def func():
    x = num + 100
    print x
  func()

출력 결과는 200입니다. 변수 이름 num이 이전에 전역 변수로 정의되지 않은 경우 다음과 같은 오류 메시지가 나타납니다. 변수가 정의되지 않았습니다. 예:

  def func():
    x = num + 100
    print x
  func()

출력 결과는 다음과 같습니다. NameError: 전역 이름 'num'이 정의되지 않았습니다.

3. 함수에서 변수를 사용할 때 변수 이름에 전역 변수와 지역 변수가 모두 있으면 기본적으로 지역 변수가 사용됩니다. 예:

  num = 100
  def func():
    num = 200
    x = num + 100
    prinx x
  func()

출력 결과는 300입니다.

4. 함수에서 변수를 전역 변수로 정의할 때는 global 키워드를 사용해야 합니다. 예:

  num = 100
  def func():
    global num
    num = 200
    print num
  func()
  print num

출력 결과는 각각 200과 200입니다. 이는 함수의 변수 이름 num이 전역 변수로 정의되어 값 200이 할당되었음을 보여줍니다. 또 다른 예:

  num = 100
  def func():
    global num
    num = 200
    num += 100
    print num
  func()
  print num

출력 결과는 각각 300과 300입니다.

위의 전역 변수와 지역 변수의 적용 시나리오 결과를 결합하여 입력 필드의 교육 코드 전반부에 대한 분석을 시도했습니다(중국어 부분에 대한 설명):

  # calculator with all buttons

  import simplegui

  # intialize globals
  store = 0
  operand = 0

simplegui 사용 모듈을 사용하면 http://www.codeskulptor.org/가 올바르게 작동할 수 있습니다. 하지만 이 모듈은 Python 환경에서 직접 사용할 수 없으며 SimpleGUICS2Pygame 패키지를 먼저 설치해야 합니다.

  # event handlers for calculator with a store and operand

  def output():
  """prints contents of store and operand"""
    print "Store = ", store
    print "Operand = ", operand
    print ""

전역변수 store와 피연산자는 정의된 함수output()에서 직접 사용됩니다. 2번 항목을 참고하시면 됩니다.

  def swap():
  """ swap contents of store and operand"""
    global store, operand
    store, operand = operand, store
    output()

정의된 함수 swap()에서는 먼저 store와 Operand의 전역 변수를 정의합니다. 그렇지 않으면 값을 할당하지 않고 사용한다는 오류 메시지가 나타납니다. 1번 항목을 참고하시면 됩니다. 동시에 다음과 같이 이해해도 될까요: swap() 함수에서 global 키워드가 없을 때 store와 피연산자는 기본 지역 변수이고 = 오른쪽 부분을 사용하는 것은 잘못된 것입니다. 할당 없이. 3번 항목을 참고하시면 됩니다.

  def add():
  """ add operand to store"""

    global store
    store = store + operand
    output()

여기서 2주 과정 학습 이후 첫 번째 문제에 직면했습니다. 이것이 바로 add() 함수가 store를 전역 변수로만 정의하고 피연산자를 같은 방식으로 정의하지 않는 이유입니다. 이제 1번과 합쳐지면 로컬 변수인 store는 미리 값을 할당하지 않아 직접 사용할 수 없는 반면, 피연산자는 앞서 정의한 글로벌 변수를 직접 호출하여 사용할 수 있기 때문이다.

가변 범위
가변 범위(scope)는 파이썬에서 함정에 빠지기 쉬운 곳입니다.
Python에는 총 4개의 범위가 있습니다.

L(로컬) 로컬 범위
E(인클로징) 클로저 함수 외부 함수
G(글로벌) 글로벌 범위
B(내장) 구성 범위
L --> 의 규칙에 따라 검색됩니다. 도착하면 전역 검색으로 이동한 다음 내장 검색으로 이동합니다.

Python의 def/class/lambda를 제외하고 if/elif/else/ try/except for/while과 같은 다른 것들은 범위를 변경할 수 없습니다. 그 안에 정의된 변수는 외부에서 계속 접근할 수 있습니다.

>>> if True:
...   a = 'I am A'
... 
>>> a
'I am A'

if 언어에 정의된 변수 a는 외부에서 여전히 접근 가능합니다.
하지만 def/class/lambda로 래핑되어 내부적으로 할당되면 이 함수/클래스/lambda의 로컬 범위가 된다는 점에 유의해야 합니다.
def/class/lambda 내의 할당은 로컬 범위가 됩니다. 로컬 범위는 전역 범위를 포함하지만 전역 범위에는 영향을 미치지 않습니다.

g = 1 #全局的
def fun():
  g = 2 #局部的
  return g

print fun()
# 结果为2
print g
# 结果为1

그러나 때로는 함수 내에서 전역 변수를 참조하려는 경우 주의하지 않으면 오류가 발생할 수 있습니다. 예:

#file1.py
var = 1
def fun():
  print var
  var = 200
print fun()

#file2.py
var = 1
def fun():
  var = var + 1
  return var
print fun()

두 함수 모두 UnboundLocalError: local Variable 'var' referenced before 할당이라는 오류를 보고합니다.
과제 전 인용 오류! 왜? 함수 내부에서는 var가 재할당된 것을 인터프리터가 감지하므로 var는 지역 변수가 되지만, var가 할당되기 전에 사용하려고 하면 이런 오류가 발생합니다. 해결책은 함수 내부에 전역 변수를 추가하는 것입니다. 그러나 전역 변수도 함수를 실행한 후에 수정됩니다.

闭包Closure
闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

函数嵌套/闭包中的作用域:

a = 1
def external():
  global a
  a = 200
  print a

  b = 100
  def internal():
    # nonlocal b
    print b
    b = 200
    return b

  internal()
  print b

print external()

一样会报错- 引用在赋值之前,Python3有个关键字nonlocal可以解决这个问题,但在Python2中还是不要尝试修改闭包中的变量。 关于闭包中还有一个坑:

from functools import wraps

def wrapper(log):
  def external(F):
    @wraps(F)
    def internal(**kw):
      if False:
        log = 'modified'
      print log
    return internal
  return external

@wrapper('first')
def abc():
  pass

print abc()

也会出现 引用在赋值之前 的错误,原因是解释器探测到了 if False 中的重新赋值,所以不会去闭包的外部函数(Enclosing)中找变量,但 if Flase 不成立没有执行,所以便会出现此错误。除非你还需要else: log='var' 或者 if True 但这样添加逻辑语句就没了意义,所以尽量不要修改闭包中的变量。

好像用常规的方法无法让闭包实现计数器的功能,因为在内部进行 count +=1 便会出现 引用在赋值之前 的错误,解决办法:(或Py3环境下的 nonlocal 关键字)

def counter(start):
    count =[start]
    def internal():
      count[0] += 1
      return count[0]
    return internal

count = counter(0)
for n in range(10):
  print count()
# 1,2,3,4,5,6,7,8,9,10

count = counter(0)
print count()
# 1

由于 list 具有可变性,而字符串是不可变类型。

locals() 和 globals()
globals()
global 和 globals() 是不同的,global 是关键字用来声明一个局部变量为全局变量。globals() 和 locals() 提供了基于字典的访问全局和局部变量的方式

比如:如果函数1内需要定义一个局部变量,名字另一个函数2相同,但又要在函数1内引用这个函数2。

def var():
  pass

def f2():
  var = 'Just a String'
  f1 = globals()['var']
  print var
  return type(f1)

print f2()
# Just a String
# <type &#39;function&#39;>

locals()
如果你使用过Python的Web框架,那么你一定经历过需要把一个视图函数内很多的局部变量传递给模板引擎,然后作用在HTML上。虽然你可以有一些更聪明的做法,还你是仍想一次传递很多变量。先不用了解这些语法是怎么来的,用做什么,只需要大致了解locals()是什么。
可以看到,locals()把局部变量都给打包一起扔去了。

@app.route(&#39;/&#39;)
def view():
  user = User.query.all()
  article = Article.query.all()
  ip = request.environ.get(&#39;HTTP_X_REAL_IP&#39;,     request.remote_addr)
  s = &#39;Just a String&#39;
  return render_template(&#39;index.html&#39;, user=user,
      article = article, ip=ip, s=s)
  #或者 return render_template(&#39;index.html&#39;, **locals())

위 내용은 지역 변수와 전역 변수를 시작으로 Python의 변수 범위를 종합적으로 분석합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.