0

Im new to python so forgive me if Im not applying best practices and I welcome any feedback to help doing the code below the python way. I have the following code and the out put is making me very confused and not sure how to fix in order to get the expected output. Im getting the name Sal on both greetings:

    from time import sleep
    import threading
    
    def printGreating(get_greeting):
        sleep(5)
        greeting = get_greeting()
        print(greeting)
    
    
    def createGreeting(greeting,name):
        return greeting+' '+ name
    
    
    
    nameslist = ["Sam","Sal"]
    threads = []
    
    for n in nameslist:
        print(n)
    
        if n == "Sam":
    
            create_greeting_l = lambda : createGreeting("Hello",n)
    
        else:
    
            create_greeting_l = lambda : createGreeting("Greeting",n)
    
    
        t = threading.Thread(target=printGreating, args=(create_greeting_l,))
    
        t.start()
    
        threads.append(t)
    
    for t in threads:
    
        t.join()
    
    
print('-------------------Completed--------------')

Expected output:

Sam
Sal
Hello Sam
Greeting Sal
-------------------Completed--------------

What Im getting:
Sam
Sal
Greeting Sal
Hello Sal

Expected output:

Sam Sal Hello Sam Greeting Sal

What Im getting: Sam Sal Greeting Sal Hello Sal

UPDATED Dec 22,2022:

I finally figured out the fix. the name should be passed as parameter to the lambda funntion:

if n == "Sam":
        
        create_greeting_l = lambda a : createGreeting("Hello",a)

     else:
        
        create_greeting_l = lambda a : createGreeting("Greeting",a)

     t = GreeterClass(create_greeting_l,n)
  • 1
    Threads are executed asynchronously. There is no "expected" order of execution here. The only thing that's really guaranteed is that `"Sam"` will be printed first, and that each name will be printed before its associated greeting. – chepner Dec 21 '22 at 20:53
  • No Sir please see my full post. Im expecting: Hello Sam Greeting Sal but Im getting the name Sal on both greetings – samer saleh Dec 21 '22 at 21:10
  • 1
    You don’t need threads to get this behaviour. Any code that executes the first function after defining the second has this behaviour; see the duplicate. – MisterMiyagi Dec 21 '22 at 21:13
  • 2
    My point stands, even after fixing the closure issue. Once the thread is started, it could be scheduled to execute before the `for` loop continues on to the next name in `nameslist`. – chepner Dec 21 '22 at 21:15
  • so how can I fix it where each call preserve the passed parameters – samer saleh Dec 21 '22 at 21:16
  • I dont think the duplicate has anything to do with this post. @MisterMiyagi , executing this code without threads works as expected. Please read the post carefully and dont rush your judgment. – samer saleh Dec 21 '22 at 21:33
  • @samersaleh Of course executing this code without threads works as expected, just as executing the duplicates code without storing the fictions works as expected; the point is that *any* means of delayed execution triggers this. Did you try the *solution* offered on the duplicate, I.e. `create_greeting_l = lambda n=n : createGreeting("Hello",n)`? – MisterMiyagi Dec 22 '22 at 04:31

0 Answers0