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?
CEVAP
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
mylist
iterable. 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, amawhile
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:
- DeÄŸerleri iki kez okumak zorunda deÄŸilsin.
- 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.
Java mı anahtar kelime iddia, ne yapar...
Neden verim sıradan bir IEnumerable ku...
Geçen anahtar kelime python parametre ...
'in ne verim JavaScript anahtar k...
Kullanımı "genel" Python ana...