0

I am trying to make a datalogging code, for the user to input the number and age of animals, the birth rate and their chances of surviving the generation. I have tried to use return but when I run the program, the variables remain at 0.

Here I have initiated the variables

Gen0_J=0
Gen0_A=0
Gen0_S=0
Birth_rate=0
Srate_J=0
Srate_A=0
Srate_S=0
New_generations=5

My first function

def generation_values():
    Gen0_J=int(input("How many juveniles in Generation 0? "))
    Gen0_A=int(input("How many adults in Generation 0? "))
    Gen0_S=int(input("How many seniles in Generation 0? "))
    Srate_J=float(input("What is the survival rate for juveniles? "))
    Srate_A=float(input("What is the survival rate for adults? "))
    Srate_S=float(input("What is the survival rate for seniles? "))
    Birth_rate=int(input("What is the birth rate? "))
    return Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate

displaying the variables

def display_values():
    print("\nThe amount of juveniles in Generation 0 is",Gen0_J)
    print("The amount of adults in Generation 0 is",Gen0_A)
    print("The amount of seniles in Generation 0 is",Gen0_S)
    print("The birth rate in Generation 0 is",Birth_rate)
    print("The survival rate for juveniles in Generation 0 is",Srate_J)
    print("The survival rate for adults in Generation 0 is",Srate_A)
    print("The survival rate for seniles in Generation 0 is",Srate_S)

generation_values()
display_values()

However, the variables stay at 0

How many juveniles in Generation 0? 5
How many adults in Generation 0? 6
How many seniles in Generation 0? 7
What is the survival rate for juveniles? 0.75
What is the survival rate for adults? 1
What is the survival rate for seniles? 0
What is the birth rate? 2

The amount of juveniles in Generation 0 is 0
The amount of adults in Generation 0 is 0
The amount of seniles in Generation 0 is 0
The birth rate in Generation 0 is 0
The survival rate for juveniles in Generation 0 is 0
The survival rate for adults in Generation 0 is 0
The survival rate for seniles in Generation 0 is 0
2
  • 4
    Variables created inside a function don't change the value of variables created outside the function, even if they have the same names. Commented Dec 2, 2015 at 14:06
  • return doesn't place those values in the greater scope, they need to be assigned to values for that to happen. This may be helpful. Commented Dec 2, 2015 at 14:10

3 Answers 3

1

The scope of your variables is not consistent.

You could do it this way:

def generation_values():
    Gen0_J=int(input("How many juveniles in Generation 0? "))
    Gen0_A=int(input("How many adults in Generation 0? "))
    Gen0_S=int(input("How many seniles in Generation 0? "))
    Srate_J=float(input("What is the survival rate for juveniles? "))
    Srate_A=float(input("What is the survival rate for adults? "))
    Srate_S=float(input("What is the survival rate for seniles? "))
    Birth_rate=int(input("What is the birth rate? "))
    return Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate

def display_values(Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate):
    print("\nThe amount of juveniles in Generation 0 is",Gen0_J)
    print("The amount of adults in Generation 0 is",Gen0_A)
    print("The amount of seniles in Generation 0 is",Gen0_S)
    print("The birth rate in Generation 0 is",Birth_rate)
    print("The survival rate for juveniles in Generation 0 is",Srate_J)
    print("The survival rate for adults in Generation 0 is",Srate_A)
    print("The survival rate for seniles in Generation 0 is",Srate_S)

Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate = generation_values()
display_values(Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate)

would be a first step.

This way, the variables in the "main" namespace is separated from the variables in the functions.

A next step to remove repetition could be not to care about the separation of the variables in the main namespace, just to treat them as a tuple:

data = generation_values()
display_values(*data)

Further steps to remove repetition and to intoduce clarity could include:

  • assemble the data in one object (namedtuple or other object)
  • ask for and outout the data in a method of the object
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much! What does the *data do?
It unpacks the tuple data so that its components are passed as distinct arguments to the called function. See here.
1

The scope of your variables is incorrect. [variables declared inside a function, inside a class, or inside a module are not accessible at a higher level in your program - here is a short description of python scoping rules that super_biased_man posted in the comments]- in this case, the variables you are assigning to in generation_values() are defined locally.

It is surely not the proper way to do this, but declaring the variables global in generation_values() will solve your problem: (defining what would be an "ideal way" of doing this is dependent on where you are at in your study of programming & would take us too far)

Gen0_J=0
Gen0_A=0
Gen0_S=0
Birth_rate=0
Srate_J=0
Srate_A=0
Srate_S=0
New_generations=5


def generation_values():

    global Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate

    Gen0_J=int(input("How many juveniles in Generation 0? "))
    Gen0_A=int(input("How many adults in Generation 0? "))
    Gen0_S=int(input("How many seniles in Generation 0? "))
    Srate_J=float(input("What is the survival rate for juveniles? "))
    Srate_A=float(input("What is the survival rate for adults? "))
    Srate_S=float(input("What is the survival rate for seniles? "))
    Birth_rate=int(input("What is the birth rate? "))
    return Gen0_J,Gen0_A,Gen0_S,Srate_J,Srate_A,Srate_S,Birth_rate


def display_values():
    print("\nThe amount of juveniles in Generation 0 is",Gen0_J)
    print("The amount of adults in Generation 0 is",Gen0_A)
    print("The amount of seniles in Generation 0 is",Gen0_S)
    print("The birth rate in Generation 0 is",Birth_rate)
    print("The survival rate for juveniles in Generation 0 is",Srate_J)
    print("The survival rate for adults in Generation 0 is",Srate_A)
    print("The survival rate for seniles in Generation 0 is",Srate_S)

generation_values()
display_values()

An alternate way of handling this would be to pass the variables as arguments to your functions, and return them with values assigned... But there are a lot of them and passing them around is maybe going to clutter your code.

You could also gather them in a tuple or wrap them in a class.

Comments

0

As others have stated, the problem is that assignments to variables inside of a function create new variables instead of assigning the values to the globals. This is why the global keyword exists.

In this case, I would consider using a class since you have a number of related state values that you manipulate together.

class GenerationData(object):

    def __init__(self, gen_number):
        self.number = gen_number
        self.birth_rate = 0
        self.num_juveniles, self.num_adults, self.num_seniles = 0, 0, 0
        self.juvenile_rate, self.adult_rate, self.senile_rate = 0.0, 0.0, 0.0

    @classmethod
    def read(cls, gen_number):
        gen = cls(gen_number)
        gen.num_juveniles = read_integer(
            'How many juveniles in Generation {}?'.format(gen_number))
        gen.num_adults = read_integer(
            'How many adults in Generation {}?'.format(gen_number))
        gen.num_seniles = read_integer(
            'How many seniles in Generation {}?'.format(gen_number))
        gen.juvenile_rate = read_float(
            'What is the survival rate for juveniles? ')
        gen.adult_rate = read_float('What is the survival rate for adults? ')
        gen.senile_rate = read_float('What is the survival rate for seniles? ')
        gen.birth_rate = read_integer('What is the birth rate? ')

    def display(self):
        print('The amount of juveniles in Generation', self.number,
              'is', self.num_juveniles)
        print('The amount of adults in Generation', self.number,
              'is', self.num_adults)
        print('The amount of seniles in Generation', self.number,
              'is', self.num_seniles)
        print('The birth rate in Generation', self.number,
              'is', self.birth_rate)
        print('The survival rate for juveniles in Generation', self.number,
              'is', self.juvenile_rate)
        print('The survival rate for adults in Generation', self.number,
              'is', self.adult_rate)
        print('The survival rate for seniles in Generation', self.number,
              'is', self.senile_rate)


def read_integer(prompt):
    return int(raw_input(prompt))


def read_float(prompt):
    return float(raw_input(prompt))


first_generation = Generation.read(0)
first_generation.display()

This will make things easier when you are manipulating the generation data since it is all bundled into a single object.

Comments

Your Answer

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.