Alan ve Fonksiyon Farkı Nedir?

Python öğreniyorum. Aşağıdaki yazıda 5 alanı anlatıyor.

Yerel alan ve yerel değişken arasındaki fark nedir? Örneğin yazıda şöyle yazıyor “L Yerel (local) : Lambda ya da fonksiyonlar içinde tanımlanan değişkenler için kullanılan alandır.”

Bir de yazıdaki “Kapalı (enclosed) :” tanımını anlamadım. :thinking:

Aslında site üzerindeki bir fotoğraf çok güzel anlatmış ama bir ufak örnek vereyim :slight_smile:

def function():
    a = "yazbel"
    
    return(a)
    
print(function())
print(a)

#output;
    print(a)
NameError: name 'a' is not defined

Ben a değişkenini function() adlı fonksiyon içerisinde tanımladım yani “Local” bu yüzden “global” olarak erişemiyorum.

Enclosed kapsamı dediği fonksiyon içerisinde bir fonksiyon daha tanımlandığı zaman kullanılıyor.

Eğer a değişkenini şu şekilde tanımlasaydım bir hata almazdım.

a = "yazbel"

def function():
    return(a)

print(function())
print(a)

The globals() function returns a dictionary containing the variables defined in the global namespace

Globals() ad uzayında tanımlanmış değişkenleri görebilmek istiyorsan bu fonksiyonu kullanabilirsin.

The locals () function returns a dictionary containing the variables defined in the local namespace

Local ad uzayında tanımlanmış değişkenleri görebilmek istiyorsan bu fonksiyonu kullanabilirsin.

Kaynak eski ve Python2 için yazılmış, şuanki CPython için bilgi yanlışları var. Hatta Python2 için de yanlış bilgi var.

Python3’te __builtin__ yerine __builtins__ var.

>>> __builtin__
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    __builtin__
NameError: name '__builtin__' is not defined
>>> __builtins__
<module 'builtins' (built-in)>

__name__ değişkeni modül globallerinin bir parçası ve her modülün kendi __name__ değişkeni var.

>>> __name__ is __builtins__.__name__
False
>>> __name__ is globals()["__name__"]
True
>>> __name__
'__main__'
>>> __builtins__.__name__
'builtins'

Yerel alan, yerel değişkenlerin bulunduğu alan oluyor. Yerel değişkenler de yerel alanda oluşturulan sıradan değişkenler.

Fonksiyonlar kendi alanlarına (scope) sahipler, bir değişken hangi alanda oluşturulursa o alana ait olur.

Herhangi bir fonksiyonun içinde tanımlanan başka herhangi bir fonksiyona enclosed fonksiyon deniyor:

def herhangi_bir_fonksiyon():
    def bir_enclosed_fonksiyon():
        ...


Python’un isim çözümlemesi (name resolution) basit, kendi alanına sahip olan üç şey var: modüller, sınıflar ve fonksiyonlar.

Modül alanlarına global alan da deniliyor. globals fonksiyonu içinde çağırıldığı modülün alanını dict olarak döndürüyor, çünkü alanlar zaten birer dict:

>>> a = 1
>>> b = "c"
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\Dinçel\\Desktop\\client.py', 'a': 1, 'b': 'c'}

Sınıfların ve fonksiyonların alanlarına yerel alan deniyor. Sınıfların isim çözümlemesindeki yerleri küçük. Ama nitelik çözümlemesinde (attribute resolution) önemliler.

Bir isme erişilmeye çalışıldığında:

  • Eğer yerel bir alanda isek önce bulunduğumuz yerel alana bakılır. Orada bulunamaz ise:
    • Eğer içinde bulunduğumuz yerel alan -alanın ait olduğu sınıf veya fonksiyonun kullanıldığı değil, tanımlandığı yer olarak- herhangi bir veya birden fazla fonksiyonun içinde bulunuyor ise en iç fonksiyonun alanından başlayarak en sondaki fonksiyonun alanına kadar isim için kontrol yapılır (bu kuralın yan etkilerinden biri de late binding oluyor), bulunamaz ise son maddede belirttiğim şekilde global alana bakılır.
    • Eğer içinde bulunduğumuz yerel alan herhangi bir fonksiyonun içinde değilse global alana bakılır. Global alana bakarken aşağıdaki kural geçerli.
  • Eğer yerel bir alanda değil isek, yani global alanda isek direkt global alana bakılır. Orada bulunamaz ise __builtins__'e bakılır. Orada da bulunamaz ise NameError yükseltilir.
3 Beğeni

Ek olarak, tanımlanmasa da her nesnenin bir __name__ niteliği var.

>>> class A: pass
...
>>> A.__name__
'A'
1 Beğeni

Her nesnenin değil, lambda olmayan fonksiyonların, modüllerin ve sınıfların var.

1 Beğeni

Lambda’nın da var.

>>> x = lambda: 1
>>> x.__name__
'<lambda>'
>>> 
2 Beğeni

Doğru, kafam karıştı. Ama hepsinin ismi aynı: <lambda>:

2 Beğeni

Orası öyle ama bir adı var. Zaten tam da sizin bahsettiğiniz nedenden ötürü, bir lambda fonksiyonunun doğrudan bir değişkene atanması, PEP8 E731’e göre istenmiyor.

Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.

Yes:

def f(x): return 2*x

No:

f = lambda x: 2*x

The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic '<lambda>'. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)

1 Beğeni

Cevaplar için teşekkürler. Türkçe kaynaklarda global alan ve global değişken arasındaki farklar iyi anlatılmamış. İngilizce sitelerden araştırdım, zor anladım. Belki önemli bir konu değil ama kafamı karıştırdı.
Bence web sitesi açıp python dersi verenler bu farklı iyi açıklamalı. Hatta bazı web sitelerindeki yazıların aynı olduğunu gördüm. Sanırım kelimeleri değiştirip kendi yazıları gibi gösteriyorlar.