SORU
23 EKİM 2008, PERŞEMBE


Verim anahtar kelime Python ne yapar?

Python yield anahtar kullanımı nedir? Ne işe yarar?

Örneğin, bu kodu anlamaya çalışıyorum1:

def node._get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance   max_dist >= self._median:
        yield self._rightchild  

Ve bu arayan kişi:

result, candidates = list(), [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

Yöntemi _get_child_candidates çağrıldığında ne olur? Bir liste döndürülür? Tek bir öğe döndürülür? Yine mi aradı? Sonraki aramalar ne zaman duracak?


1. Kod metrik uzaylar için harika bir Python kitaplığı yapan Jochen Schulz (jrschulz), geliyor. Bu tam kaynak link: Module mspace.

CEVAP
23 EKİM 2008, PERŞEMBE


yield ne yaptığını, ne olduğunu anlamak gerekirjeneratörler. Ve jeneratörler önce geliriterables.

İterables

Bir liste oluşturduğunuzda, öğeleri tek tek okuyabilirsiniz. Öğeleri tek tek yineleme denir okuma:

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

mylistiterable. Liste bir anlama kullandığınızda, bir listesi, ve bir iterable Peki oluşturun:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

"for... in..." bir iterable kullanımı hakkındaki herşeyi: lists, strings, dosyaları...

Bu iterables onları istediğiniz kadar okuyabilirsiniz, çünkü çok kullanışlı, ama belleğindeki tüm değerleri saklamak ve bu değerler çok şey var, istediğiniz her zaman mümkün değildir.

Jeneratörler

Jeneratör kullanımına, amasadece onları bir kez üzerinde yineleme yapabilirsiniz. Bellekteki tüm değerleri saklamak, onlar değil çünküsinek değerleri üretir:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

[] yerine () kullanılan hariç aynıdır. AMA, olamaz gerçekleştirmek for i in mygenerator bir saniye zamandan beri jeneratörler sadece bir kez kullanılabilir: onlar hesaplamak 0, sonra unut gitsin ve hesaplamak 1 ve son hesaplama 4, teker teker.

Verim

Yield fonksiyon jeneratörü döndürür hariç return gibi kullanılan bir kelime.

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

Burada gereksiz bir örnek olacak ama senin fonksiyonu sadece bir kez okunması gereken değerlerin büyük bir set dönecektir biliyorsun kullanışlı.

Usta yield bunu anlamanız gerekirişlevini çağırdığınızda, işlev gövdesi içinde yazdığınız kod çalışmaz.İşlevi sadece jeneratör nesneyi döndürür, bu biraz zor :-)

Sonra, kodunuzu for jeneratör kullanan her zaman çalışır.

Şimdi işin zor kısmı:

İlk kez for aramalar jeneratör nesne oluşturulan fonksiyon, çalıştırılacak kodu işlevinden başına kadar vurur yield, sonra döner ve ilk değeri döngü. Sonra, birbirlerine geri dönüş değeri yok kadar işlevi bir kez daha yazdım döngü çalıştırın ve bir sonraki değeri döndürür.

Jeneratör işlevi çalışır sonra boş sayılır ama verim artık isabet etmez. Döngünün bir sonu vardı çünkü, ya "if/else" artık memnun olmadığınız için olabilir.

Kodunuzu açıkladı

Jeneratör:

# Here you create the method of the node object that will return the generator
def node._get_child_candidates(self, distance, min_dist, max_dist):

  # Here is the code that will be called each time you use the generator object:

  # If there is still a child of the node object on its left
  # AND if distance is ok, return the next child
  if self._leftchild and distance - max_dist < self._median:
      yield self._leftchild

  # If there is still a child of the node object on its right
  # AND if distance is ok, return the next child
  if self._rightchild and distance   max_dist >= self._median:
      yield self._rightchild

  # If the function arrives here, the generator will be considered empty
  # there is no more than two values: the left and the right children

Arayan:

# Create an empty list and a list with the current object reference
result, candidates = list(), [self]

# Loop on candidates (they contain only one element at the beginning)
while candidates:

    # Get the last candidate and remove it from the list
    node = candidates.pop()

    # Get the distance between obj and the candidate
    distance = node._get_dist(obj)

    # If distance is ok, then you can fill the result
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)

    # Add the children of the candidate in the candidates list
    # so the loop will keep running until it will have looked
    # at all the children of the children of the children, etc. of the candidate
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result

Bu kodu çok akıllı parçaları içerir:

  • Döngüyü yineler bir liste ama liste genişletir, ancak döngü olmak yineledi :-) kısa ve öz bir şekilde geçmek tüm bu iç içe geçmiş veri olsa bile biraz tehlikeli sen sonunda bir sonsuz döngü. Bu durumda, candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) egzoz tüm değerleri jeneratör, ama while tutar oluşturma Yeni jeneratör nesneleri üretecek farklı değerler önceki olanlardan yana değil uygulanan aynı düğüm.

  • extend() yöntemi bir iterable bekliyor ve listeye değerlerini ekler listesi nesnesi bir yöntemdir.

Genellikle bunun için bir liste geçiyoruz:

>>> a = [1, 2]
>>> b = [3, 4]
>>> a.extend(b)
>>> print(a)
[1, 2, 3, 4]

Ama kodunuzda çünkü iyi bir jeneratör alır:

  1. Değerleri iki kez okumak zorunda değilsin.
  2. Bir sürü çocuk var ve bellekte hepsini saklı istemezsin.

Ve Python bir yöntem bağımsız değişken bir liste olup olmadığını umursamıyor, çünkü işe yarıyor. Python karakter dizileri, listeler, dizilerini ve jeneratörler ile çalışması iterables bekliyor! Bu ördek yazarak aradı ve Python bu kadar soğuk olmasının nedeni biridir. Ama bu başka bir hikaye, başka bir soru için

Burada dur, ya da jeneratör gelişmiş bir kullanım görmek için biraz okuyabilirsiniz:

Bir jeneratör bitkinlik kontrol

>>> class Bank(): # let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self):
...        while not self.crisis:
...            yield "$100"
>>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want
>>> corner_street_atm = hsbc.create_atm()
>>> print(corner_street_atm.next())
$100
>>> print(corner_street_atm.next())
$100
>>> print([corner_street_atm.next() for cash in range(5)])
['$100', '$100', '$100', '$100', '$100']
>>> hsbc.crisis = True # crisis is coming, no more money!
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs
>>> print(wall_street_atm.next())
<type 'exceptions.StopIteration'>
>>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business
>>> for cash in brand_new_atm:
...    print cash
$100
$100
$100
$100
$100
$100
$100
$100
$100
...

Bir kaynağa erişimi kontrol etme gibi çeşitli şeyler için yararlı olabilir.

İtertools, en iyi arkadaşın

İtertools modülü özel fonksiyonlar iterables işlemek için içerir. Hiç bir jeneratör çoğaltmak istiyorsunuz? Zincir iki adet jeneratör? Bir yolcu gemisi ile iç içe bir listesi grup değerleri? 41* *başka bir liste oluşturmadan?

import itertools o zaman.

Örnek mi? Hadi 4 at yarışı için varış order bakın:

>>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
 (1, 2, 4, 3),
 (1, 3, 2, 4),
 (1, 3, 4, 2),
 (1, 4, 2, 3),
 (1, 4, 3, 2),
 (2, 1, 3, 4),
 (2, 1, 4, 3),
 (2, 3, 1, 4),
 (2, 3, 4, 1),
 (2, 4, 1, 3),
 (2, 4, 3, 1),
 (3, 1, 2, 4),
 (3, 1, 4, 2),
 (3, 2, 1, 4),
 (3, 2, 4, 1),
 (3, 4, 1, 2),
 (3, 4, 2, 1),
 (4, 1, 2, 3),
 (4, 1, 3, 2),
 (4, 2, 1, 3),
 (4, 2, 3, 1),
 (4, 3, 1, 2),
 (4, 3, 2, 1)]

Yineleme iç mekanizmalarını kavrama

Yineleme işlemi iterables (__iter__() yöntemi uygulayan ve kullanımına (__next__() yöntemini uygulama) olarak sınıflandırılır. İterables bir yineleyici elde edebilirsiniz herhangi bir nesne. Kullanımına seni iterables üzerinde yineleme izin nesneleridir.

how does the for loop work konu hakkında daha fazla, bu madde.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • efaustus9

    efaustus9

    16 HAZİRAN 2006
  • mist64

    mist64

    30 Mayıs 2006
  • Top10Series

    Top10Series

    26 Kasım 2008