0

I am making new program in Python (Mastermind). I have a problem with references of variables:

def user_turn():
 try_counter = 1
 user_code = []
 guessed_code = random_code()
 print("Twoja kolej na zgadywanie!")
 while try_counter <= max_tries and user_code != guessed_code:
 good_number, good_number_and_position = 0, 0
 appearance_types_guessing_code = [0 for i in range(types)]
 appearance_types_user_code = [0 for i in range(types)]
 user_code = input("Próba nr {}: ".format(try_counter))
 user_code = list(map(int, str(user_code)))
 count_xos()
 print_xos()
 try_counter += 1
 print_result_user_turn()

Body of the function print_xos():

def print_xos():
 for i in range(good_number_and_position):
 print("x", end='')
 for i in range(good_number):
 print("o", end='')
 print("")

And my problem is that in function print_xos() variables good_number and good_number_and_position are unknown, despite of fact I declared this variables in the while loop in the body of the function user_turn(). How can I solve this problem? I don't want to send the reference as an argument of the function. In my opinion it isn't elegant. Is it possible to do it in another way?

EDIT:

OK, I changed a code a little bit then:

def user_turn():
 try_counter = 1
 user_code = []
 guessed_code = random_code()
 appearance_types_guessed_code = [0] * types
 how_many_appearance(guessed_code, appearance_types_guessed_code)
 print("Twoja kolej na zgadywanie!")
 while try_counter <= max_tries and user_code != guessed_code:
 good_number, good_number_and_position = 0, 0
 appearance_types_user_code = [0] * types
 user_code = input("Próba nr {}: ".format(try_counter))
 user_code = list(map(int, str(user_code)))
 how_many_appearance(user_code, appearance_types_user_code)
 print(appearance_types_guessed_code, appearance_types_user_code)
 count_xos(guessed_code, appearance_types_guessed_code, user_code, appearance_types_user_code, good_number, good_number_and_position)
 print(good_number_and_position, good_number)
 print_xos(good_number_and_position, good_number)
 try_counter += 1
 print_result_user_turn(guessed_code, user_code)

And the body of function count_xos:

def count_xos(guessed_code, appearance_types_guessed_code, user_code, appearance_types_user_code, good_number, good_number_and_position):
 for i in range(len(appearance_types_guessed_code)):
 good_number += np.min([appearance_types_guessed_code[i], appearance_types_user_code[i]])
 for i in range(code_size):
 if guessed_code[i] == user_code[i]:
 good_number_and_position += 1
 good_number -= 1
 print(good_number_and_position, good_number)

And I got this output:

RUNDA 1
Twoja kolej na zgadywanie!
Próba nr 1: 0011
[0, 2, 0, 1, 0, 0, 0, 1, 0, 0] [2, 2, 0, 0, 0, 0, 0, 0, 0, 0]
1 1
0 0

You can be certain that function count_xos counts good_number, good_number_and_position counts properly. It should be 1 1, but I don't know why after running the method count_xos, variables good_number_and_position, good_number are not changed?

marc_s
760k186 gold badges1.4k silver badges1.5k bronze badges
asked Mar 3, 2019 at 7:36
3
  • 3
    quite the contrary, the elegant solution is for your function to receive those values as argument, not to rely on those being set as global variables outside the function. Commented Mar 3, 2019 at 7:43
  • as a side note, [0 for i in range(types)] is better written as [0] * types Commented Mar 3, 2019 at 7:46
  • Read about Scoping rules - it it best to keep the scope as small as possible and provide data to the function they need. There is seldom need to do something global. Commented Mar 3, 2019 at 9:09

1 Answer 1

0

Your last attempt does not return the numbers so the provided numbers do not carry out into your calling function.

Your code does the equivalent of:

def one(aa,bb):
 aa *= 2
 bb *= 3
 print("In function", aa, bb)
 return aa, bb
a = 5
b = 11
one(a,b) # does not reassign returned values - similar to not return anything like yours
print(a,b)

Output:

In function 10 33
5 11 

You need to return and reassign the values:

a,b = one(a,b) # reassign returns
print(a,b)

Output:

In function 10 33
10 33

Have a look at Scoping rules - it it best to keep the scope as small as possible and provide data to the function they need.

If you modify things inside function return its new values and reassign them - this is not deeded if you pass a list, they are mutable references and "autoupdate" because you operate through the ref on the data:

# same function used as above
a = 5
b = [11]
one(a,b)
print(a,b)

Output:

In function 10 [11, 11, 11]
5 [11, 11, 11]

If you take a look at the id()s of the variables you can see that altering aa will repoint the name aa to some other id - but a on the outside still points to the original one. Altering the list does not alter the reference-id - it alters the data the ref "points" to:

def one_ids(aa,bb):
 print(id(aa),id(bb))
 aa *= 3 # modify an integer
 bb *= 3 # modify the list
 print(id(aa),id(bb))
a = 5
b = [11]
print(id(a),id(b))
one_ids(a,b)
print(id(a),id(b))

Output:

139647789732288 139647790644808 # id of a,b
139647789732288 139647790644808 # id of aa,bb before changing
139647789732**6**08 139647790644808 # id of aa,bb after changing
139647789732288 139647790644808 # id of a,b 

You can read further in Function changes list values and not variable values in Python - see if those explanaitions fit you better.

answered Mar 3, 2019 at 9:15
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.