How to call variables from other files python with classes? - python

Hi all I would like to know how to call variables (which are inside classes) from other python files. I am aware of the bellow method of doing this however it will not work if the class is called from the original file.
from (insert_file_name_hear) import *
This a similar sample to what I'm working with:
functions.py
num = 0
num2 = 0
class Test():
def alt_num(self):
global alt_num
alt = 55
def change(self):
global num, num2
num += alt_num
num2 = num
def print_num():
global num2
print(num2)
def work():
Test.alt_num(Test)
Test.change(Test)
print_num()
print.py
from functions import *
work()
def printing():
print(num2)
printing()
When I run print.py it will accuratly print in the functions.py file however it will print 0 in the print.py file. Note: Both files are in the same folder and I am running this in Python 3.
Thanks

Instead of using Globals you can use class variables with a little bit of effort
functions.py
class Test():
num = 0
num2 = 0
alt = 0
#classmethod
def alt_num(cls):
cls.alt = 55
#classmethod
def change(cls):
cls.num += cls.alt
cls.num2 = cls.num
def print_num():
print(Test.num2)
def work():
Test.alt_num()
Test.change()
print_num()
Test.change()
print_num()
Test.change()
print_num()
return Test.num2
print.py
from functions import *
work()
def printing():
print(Test.num2)
printing()
Note: the output of the above is
55
110
165
165
The first three come from work(), the last from printing()

First - alt and alt_num are not defined
Second - You need to return the variable through a function to use it elsewhere
Below is how you can do this
functions.py
alt = 0
num = 0
num2 = 0
class Test():
def alt_num(self):
global alt
alt = 55
def change(self):
global num, num2
num += alt
num2 = num
def print_num():
global num2
def work():
Test.alt_num(Test)
Test.change(Test)
print_num()
return num2
print.py
from functions import *
def printing():
print(work())
printing()

In functions.py you declare num2 = 0, the rest of the manipulation of num2 is made inside functions that do not return the new value.
The function print_num() actually prints the new value of num2, this is where 55 comes from in the output.
In print.py you are printing the num2 that is declared on line 2 of functions.py
If you are only interested in num2 after the value has been updated you could skip the printing in functions.py, instead return the value and print it from print.py.
It could look something like this.
functions.py
num = 0
class Test():
def alt_num():
global alt
alt = 55
def change():
global num
global num2
num += alt
num2 = num
def work():
Test.alt_num()
Test.change()
return(num2)
print.py
from functions import *
def printing():
print(work())
printing()

Related

How to call a python function "with arguments" present within a class which has a constructor from a pytest function?

I could not find a similar question based on pytest. Stuck with this for quite sometime. Please do not close this until it is answered. thank you.
The python class looks like:
class Calculator:
def __init__(self, num1=None, num2=None):
self.logger = get_logger(__name__)
self.num1 = num1
self.num2 = num2
def calculate(self):
if self.num1 and self.num2:
num = self.__divider(num1, num2)
else:
raise Exception('num2 cannot be 0')
return self.__faulty_displayer(num)
def __divider(self, num1, num2):
value = num1/num2
return value
def __faulty_displayer(self,num)
value = num + 1
return value
What I want to be able to do is, write a pytest for calculate() method. But, I am unable to do so, as I am unable to call the method with any values. So, inherently, every time, the exception is getting called.
What I have tried so far is:
import pytest
#pytest.fixture
def obj():
return Calculator()
# Need help in writing a test case which can take the values of num1, and num2
def test_calculate(obj):
expected_value = 1
actual_value = obj.calculate() #How to pass num1, and num2 values
assert expected_value == actual_value
The way that your class is defined, num1 and num2 have to be defined at the time the object is constructed. This is an awkward design (as you're discovering now in trying to write your test), but assuming that we need to work with that class as-is instead of fixing it, then the test needs to construct the object with the test values, like this:
def test_calculate(num1, num2, expected):
"""Test that Calculator.calculate() produces the expected result."""
assert Calculator(num1, num2).calculate() == expected
test_calculate(1, 1, 2) # 1 / 1 + 1 = 2
test_calculate(4, 2, 3) # 4 / 2 + 1 = 3

Python variable's value doesn't get changed outside the function

I'm working on a school project. I made a test version of my program, because I'm new to Python and I only have experience with C#, so I'm still learning te basics. My problem is the following:
Before the function "Fill_Array()" I declared a variable (" max_element_var") that is supposed to store the max number of elements that can be stored in the array ("content_array"). Later in the function I change it's value to the input of the console, which happens, and the function runs as it should, the only problem being is that outside the function the value of " max_element_var" stays "None". What should I do in order to fix this?
#__Test__#
def Test():
class Que:
def __init__(self, content, max_element ,actual_elements):
self.content = content
self.max_element = max_element
self.actual_elements = actual_elements
max_element_var = None
content_array = []
def Fill_array():
print("What should be the max number of elements that can be stored in the array? (Type in an integer!)")
max_element_var = int(input())
if(max_element_var>0):
import random
random_var = random.randrange(0,max_element_var)
for x in range(max_element_var-random_var):
content_array.append(x)
else:
print("It has to be more than 0!")
Fill_array()
Fill_array()
actual_elements_var = len(content_array)
que = Que (content_array, max_element_var, actual_elements_var)
print("Content: ", que.content)
print("Max number of elements: ", que.max_element)
print("Actual number of elements: ", que.actual_elements)
#__Test__#
#__Full__#
def Full():
pass
#__Full__#
#__Version_selector__#
def Version_selector():
print("Which version should be used? (Type in the number!)")
print("1 - Test")
print("2 - Full")
answer = int(input())
if(answer == 1):
Test()
Version_selector()
elif(answer == 2):
Full()
Version_selector()
#__Version_selector__#
Version_selector()
In python variables are automatically created as local, in the scope of the function which used them alone.
To solve your problem you may either
(1) return the variable, passing it from one function the other explicitly.
(2) declare it as global so all functions have access to it.
More about scopes here and here.
Consider the following code. In the code below you persumably change the value of x but in fact there is a big difference between the x inside the function and outside. The x inside the function is a local variable and will "disappear" once the function ends. If you want to save the value of x you must use return x and save the outcome to a variable. For example, See the function a_saving_example(x)
you may also use a global variable though some say it is bad practice and it is better to use return in your function.
def times_two(x):
x = x * 2
x = 5
print(x)
times_two(x)
print(x)
output:
5
5
saving example:
def a_saving_example(x):
x = x * 2
return x
x = 5
print(x)
x = a_saving_example(x)
print(x)
output:
5
10
Modified code to correct some issues.
Import normally done at top of module (not within functions)
Remove nested class definition inside function (obfuscates things in simple code)
Changed recursive calls to a while loop (a better way to repeat execution of a function from beginning in Python since no tail recursion).
Code Refactoring
import random
class Que:
def __init__(self, content, max_element ,actual_elements):
self.content = content
self.max_element = max_element
self.actual_elements = actual_elements
def Fill_array():
" Returns requested size and array "
while True:
prompt = """"What should be the max number of elements that can be stored in the array? Type in an integer!: """
max_element_var = int(input(prompt))
if max_element_var > 0:
random_var = random.randrange(0,max_element_var)
return max_element_var, [x for x in range(max_element_var-random_var)]
else:
print("It has to be more than 0!")
def Test():
max_element_var, content_array = Fill_array()
actual_elements_var = len(content_array)
que = Que (content_array, max_element_var, actual_elements_var)
print("Content: ", que.content)
print("Max number of elements: ", que.max_element)
print("Actual number of elements: ", que.actual_elements)
#__Test__#
#__Full__#
def Full():
pass
#__Full__#
#__Version_selector__#
def Version_selector():
while True:
prompt = """Which version should be used? (Type in the number!)
1 - Test
2 - Full
3 - Quit\n\t"""
answer = int(input(prompt))
if answer == 1:
Test()
elif answer == 2:
Full()
else:
break
#__Version_selector__#
Version_selector()

Issues with declaration method ( & self) in python

While trying to experiment with classes and methods, and how to pass variables between them, I wrote a couple of scripts to try to understand the mechanics.
In doing so I hit an issue where one of my functions is un-defined:
NameError: name 'exclaim' is not defined
I thought use of self might resolve but i just loop round into
NameError: name 'self' is not defined
I've come across several sources regarding this leading me to look at indentation levels of methods, and calling via HelloWorld.exclaim()
which hits the same issue.
please see my code: (script1)
import datasource
class HelloWorld:
def exclaim():
number1 = input("enter a number")
datasource.Class2.method3.impvariable1 = number1
def main():
HelloWorld.exclaim()
print(datasource.Class1.method1.variable1)
print(datasource.Class2.method2.variable2)
print(datasource.Class2.method3.variable3)
if __name__ == '__main__':
main()
Script2:
#datasource.py
class Class1:
def method1():
variable1 = "Hello "
class Class2:
def method2():
variable2 = "World"
def method3():
impvariable1 = 0
variable3 = "!"
for x in range(impvariable1):
variable3 = variable3 + "!"
I also tried (amount 100's of other iterations)
#datahandler.py
import datasource
class HelloWorld:
def exclaim(self):
number1 = input("enter a number")
datasource.Class2.method3.impvariable1 = number1
def main(self):
HelloWorld.exclaim(self)
print(datasource.Class1.method1.variable1)
print(datasource.Class2.method2.variable2)
print(datasource.Class2.method3.variable3)
if __name__ == '__main__':
main(self)
which produces;
NameError: name 'self' is not defined
import datasource
class HelloWorld:
def exclaim(self):
number1 = input("enter a number")
datasource.Class2.method3.impvariable1 = number1
def main():
obj = HelloWorld()
obj.exclaim()
print(datasource.Class1.method1.variable1)
print(datasource.Class2.method2.variable2)
print(datasource.Class2.method3.variable3)
if __name__ == '__main__':
main()

Shortening a class with __init__

I created a Class that does math with Mixed numbers.
It takes two strings (f1 and f2) ex '1+1/4' and '3+1/5' and can add subtract multiply or divide them.
I was wondering if I could shorten the code using __init__
Can I just pass f1 and f2 to __init__ and reduce the repetition?!
at the moment I have to put the following code into each method which takes in f1 and f2
coef1 = int(f1.split('+')[0])
coef2 = int(f2.split('+')[0])
num1 = int(f1.split('+')[1].split('/')[0])
num2 = int(f2.split('+')[1].split('/')[0])
de1 = int(f1.split('+')[1].split('/')[1])
de2 = int(f2.split('+')[1].split('/')[1])
Each method needs each of those variables to do math
You don't show any classes, where you could use __init__.
First you should write a function:
def parse_mixed_number(f):
coef, numden = f.split('+')
num, den = numden.split('/')
return int(coef), int(num), int(den)
coef1, num1, den1 = parse_mixed_number(f1)
coef2, num2, den2 = parse_mixed_number(f2)
If you want to use classes, then, parse_mixed_number should be called in __init__:
from collections import namedtuple
class MixedNumber(namedtuple("MixedNumber", "coef,num,den")):
def __new__(cls, f):
coef, numden = f.split('+')
num, den = numden.split('/')
return tuple.__new__(cls, [int(coef), int(num), int(den)])

Returning values to other functions

I am fairly new to python and I am trying to figure out how to use variables from one function in another one. I can't seem to use the return command correctly. All help is appreciated! Here is an example of what I want:
{
def a():
num1 = input("number: ")
return num1
def b():
str1 = input("letter :")
return str1
def main():
a()
b()
print(num1,str1)
}
Simply assign the returned values to variables in main(), and don't forget to add a return statement in b(). By default a function returns None in Python.
def a():
num1 = input("number: ")
return num1
def b():
str1 = input("letter :")
return str1
def main():
num1 = a() #here you can use any variable name, not necessarily `num1`
str1 = b() #here you can use any variable name, not necessarily `str1`
print(num1,str1)
Demo:
>>> main()
number: 10
letter :a
10 a
Try like this,
def main():
print(a(),b())

Categories

Resources