casualpy
casualpy

Reputation: 11

How do you change a variable function argument in python

I am trying to do something like this

x = 'no'
y = 'no'
z = 'no'

def xyz(arg):
    global x,y,z
    if foo in bar:
        if arg == 'no':
            print('yay')
            arg = 'yes'
        else:
            print('not yay')
    else:
        print('not yay')
        arg = 'no'

while True:
   xyz(x)
   xyz(y)
   xyz(z)

but it does not seem to change "arg" to yes or no. Any way I could do that?

Upvotes: 0

Views: 81

Answers (3)

wjandrea
wjandrea

Reputation: 32963

arg refers to a string object, e.g. 'no'. It cannot affect any other names that refer to the same string, e.g. x. It can't even change the value of the string object since strings are immutable.

What you should do is return from xyz and reassign x in the calling scope:

(Here I've also simplified the function logic and put the assignments onto one line to DRY them out.)

x = y = z = 'no'

def xyz(arg):
    if foo in bar and arg == 'no':
        print('yay')
        return 'yes'
    else:
        print('not yay')
        return 'no'

while True:
   x, y, z = map(xyz, [x, y, z])

Upvotes: 1

milanbalazs
milanbalazs

Reputation: 5329

I have implemented a working script. You should return the required value in the function and handling it on the caller side (when you call the function with the parameter).

The below script generates a random string and it returns "no" or "yes" based on if "a" is in the string (And prints your original "yay").

Code:

# Import modules for random string generation.
import random
import string

x = "no"
y = "no"
z = "no"


def generate_random_chars(number_of_chars):
    """
    Generating a random string.
    :param number_of_chars: Number of generated chars
    :return: The string with random chars.
    """
    return "".join(random.choice(string.ascii_letters) for _ in range(number_of_chars)).lower()


def xyz(arg):
    # Global variables are not needed. These are not used inside the function.
    # global x, y, z
    # Define the return value.
    return_value = "no"
    random_chars = generate_random_chars(10)
    print("Random characters: {}".format(random_chars))
    if "a" in random_chars:
        print("'a' is in generated chars")
        if arg == "no":
            print("yay")
            return_value = "yes"
        else:
            print("not yay")
    else:
        print("'a' is NOT in generated chars")
        print("not yay")
        # The following line is not needed because the default value of return in "no"
        # arg = "no"
    return return_value


# Only test in a 10th for loop Not in infinite while loop
for _ in range(10):
    print("X - Input: '{}' Output: '{}'".format(x, xyz(x)))
    print("Y - Input: '{}' Output: '{}'".format(y, xyz(y)))
    print("Z - Input: '{}' Output: '{}'".format(z, xyz(z)))

Output:

>>> python3 test.py 
Random characters: nbqrezimym
'a' is NOT in generated chars
not yay
X - Input: 'no' Output: 'no'
Random characters: ldbymrkarr
'a' is in generated chars
yay
Y - Input: 'no' Output: 'yes'
Random characters: cwlglelcqt
'a' is NOT in generated chars
not yay
Z - Input: 'no' Output: 'no'
Random characters: irjanpwnvh
'a' is in generated chars
yay
X - Input: 'no' Output: 'yes'
Random characters: rlvszdglqu
'a' is NOT in generated chars
not yay
Y - Input: 'no' Output: 'no'
Random characters: dnmvsjciwg
'a' is NOT in generated chars

Upvotes: 0

t0mas
t0mas

Reputation: 147

i think your issue is that you're not returning your arg

like this:

def xyz(arg):
    global x,y,z
    if foo in bar:
        if arg == 'no':
            print('yay')
            arg = 'yes'
        else:
            print('not yay')
    else:
        print('not yay')
        arg = 'no'
    return arg

but you have to have a variable to write to after you have called the funtion,

example = xyz(arg)

Upvotes: 1

Related Questions