Advanced Function - generator

Dian yield a keyword

yield of the English word meaning production, whenever the yield keyword appears in the function, and then call the function, the function body will not continue to execute the code, but will return a value.

def func():
    print(1)
    yield
    print(2)
    yield

g = func()
print(g)

<generator object func at 0x10ddb6b48>
Generator is essentially an iterator, but also not just an iterator, but uses other than the iterator is really small, so we can proudly say: generator provides a very convenient way of self-defined iterator. And starting from the Python 2.5+, [PEP 342: Generator achieve synergies through enhanced program] achieved by adding more features to the generator, which means that the generator can also get more work done. In this section we will introduce later in the section.

def func():
    print('from func 1')
    yield 'a'
    print('from func 2')
    yield 'b'

g = func()
print(F"g.__iter__ == g: {g.__iter__() == g}")

res1 = g.__next__()
print(f"res1: {res1}")

res2 = next(g)
print(f"res2: {res2}")

# next(g)  # StopIteration

g.__iter__ == g: True from func 1 res1: a from func 2 res2: b

def func():
    print('from func 1')
    yield 'a'
    print('from func 2')
    yield 'b'


g = func()
for i in g:
    print(i)

print(f"list(func()): {list(func())}")

from func 1 a from func 2 b from func 1 from func 2 list(func()): ['a', 'b']

1.1 yield and return a second election

Since the generator function is also a function, it can use the return output return value it?

Pro, since you have chosen a custom function as a generator, also return you doing? If this is the Python2, Python interpreter will be presented to you an exception, but in Python3, he also whether you such a fool behavior.

def i_wanna_return():
    yield 'a'
    yield 'b'
    return None
    yield 'c'

for i in i_wanna_return():
    print(i)

a b

1.2 iterator sleeve iterator

If I need to access another generator in the generator's iterative process an iterative how to do? Written below so silly, very naive. And what your intention is to do this? ? ?

def sub_generator():
    yield 1
    yield 2
    for i in range(3):
        yield i

for i in sub_generator():
    print(i)

1 2 0 1 2

def sub_generator():
    yield 1
    yield 2
    yield from range(3)

for i in sub_generator():
    print(i)

1 2 0 1 2


Dian two collaborative programs

Coroutine (coroutine) generally refers to a function:

 * Each other have different local variables, the instruction pointer, but still shared global variables;
 * can easily suspend, resume, and a plurality of entry and exit points;
 * synergy among a plurality of programs running performance of collaboration, such as A the process needs to run in order to continue the implementation of the results of B.
Coroutine determine the characteristics of a moment, only a coordinated program is running (ignoring the case of multi-threaded). Thanks to this, coroutines can be passed directly between objects without regard to resource lock, or other direct wake-up process without the need for active co-sleep, like a built-in lock thread. In scenarios in line with the characteristics of coroutines, using the coroutine will undoubtedly be more convenient than using threads.

On the other hand, concurrent coroutines not in fact limit its application to the scene in a very narrow range, this feature makes the coroutine to be brought more compared with the conventional function, rather than thread. Of course, more complicated than many threads coroutine, and more powerful, so I suggest that you can firmly grasp the thread is not listening look ignorant force, then do not control him, because concurrent programming you'll relearn him. Therefore this section I will not enumerate examples of coroutines, and to understand the method described below.

Since Python2.5 + enhancement generator implements other features coroutine, in this version, a method of addition of the generator:

2.1 send(value)

The method of addition is next send another recovery generator. Python2.5 + in, yield statements into a yield expression, which means you can now have a yield value, and this value is to be called upon to restore execution method parameters send send method call generator.

def h():
    print('--start--')
    first = yield 5  # 等待接收 Fighting! 值
    print('1', first)
    second = yield 12  # 等待接收 hahaha! 值
    print('2', second)
    yield 13
    print('--end--')


g = h()
first = next(g)  # m 获取了yield 5 的参数值 5
# (yield 5)表达式被赋予了'Fighting!',  d 获取了yield 12 的参数值12
second = g.send('Fighting!')
third = g.send('hahaha!')  # (yield 12)表达式被赋予了'hahaha!'
print(f'--over--')
print(f"first:{first}, second:{second}, third:{third}")

--start-- 1 Fighting! 2 hahaha! --over-- first:5, second:12, third:13

  • Send incoming calls before non-None value, the generator must be in a suspended state, otherwise it will throw an exception. However, it does not start the generator can still use None as calling the send.
  • If you use the next recovery generator, the value of yield expression will be None.

    2.2 close()

    This method is used to close the generator. Call or send again to close next generation will raise StopIteration right.
def repeater():
    n = 0
    while True:
        n = (yield n)

r = repeater()
r.close()
print(next(r))  # StopIteration

2.3 throw(type,value=None,traceback=None)

Interrupt Generator is a very flexible technique can throw an exception through a GeneratorExit throw to terminate the Generator. Close () method does the same thing, in fact, inside it is called throw (GeneratorExit) of. We see the close of the source code:

def close(self):
    try:
        self.throw(GeneratorExit)
    except (GeneratorExit, StopIteration):
        pass 
    else:
        raise RuntimeError("generator ignored GeneratorExit") # Other exceptions are not caught


Wed and custom range () method

def my_range(start, stop, step=1):
    while start < stop:
        yield start
        start += 1

g = my_range(0, 3)
print(f"list(g): {list(g)}")

list(g): [0, 1, 2]

Four Dian summary

yield:
 1. to provide a custom iterator manner
 2.yield live pause function, and provides a return value of the current
yield and return:
 1. similarities: both are functions used internally, can return a value, and the return value does not limit the type and number of
 2. different points: return of the only return once; the yield can return multiple values


Five Dian generator expression

 * The list of derived formula [] with () is a generator expression
 * advantages: save memory, a value is generated only once in memory

t = (i for i in range(10))
print(t)
print(f"next(t): {next(t)}")

<generator object <genexpr> at 0x1101c4888> next(t): 0

Generating a list of expressions and derivation of formula

List comprehensions give you the equivalent of a basket of eggs directly, and generate equivalent expressions give you an old hen.

# 生成器表达式
with open('52.txt', 'r', encoding='utf8') as f:
    nums = [len(line) for line in f]

print(max(nums))

1

# 列表推导式
with open('52.txt','r',encoding='utf8') as f:
    nums = (len(line) for line in f)

print(max(nums)) # ValueError: I/O operation on closed file.

Guess you like

Origin www.cnblogs.com/suren-apan/p/11374764.html