Maison  >  Article  >  développement back-end  >  Analyse complète de la portée des variables en Python à partir des variables locales et des variables globales

Analyse complète de la portée des variables en Python à partir des variables locales et des variables globales

不言
不言original
2018-04-27 15:31:151597parcourir

Qu'il s'agisse de programmation orientée objet basée sur les classes ou de définition de variables au sein d'une simple fonction, la portée des variables est toujours un lien qui doit être compris et maîtrisé dans l'apprentissage de Python. Commençons par une analyse complète du démarrage de Python. avec des variables locales et des variables globales. Pour la portée des variables, les amis qui en ont besoin peuvent se référer à

Comprendre les variables globales et les variables locales
1 Si le nom de la variable est défini. La fonction apparaît pour la première fois, et avant le symbole =, elle peut être considérée comme définie comme une variable locale. Dans ce cas, que le nom de la variable soit utilisé ou non dans la variable globale, la variable locale est utilisée dans la fonction. Par exemple :

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

Le résultat de sortie est 123. Expliquez que le nom de variable num défini dans la fonction est une variable locale et couvre la variable globale. Autre exemple :

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

Le résultat de sortie est : UnboundLocalError : variable locale 'num' référencée avant l'affectation. Message d'erreur : la variable locale num est appliquée avant l'affectation. En d’autres termes, la variable est mal utilisée sans être définie. Cela prouve une fois de plus que ce qui est défini ici est une variable locale et non une variable globale.

2. Si le nom de la variable à l'intérieur de la fonction apparaît pour la première fois, apparaît après le symbole = et a déjà été défini comme variable globale, la variable globale sera référencée ici. Par exemple :

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

Le résultat de sortie est 200. Si le nom de la variable num n'a pas été défini auparavant comme variable globale, un message d'erreur apparaîtra : La variable n'est pas définie. Par exemple :

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

Le résultat de sortie est : NameError : le nom global 'num' n'est pas défini.

3. Lorsqu'une variable est utilisée dans une fonction, si le nom de la variable a à la fois des variables globales et des variables locales, la variable locale sera utilisée par défaut. Par exemple :

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

Le résultat de sortie est 300.

4. Lorsque vous définissez une variable comme variable globale dans une fonction, vous devez utiliser le mot-clé global. Par exemple :

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

Les résultats de sortie sont respectivement 200 et 200. Cela montre que le nom de la variable num dans la fonction est défini comme une variable globale et se voit attribuer une valeur de 200. Autre exemple :

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

Les résultats de sortie sont respectivement 300 et 300.

Sur la base des résultats ci-dessus des scénarios d'application de variables globales et de variables locales, j'ai essayé de faire une analyse sur la première moitié du code d'enseignement dans les champs de saisie (commentaires sur la partie chinoise) :

  # calculator with all buttons

  import simplegui

  # intialize globals
  store = 0
  operand = 0

Grâce au module simplegui, il peut être exploité sans erreur sur http://www.codeskulptor.org/. Cependant, ce module ne peut pas être utilisé directement dans l'environnement python et le package SimpleGUICS2Pygame doit être installé au préalable.

  # event handlers for calculator with a store and operand

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

Le magasin et l'opérande des variables globales sont directement utilisés dans la fonction définie output(). Vous pouvez vous référer au point 2.

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

Dans la fonction swap() définie, les variables globales de magasin et d'opérande sont d'abord définies. Si vous ne le faites pas, un message d'erreur apparaîtra indiquant qu'il est utilisé sans attribuer de valeur. Vous pouvez vous référer au point 1. En même temps, peut-on comprendre cela de cette façon : dans la fonction swap(), lorsqu'il n'y a pas de mot-clé global, store et operand sont des variables locales par défaut, et il est faux d'utiliser la partie à droite de = sans affectation. Vous pouvez vous référer au point 3.

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

    global store
    store = store + operand
    output()

Ici, j'ai rencontré le premier problème depuis les deux semaines d'études : c'est pourquoi la fonction add() définit uniquement store comme une variable globale et ne définit pas l'opérande de la même manière. Maintenant combiné avec le point 1, c'est parce que stocker en tant que variable locale n'a pas reçu de valeur à l'avance et ne peut pas être utilisé directement, alors que l'opérande peut être utilisé en appelant directement la variable globale précédemment définie.

Portée variable
La portée variable est un endroit facile pour tomber dans un piège en Python.
Python a un total de 4 portées, qui sont :

Portée locale L (Local)
E (Enclosing) dans une fonction en dehors de la fonction de fermeture
G Portée globale (Globale)
B (Intégré) La portée intégrée
est recherchée selon les règles de L ---> E ---> il sera recherché. Si vous recherchez des pièces locales en dehors de la zone locale (telles que des fermetures), si vous ne les retrouvez pas, vous accéderez à la recherche globale, puis à celles intégrées.

Sauf def/class/lambda en Python, d'autres tels que : if/elif/else/ try/sauf for/while ne peuvent pas changer sa portée. Les variables définies en leur sein sont toujours accessibles de l'extérieur.

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

La variable a définie dans le langage if est toujours accessible de l'extérieur.
Mais veuillez noter que si if est enveloppé par def/class/lambda et attribué en interne, il devient la portée locale de cette fonction/classe/lambda.
L'affectation dans def/class/lambda devient sa portée locale. La portée locale couvrira la portée globale mais n'affectera pas la portée globale.

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

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

Mais sachez que parfois vous souhaitez faire référence à des variables globales à l'intérieur d'une fonction, et des erreurs se produiront si vous ne parvenez pas à le faire. Par exemple :

#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()

Les deux fonctions. signalera une UnboundLocalError : variable locale 'var' référencée avant l'affectation
Erreur lorsqu'elle est référencée avant l'affectation ! Pourquoi? Parce qu'à l'intérieur de la fonction, l'interpréteur détecte que var a été réaffecté, donc var devient une variable locale, mais si vous souhaitez utiliser var avant qu'elle ne soit affectée, cette erreur se produira. La solution consiste à ajouter une variable globale à l'intérieur de la fonction, mais la variable globale sera également modifiée après l'exécution de la fonction.

闭包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())

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn