Python Forum
yield usage as statement or expression
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
yield usage as statement or expression
#1
hi
the below code is in site:https://realpython.com/introduction-to-p...-statement
code:
# from: https://realpython.com/introduction-to-python-generators/  \
  #understanding-the-python-yield-statement

def is_palindrome(num):
    # Skip single-digit inputs
    if num // 10 == 0:
        return False
    temp = num
    reversed_num = 0

    while temp != 0:
        reversed_num = (reversed_num * 10) + (temp % 10)
        temp = temp // 10

    if num == reversed_num:
        return True
    else:
        return False

def infinite_palindromes():
    num = 0
    while True:
        if is_palindrome(num):
            print(num)
            i = (yield num)
            if i is not None:
                num = i
        num += 1


if __name__  == "__main__":
        pal_gen = infinite_palindromes()
        for i in pal_gen:
            digits = len(str(i))
            if digits == 5:
                pal_gen.throw(ValueError("We don't like large palindromes"))
            pal_gen.send(10 ** (digits))
On the above page is written:
Quote:As of Python 2.5 (the same release that introduced the methods you are learning about now), yield is an expression, rather than a statement. Of course, you can still use it as a statement. But now, you can also use it as you see in the code block above, where i takes the value that is yielded. This allows you to manipulate the yielded value. More importantly, it allows you to .send() a value back to the generator. When execution picks up after yield, i will take the value that is sent..
I before wrote a threat about statement and expression and asked about them:https://python-forum.io/thread-40934.html

I have saw before usage of yield like
yeild num
but in the above code there is
 i = (yield num)
.
which of them are statements and which are expressions. also, plz, explain the above text that has been written on the mentioned page.
why the line if i is not None: is used?
explain about:
 pal_gen.send(10 ** (digits))
thanks.
Reply
#2
From https://docs.python.org/3/whatsnew/2.5.h...r-features
Quote:In Python 2.3, yield was a statement; it didn’t return any value. In 2.5, yield is now an expression, returning a value that can be assigned to a variable or otherwise operated on:

val = (yield i)

I recommend that you always put parentheses around a yield expression when you’re doing something with the returned value, as in the above example. The parentheses aren’t always necessary, but it’s easier to always add them instead of having to remember when they’re needed.

(PEP 342 explains the exact rules, which are that a yield-expression must always be parenthesized except when it occurs at the top-level expression on the right-hand side of an assignment. This means you can write val = yield i but have to use parentheses when there’s an operation, as in val = (yield i) + 12.)
So yield is always an expression, with or without the surrounding parenthesis. You may need parenthesis for syntactic reasons.

Later in same document:
Quote:Values are sent into a generator by calling its send(value) method. The generator’s code is then resumed and the yield expression returns the specified value. If the regular next() method is called, the yield returns None.
In your example, "i" is None when next(pal_gen) is called by the for loop, and it has some number when calling pal_gen.send(). This explains why the print statement is in the generator. The main loop only sees half the palindromes. To demonstrate I moved the print statement into the mainloop.
def is_palindrome(num):
    # Skip single-digit inputs
    if num // 10 == 0:
        return False
    temp = num
    reversed_num = 0
 
    while temp != 0:
        reversed_num = (reversed_num * 10) + (temp % 10)
        temp = temp // 10
 
    if num == reversed_num:
        return True
    else:
        return False
 
def infinite_palindromes():
    num = 0
    while True:
        if is_palindrome(num):
            i = (yield num)
            if i is not None:
                num = i
        num += 1
 
 
if __name__  == "__main__":
        pal_gen = infinite_palindromes()
        for i in pal_gen:
            print("next", i)
            digits = len(str(i))
            if digits == 5:
                pal_gen.throw(ValueError("We don't like large palindromes"))
            print("send", pal_gen.send(10 ** (digits)))
Output:
next 11 send 101 next 111 send 1001 next 1111 send 10001 next 10101
The palindrome generator runs twice for each iteration of the main loop, and ignores the palindromes returned when pal_gen.send() is called.
Reply
#3
hi deanhystad
I read the section related to generator from https://docs.python.org/3/whatsnew/2.5.h...r-features
the below code is in it(simpler and shorter than what I posted before here.).
# from:https://docs.python.org/3/whatsnew/2.5.html#pep \
# -342-new-generator-features

def counter (maximum):
    i = 0
    while i < maximum:
        val = (yield i)
        # If value provided, change counter
        if val is not None:
            i = val
        else:
            i += 1

if __name__== "__main__":
    it = counter(5)
    print( next(it))
    print( next(it))
    print( it.send(3))   # attention to send
    print( next(it))
    print( next(it))
I ran the above code with idle debugger line by line two times.
after running the line
val=(yield i)
, why the value of val is None.
if this line means that the value of i is assigned to val variable?
in the line
print(it.send(3))
, the value of 3 is assigned to i or val?

I also saw in the introduced reference by you that is written:
Quote:yield will usually return None...
I do not understand this.plz, explain

assume i=2 and maximum=3 and now we are in line
 val=(yield i)
. after running this line,
what is the value of val variable?
thanks for the last reply
Reply
#4
If the generator resumes because of next(), the yield value will be None. If the generator resumes because of send(x), the yield value will be x.
Reply
#5
(Oct-22-2023, 06:34 PM)deanhystad Wrote: If the generator resumes because of next(), the yield value will be None. If the generator resumes because of send(x), the yield value will be x.

hi
I read your reply and thanks for replying.
as I said I read the reference that you introduced and also I ran (by idle debugger)all the code in this thread at least twice for each( i ran some 5 times), but I sense I do not understand gernerator and send. can you mention another site or reference?
thanks
Reply
#6
(Oct-23-2023, 11:16 AM)akbarza Wrote: can you mention another site or reference?
An excellent and classical reference about generators and coroutines is David Beazley's talk(s) about this subject.
buran and akbarza like this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  yield from akbarza 4 295 Apr-19-2024, 07:58 PM
Last Post: DeaD_EyE
  difference between statement and expression akbarza 6 865 Oct-18-2023, 07:40 AM
Last Post: akbarza
  Using list comprehension with 'yield' in function tester_V 5 1,262 Apr-02-2023, 06:31 PM
Last Post: tester_V
  List Creation and Position of Continue Statement In Regular Expression Code new_coder_231013 3 1,679 Jun-15-2022, 12:00 PM
Last Post: new_coder_231013
  Yield generator weird output Vidar567 8 3,300 Nov-23-2020, 10:59 PM
Last Post: deanhystad
  Trying to access next element using Generator(yield) in a Class omm 2 1,982 Oct-19-2020, 03:36 PM
Last Post: omm
  Yield statement question DPaul 6 2,527 Sep-26-2020, 05:18 PM
Last Post: DPaul
  Problem about yield, please help!! cls0724 5 2,878 Apr-08-2020, 05:37 PM
Last Post: deanhystad
  Pass results of expression to another expression cmdr_eggplant 2 2,299 Mar-26-2020, 06:59 AM
Last Post: ndc85430
  does yield support variable args? Skaperen 0 1,688 Mar-03-2020, 02:44 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020