Чаму не Пайтона нелокального ключавым словы як глабальны маштаб?

У Python 3.3.1, гэта працуе:

i = 76

def A():
    global i
    i += 10

print(i) # 76
A()
print(i) # 86

Гэта таксама працуе:

def enclosing_function():
    i = 76
    def A():
        nonlocal i
        i += 10

    print(i) # 76
    A()
    print(i) # 86

enclosing_function()

Але гэта не працуе:

i = 76
def A():
    nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
    i += 10

print(i)
A()
print(i)

Дакументацыя нелокальной ключавое слова дзяржаў (курсіў дададзена):

<�Р> Нелокальный аператар выклікае пералічаныя ідэнтыфікатары для абазначэння   раней звязаныя зменныя ў <�моцнай> бліжэйшай вобласці бачнасці </моцнай>. </Р>

У трэцім прыкладзе, «бліжэйшым зашытая вобласць дзеяння» як раз здараецца быць глабальны маштаб. Дык чаму ж яна не працуе?

Прачытайце ГЭТА BIT

Я заўважаю, што дакументацыя пераходзіць да дзяржавы (курсіў мой):

<�Р> [ нелокальной ] інструкцыя дазваляе інкапсуляваць код у   перепривязывают зменныя па-за лакальнай вобласці акрамя глабальнага   (Модуль) сфера </моцны>. </Р>

але, строга кажучы, гэта не значыць, што тое, што я раблю ў трэцім прыкладзе не павінна працаваць.

9
Вашы развагі цалкам зразумела. На жаль, часам (гэтак жа, як і ў многіх мовах), некаторыя рэчы проста так, як яны ёсць, альбо з-за зваротнай сумяшчальнасці праблем або цяжкасцяў ажыццяўлення або супольнасці галасавання або любы іншы. У гэтым выпадку, я думаю, што ў дакументацыі варта паказаць больш моцна, што нелокальной спецыяльна выключае у глабальным маштабе. Тады вы можаце не пагадзіцца, ці што добры выбар, але, па меншай меры, было б адназначным.
дададзена аўтар John Y, крыніца
Вашы развагі цалкам зразумела. На жаль, часам (гэтак жа, як і ў многіх мовах), некаторыя рэчы проста так, як яны ёсць, альбо з-за зваротнай сумяшчальнасці праблем або цяжкасцяў ажыццяўлення або супольнасці галасавання або любы іншы. У гэтым выпадку, я думаю, што ў дакументацыі варта паказаць больш моцна, што нелокальной спецыяльна выключае у глабальным маштабе. Тады вы можаце не пагадзіцца, ці што добры выбар, але, па меншай меры, было б адназначным.
дададзена аўтар John Y, крыніца

8 адказы

Парадак пошуку імёнаў з'яўляецца LEGB, то ёсць мясцовы, які агароджвае, Global, Builtin. Такім чынам, глабальны ахоп не з'яўляецца сфера зашытая.

<�Моцны> Змяніць

З дакументы :

<�Р> Нелокальный аператар выклікае пералічаныя ідэнтыфікатары для абазначэння   раней звязаныя зменныя ў бліжэйшай ўмяшчае вобласці. Гэта   важна, таму што паводзіны па змаўчанні для звязвання з'яўляецца абшукваць   лакальнае прастору імёнаў першага. Заява дазваляе схаваны код у   перепривязывают зменныя па-за лакальнай вобласці, акрамя глабальнай   (Модуль) сфера. </Р>
5
дададзена
+1. Таксама гэта можа быць цікава адзначыць, што нелокальной быў дададзены, каб зрабіць укладзеныя функцыі мовы Python працаваць як кананічныя ( «функцыянальныя») замыкання. Гэта свайго роду патч, а не так элегантна, як зачыняюць аглядны JavaScript ў або схеме. Тое, што я хацеў бы ведаць, <�б> чаму вобласць бачнасці модуля лічацца глабальнымі і не складаючы адзін? Гэта яшчэ не <�я> глабальны да іншых модуляў (ну, калі вы не робіце <�код > ад імпарту модуля * ), ці не так?
дададзена аўтар Nadir Sampaoli, крыніца
На маім позірку глабальны не павінен выкарыстоўвацца на ўсіх, за выключэннем некаторых выключных выпадкаў, як ўкладанне ў C, дзе я выкарыстаў яго адзін раз, за ​​выключэннем. Існуе заўсёды ёсць рашэнні без глабальны , калі толькі паспрабаваць дастаткова цяжка, і ваш код будзе лепш. Так што робіць нелокального дабіраючыся да глабальнага маштабу было б памылкай, на мой погляд.
дададзена аўтар Mike Müller, крыніца
Надзір: так, гэта ў асноўным тое, што я прасіў, а таксама.
дададзена аўтар qntm, крыніца
Чаму не? Яна ахоплівае ўсе.
дададзена аўтар qntm, крыніца

Парадак пошуку імёнаў з'яўляецца LEGB, то ёсць мясцовы, які агароджвае, Global, Builtin. Такім чынам, глабальны ахоп не з'яўляецца сфера зашытая.

<�Моцны> Змяніць

З дакументы :

<�Р> Нелокальный аператар выклікае пералічаныя ідэнтыфікатары для абазначэння   раней звязаныя зменныя ў бліжэйшай ўмяшчае вобласці. Гэта   важна, таму што паводзіны па змаўчанні для звязвання з'яўляецца абшукваць   лакальнае прастору імёнаў першага. Заява дазваляе схаваны код у   перепривязывают зменныя па-за лакальнай вобласці, акрамя глабальнай   (Модуль) сфера. </Р>
5
дададзена
+1. Таксама гэта можа быць цікава адзначыць, што нелокальной быў дададзены, каб зрабіць укладзеныя функцыі мовы Python працаваць як кананічныя ( «функцыянальныя») замыкання. Гэта свайго роду патч, а не так элегантна, як зачыняюць аглядны JavaScript ў або схеме. Тое, што я хацеў бы ведаць, <�б> чаму вобласць бачнасці модуля лічацца глабальнымі і не складаючы адзін? Гэта яшчэ не <�я> глабальны да іншых модуляў (ну, калі вы не робіце <�код > ад імпарту модуля * ), ці не так?
дададзена аўтар Nadir Sampaoli, крыніца
На маім позірку глабальны не павінен выкарыстоўвацца на ўсіх, за выключэннем некаторых выключных выпадкаў, як ўкладанне ў C, дзе я выкарыстаў яго адзін раз, за ​​выключэннем. Існуе заўсёды ёсць рашэнні без глабальны , калі толькі паспрабаваць дастаткова цяжка, і ваш код будзе лепш. Так што робіць нелокального дабіраючыся да глабальнага маштабу было б памылкай, на мой погляд.
дададзена аўтар Mike Müller, крыніца
Надзір: так, гэта ў асноўным тое, што я прасіў, а таксама.
дададзена аўтар qntm, крыніца
Чаму не? Яна ахоплівае ўсе.
дададзена аўтар qntm, крыніца

Адказ у тым, што глабальны ахоп нічога не ўкласці - гэта глабальная да ўсяго. Выкарыстоўвайце глабальны ключавое слова ў такім выпадку.

2
дададзена

Адказ у тым, што глабальны ахоп нічога не ўкласці - гэта глабальная да ўсяго. Выкарыстоўвайце глабальны ключавое слова ў такім выпадку.

2
дададзена
<�Р> чаму вобласць бачнасці модуля лічацца глабальнымі і не складаючы адзін? Гэта ўсё яшчэ не глабальнымі ў адносінах да іншых модуляў (ну, калі вы не зробіце ад імпарту модуля * ), гэта?

Калі змясціць некаторы імя ў Модуль 's прастору імёнаў; гэта відаць у любым элеменце, які выкарыстоўвае модуль гэта значыць, яна носіць глабальны характар ​​для ўсяго працэсу Python.

Увогуле, ваша прыкладанне павінна выкарыстоўваць як некалькі змяняных Глобал наколькі гэта магчыма. См Чаму Глобал дрэнна :

  • Нелокальность
  • Няма кантроль доступу або абмежаванні Праверкі
  • <�Літый> няяўных муфта
  • Пытанні Паралелізм
  • Забруджванне прастор імёнаў
  • Тэсціраванне і Confinement

Таму было б нядрэнна, калі нелокальной дазволіў стварыць Глобал выпадкова. Калі вы хочаце змяніць глабальную зменную; Вы можаце выкарыстоўваць Глабальны Ключавое слова непасрэдна.

  • global is the most destructive: may affect all uses of the module anywhere in the program
  • nonlocal is less destructive: limited by the outer() function scope (the binding is checked at compile time)
  • no declaration (local variable) is the least destructive option: limited by inner() function scope

Вы можаце прачытаць пра гісторыю і матывацыі нелокального у PEP: 3104 Доступ да назваў у Outer Галіне .

1
дададзена
@NadiRSampaoli: Я не бачу, як ваш каментар звязаны з маім адказам, які кажа: Глобал дрэнна таму было б нядрэнна, калі нелокальные могуць стварыць глабальную выпадкова.
дададзена аўтар jfs, крыніца
Гэта крыху звязаныя. Паводзіны Іма нелокальное аддзеленае ад глабальнага, таму што гэта было б залішнім, не з-за «зласлівасцю Глобал». Вы кажаце, што «Глобал дрэнна таму было б нядрэнна, калі нелокальным можа стварыць глабальны па аварыі». Па-першае: як гэта <�я> выпадкова </я>? Па-другое: «няшчасны выпадак» не прымаецца да ўвагі ў Python (Guido бы сказаць: «мы ўсе паўналетнімі тут»). Трэці: больш разумнае зацвярджэнне было б «Глобал дрэнна таму было б лепш, калі б не былі Глобал». Але гэта будзе яшчэ ісці супраць Гвіда «мы ўсе дарослыя», не дазваляючы нам зрабіць наш выбар.
дададзена аўтар Nadir Sampaoli, крыніца
З аднаго боку, гэта мае сэнс абмежаваць паводзіны сферы нелокального не перасякаюцца глабальны 's ( «Там павінна быць одно-- і пераважна толькі адзін спосаб --obvious зрабіць гэта »). З іншага боку, гэты від адчувае сябе непаслядоўна: «Асаблівыя выпадкі не настолькі асаблівыя, каб парушаць правілы». <�Код> глабальны здаецца, асаблівы выпадак нелокальной , да мяне. Хоць вы маглі б сцвярджаць, што гэта не так, таму што вы можаце імпартаваць імёны са сферы модуля, але не з «умяшчаючага», функцыі ўзроўню ахопу. Python выдатна, але, як яна апрацоўвае вобласць бачнасці складана, у лепшым выпадку.
дададзена аўтар Nadir Sampaoli, крыніца
<�Р> чаму вобласць бачнасці модуля лічацца глабальнымі і не складаючы адзін? Гэта ўсё яшчэ не глабальнымі ў адносінах да іншых модуляў (ну, калі вы не зробіце ад імпарту модуля * ), гэта?

Калі змясціць некаторы імя ў Модуль 's прастору імёнаў; гэта відаць у любым элеменце, які выкарыстоўвае модуль гэта значыць, яна носіць глабальны характар ​​для ўсяго працэсу Python.

Увогуле, ваша прыкладанне павінна выкарыстоўваць як некалькі змяняных Глобал наколькі гэта магчыма. См Чаму Глобал дрэнна :

  • Нелокальность
  • Няма кантроль доступу або абмежаванні Праверкі
  • <�Літый> няяўных муфта
  • Пытанні Паралелізм
  • Забруджванне прастор імёнаў
  • Тэсціраванне і Confinement

Таму было б нядрэнна, калі нелокальной дазволіў стварыць Глобал выпадкова. Калі вы хочаце змяніць глабальную зменную; Вы можаце выкарыстоўваць Глабальны Ключавое слова непасрэдна.

  • global is the most destructive: may affect all uses of the module anywhere in the program
  • nonlocal is less destructive: limited by the outer() function scope (the binding is checked at compile time)
  • no declaration (local variable) is the least destructive option: limited by inner() function scope

Вы можаце прачытаць пра гісторыю і матывацыі нелокального у PEP: 3104 Доступ да назваў у Outer Галіне .

1
дададзена
@NadiRSampaoli: Я не бачу, як ваш каментар звязаны з маім адказам, які кажа: Глобал дрэнна таму было б нядрэнна, калі нелокальные могуць стварыць глабальную выпадкова.
дададзена аўтар jfs, крыніца
Гэта крыху звязаныя. Паводзіны Іма нелокальное аддзеленае ад глабальнага, таму што гэта было б залішнім, не з-за «зласлівасцю Глобал». Вы кажаце, што «Глобал дрэнна таму было б нядрэнна, калі нелокальным можа стварыць глабальны па аварыі». Па-першае: як гэта <�я> выпадкова </я>? Па-другое: «няшчасны выпадак» не прымаецца да ўвагі ў Python (Guido бы сказаць: «мы ўсе паўналетнімі тут»). Трэці: больш разумнае зацвярджэнне было б «Глобал дрэнна таму было б лепш, калі б не былі Глобал». Але гэта будзе яшчэ ісці супраць Гвіда «мы ўсе дарослыя», не дазваляючы нам зрабіць наш выбар.
дададзена аўтар Nadir Sampaoli, крыніца
З аднаго боку, гэта мае сэнс абмежаваць паводзіны сферы нелокального не перасякаюцца глабальны 's ( «Там павінна быць одно-- і пераважна толькі адзін спосаб --obvious зрабіць гэта »). З іншага боку, гэты від адчувае сябе непаслядоўна: «Асаблівыя выпадкі не настолькі асаблівыя, каб парушаць правілы». <�Код> глабальны здаецца, асаблівы выпадак нелокальной , да мяне. Хоць вы маглі б сцвярджаць, што гэта не так, таму што вы можаце імпартаваць імёны са сферы модуля, але не з «умяшчаючага», функцыі ўзроўню ахопу. Python выдатна, але, як яна апрацоўвае вобласць бачнасці складана, у лепшым выпадку.
дададзена аўтар Nadir Sampaoli, крыніца

Гэта залежыць ад межавых выпадкаў:

nonlocals прыходзяць з некаторымі senstivity абласцей, якія мы павінны быць у курсе. Па-першае, у адрозненне ад глабальнага заявы, <�моцны> нелокальной імёны сапраўды павінны быць папярэдні былі прызначаныя ў рамках якая ахоплівае DEF, калі Ісакавіча ацэньваецца, інакш вы атрымаеце памылку, вы не можаце ствараць іх дынамічна прызначаючы іх зноўку ў галіне бачнасці. На самай справе, яны правяраюцца падчас вызначэння функцыі, перш чым небудзь або укладзеная функцыя называецца

>>>def tester(start):
      def nested(label):
         nonlocal state   #nonlocals must already exist in enclosing def!
         state = 0
         print(label, state)
      return nested
SyntaxError: no binding for nonlocal 'state' found

>>>def tester(start):
      def nested(label):
          global state   #Globals dont have to exits yet when declared
          state = 0      #This creates the name in the module now
          print(label, state)
      return nested

>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0

Па-другое, <�моцны> нелокальна </моцны> абмяжоўвае вобласць пошуку толькі агароджваюць DEFS; nonlocals ня шукаецца ў глабальнай вобласці бачнасці модуля змяшчаюць або убудаванага дзеянні за межамі ўсіх ДЕФа, нават калі яны ўжо ёсць:

напрыклад:-

>>>spam = 99
>>>def tester():
      def nested():
         nonlocal spam  #Must be in a def, not the module!
         print('current=', spam)
         spam += 1
      return nested
SyntaxError: no binding for nonlocal 'spam' found

Гэтыя абмежаванні маюць сэнс, калі вы разумееце, што пітон няйначай, як правіла ведаюць, якія агароджваюць вобласць, каб стварыць зусім новае імя ў. У папярэднім узроўні лістынга, павінны <�моцны> спам быць прызначаныя ў <�моцны> тэстар або вонкавы модуль? Паколькі гэта неадназначнае, Python павінен вырашыць nonlocals на функцыі Стварэнне час, а не функцыя часу выкліку.

0
дададзена

Гэта залежыць ад межавых выпадкаў:

nonlocals прыходзяць з некаторымі senstivity абласцей, якія мы павінны быць у курсе. Па-першае, у адрозненне ад глабальнага заявы, <�моцны> нелокальной імёны сапраўды павінны быць папярэдні былі прызначаныя ў рамках якая ахоплівае DEF, калі Ісакавіча ацэньваецца, інакш вы атрымаеце памылку, вы не можаце ствараць іх дынамічна прызначаючы іх зноўку ў галіне бачнасці. На самай справе, яны правяраюцца падчас вызначэння функцыі, перш чым небудзь або укладзеная функцыя называецца

>>>def tester(start):
      def nested(label):
         nonlocal state   #nonlocals must already exist in enclosing def!
         state = 0
         print(label, state)
      return nested
SyntaxError: no binding for nonlocal 'state' found

>>>def tester(start):
      def nested(label):
          global state   #Globals dont have to exits yet when declared
          state = 0      #This creates the name in the module now
          print(label, state)
      return nested

>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0

Па-другое, <�моцны> нелокальна </моцны> абмяжоўвае вобласць пошуку толькі агароджваюць DEFS; nonlocals ня шукаецца ў глабальнай вобласці бачнасці модуля змяшчаюць або убудаванага дзеянні за межамі ўсіх ДЕФа, нават калі яны ўжо ёсць:

напрыклад:-

>>>spam = 99
>>>def tester():
      def nested():
         nonlocal spam  #Must be in a def, not the module!
         print('current=', spam)
         spam += 1
      return nested
SyntaxError: no binding for nonlocal 'spam' found

Гэтыя абмежаванні маюць сэнс, калі вы разумееце, што пітон няйначай, як правіла ведаюць, якія агароджваюць вобласць, каб стварыць зусім новае імя ў. У папярэднім узроўні лістынга, павінны <�моцны> спам быць прызначаныя ў <�моцны> тэстар або вонкавы модуль? Паколькі гэта неадназначнае, Python павінен вырашыць nonlocals на функцыі Стварэнне час, а не функцыя часу выкліку.

0
дададзена