Penggunaan kata kunci "global" dalam Python

285

Apa yang saya pahami dari membaca dokumentasi adalah bahwa Python memiliki namespace terpisah untuk fungsi, dan jika saya ingin menggunakan variabel global dalam fungsi itu, saya perlu menggunakannya global.

Saya menggunakan Python 2.7 dan saya mencoba tes kecil ini

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Tampaknya semuanya berjalan dengan baik bahkan tanpa itu global. Saya dapat mengakses variabel global tanpa masalah.

Apakah saya kehilangan sesuatu? Juga, berikut ini dari dokumentasi Python:

Nama-nama yang tercantum dalam pernyataan global tidak boleh didefinisikan sebagai parameter formal atau dalam target kontrol loop, definisi kelas, definisi fungsi, atau pernyataan impor.

Sementara parameter formal dan definisi kelas masuk akal bagi saya, saya tidak dapat memahami batasan untuk target kontrol loop dan definisi fungsi.

nik
sumber
1
Saya pikir Anda bingung dengan php yang memerlukan penggunaan kata kunci global - python docs mengkonfirmasi ini - pada dasarnya jika tidak didefinisikan dalam konteks lokal itu diperlakukan sebagai global
tobyodavies
11
Hati-hati dengan kata-kata Anda: Python tidak memiliki namespace terpisah untuk fungsi (itu berarti Anda bisa memiliki def foo(): ...dan foo = ...pada saat yang sama). Itu membuat ruang lingkup baru untuk setiap panggilan fungsi. (Tapi apa bedanya dengan hampir semua bahasa tingkat tinggi lain di dunia?)

Jawaban:

366

Kata kunci globalhanya berguna untuk mengubah atau membuat variabel global dalam konteks lokal, meskipun membuat variabel global jarang dianggap sebagai solusi yang baik.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Di atas akan memberi Anda:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

Sementara jika Anda menggunakan globalpernyataan, variabel akan tersedia "di luar" ruang lingkup fungsi, secara efektif menjadi variabel global.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Jadi kode di atas akan memberi Anda:

locally defined
locally defined

Selain itu, karena sifat python, Anda juga bisa menggunakan globaluntuk mendeklarasikan fungsi, kelas atau objek lain dalam konteks lokal. Meskipun saya akan menyarankan itu karena hal itu menyebabkan mimpi buruk jika terjadi kesalahan atau perlu debugging.

unode
sumber
59
"global" dalam konteks ini tampaknya berbeda dari bahasa lain yang menganggap "global". Dalam Python referensi "global" masih dalam batas-batas modul dan perlu direferensikan dari luar modul sebagai "module.global_var" daripada sekadar "global_var" seperti yang mungkin diharapkan.
jus
17
@ Juice - Dalam Python tidak ada yang namanya absolut yang globalssecara otomatis didefinisikan di semua ruang nama (untungnya). Seperti yang Anda tunjukkan dengan benar, global terikat ke namespace di dalam modul, namun itu dapat diimpor ke modul lain sebagai from module import variableatau import module.variable. Dalam kasus pertama, impor akan membuat variabel dapat diakses variabletanpa memerlukan referensi sebagai module.. Jika dianggap global dalam cakupan modul akan tergantung pada tempat diimpornya. Lihat juga nonlocalsebagai kata kunci terkait lingkup baru di python 3.
hapus kode
3
Bisakah Anda menjelaskan mengapa variabel global bukan solusi yang baik? Saya sering mendengar ini, tetapi dalam proyek saya saat ini mereka tampaknya melakukan apa yang saya butuhkan. Apakah ada sesuatu yang lebih jahat yang belum saya pikirkan?
Robin Newhouse
5
@RobinNewhouse Ada beberapa pertanyaan di SO sudah mencakup bahwa topik dan SO non artikel .
hapus kode
213

Meskipun Anda dapat mengakses variabel global tanpa globalkata kunci, jika Anda ingin mengubahnya, Anda harus menggunakan globalkata kunci. Sebagai contoh:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

Dalam kasus Anda, Anda hanya mengakses daftar sub.

Ivo Wetzel
sumber
3
Dengan satu peringatan: foo = 3tanpa karya global, tetapi foo didefinisikan kembali secara lokal dalam blublingkup fungsi & tidak mengubah variabel foo asli. Ini cukup membingungkan bagi saya.
chhantyal
1
@ chhantyal jika dengan karya Anda maksudnya itu tidak menimbulkan kesalahan, Anda benar, tetapi dalam konteks Ivo Wetzel itu tidak akan berfungsi sebagaimana dimaksud. Ada kegunaan untuk perilaku seperti itu, tetapi sering kali bukan yang diinginkan programmer.
Demokratis
77

Ini adalah perbedaan antara mengakses nama dan mengikatnya dalam lingkup.

Jika Anda hanya mencari variabel untuk membaca nilainya, Anda memiliki akses ke lingkup global maupun lokal.

Namun jika Anda menetapkan ke variabel yang namanya tidak ada dalam lingkup lokal, Anda mengikat nama itu ke dalam lingkup ini (dan jika nama itu juga ada sebagai global, Anda akan menyembunyikannya).

Jika Anda ingin dapat menetapkan nama global, Anda perlu memberi tahu parser untuk menggunakan nama global daripada mengikat nama lokal baru - yang merupakan apa yang dilakukan kata kunci 'global'.

Mengikat di mana saja di dalam blok menyebabkan nama di mana saja di blok itu menjadi terikat, yang dapat menyebabkan beberapa konsekuensi yang agak aneh (mis. UnboundLocalError tiba-tiba muncul di kode yang sebelumnya berfungsi).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 
pycruft
sumber
sangat berlawanan dengan intuisi, sulit dipercaya bahwa ini adalah kode python yang valid
PlsWork
52

Jawaban lainnya menjawab pertanyaan Anda. Hal penting lain yang perlu diketahui tentang nama-nama dalam Python adalah bahwa mereka adalah lokal atau global berdasarkan basis per cakupan.

Pertimbangkan ini, misalnya:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Anda mungkin bisa menebak bahwa value = 0pernyataan akan menugaskan ke variabel lokal dan tidak mempengaruhi nilai variabel yang sama yang dinyatakan di luar doit()fungsi. Anda mungkin lebih terkejut menemukan bahwa kode di atas tidak akan berjalan. Pernyataan print valuedi dalam fungsi menghasilkan sebuahUnboundLocalError.

Alasannya adalah bahwa Python telah memperhatikan bahwa, di tempat lain dalam fungsi, Anda menetapkan nama value, dan juga valuetidak dideklarasikan di mana pun global. Itu membuatnya menjadi variabel lokal. Tetapi ketika Anda mencoba untuk mencetaknya, nama lokal belum didefinisikan. Python dalam kasus ini tidak kembali mencari nama sebagai variabel global, seperti beberapa bahasa lainnya. Pada dasarnya, Anda tidak dapat mengakses variabel global jika Anda telah mendefinisikan variabel lokal dengan nama yang sama di mana saja dalam fungsi.

baik hati
sumber
1
Terima kasih telah menunjukkan ini. Jadi, selama ruang lingkup lokal Anda tidak menetapkan nama yang ada di luarnya, maka referensi dalam lingkup lokal akan menggunakan nama luar. Namun, jika di mana saja dalam fungsi Anda Anda menetapkan untuk nama itu, referensi dalam lingkup lokal itu, bahkan sebelum penugasan lokal, jangan melihat ke luar.
Dmitry Minkovsky
1
Tepat, Anda sudah mendapatkannya. global(atau nonlocaldengan Python 3.x) mengesampingkan perilaku ini dan memungkinkan Anda untuk menetapkan kembali nama eksternal.
ramah
2
Dalam bahasa lain, ini tampaknya disebut sebagai "mengangkat", seperti ini misalnya: github.com/shichuan/javascript-patterns/blob/master/…
Dmitry Minkovsky
Untuk menambahkan penghinaan ke luka, variabel yang dideklarasikan dengan JavaScript yang lebih baru kata kunci letyang tidak mengangkat.
hati
Apakah lebih cepat mengakses variabel global yang dideklarasikan globalatau tidak masalah?
mato
14

Mengakses nama dan menetapkan nama berbeda. Dalam kasus Anda, Anda hanya mengakses nama.

Jika Anda menetapkan variabel dalam suatu fungsi, variabel itu dianggap lokal kecuali Anda mendeklarasikannya global. Dengan tidak adanya itu, diasumsikan global.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2
pengguna225312
sumber
7
  • Anda dapat mengakses kata kunci global tanpa kata kunci global
  • Untuk dapat memodifikasinya, Anda perlu secara eksplisit menyatakan bahwa kata kunci tersebut bersifat global. Jika tidak, kata kunci akan dinyatakan dalam cakupan lokal.

Contoh:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]
martynas
sumber
2

Setiap variabel yang dideklarasikan di luar suatu fungsi dianggap global, hanya ketika menyatakannya dari dalam fungsi (kecuali konstruktor) Anda harus menentukan bahwa variabel tersebut bersifat global.

Jesus Ramos
sumber
1

Ini dijelaskan dengan baik di FAQ Python

Apa aturan untuk variabel lokal dan global dalam Python?

Dalam Python, variabel yang hanya direferensikan di dalam fungsi secara global. Jika variabel diberi nilai di mana saja di dalam tubuh fungsi, itu dianggap lokal kecuali dinyatakan secara eksplisit sebagai global.

Meskipun sedikit mengejutkan pada awalnya, pertimbangan sesaat menjelaskan hal ini. Di satu sisi, mewajibkan globalvariabel yang ditugaskan menyediakan bilah terhadap efek samping yang tidak diinginkan. Di sisi lain, jika globaldiperlukan untuk semua referensi global, Anda akan selalu menggunakannya global. Anda harus mendeklarasikan sebagai globalsetiap referensi ke fungsi bawaan atau ke komponen modul yang diimpor. Kekacauan ini akan mengalahkan kegunaan globaldeklarasi untuk mengidentifikasi efek samping.

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

pengguna7610
sumber
0

Ini berarti Anda tidak boleh melakukan hal berikut:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"
ikostia
sumber
ikostia sedang menghitung semua hal yang tidak dapat Anda gunakan 'x' karena telah menggunakan global - docs.python.org/reference/…
pycruft
1
@Unode: Saya hanya menunjukkan semua kasus yang NikhilRathod berikan dalam kutipannya.
ikostia
0

Global membuat variabel "Global"

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

Ini membuat 'x' bertindak seperti variabel normal di luar fungsi. Jika Anda mengeluarkan global maka itu akan memberikan kesalahan karena tidak dapat mencetak variabel di dalam suatu fungsi.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
Michael
sumber