python get new value in a class or method - python

i'am new to python and try to get the new value for my bool in a class .
i try create a global, set in the init.
How can i get the new value of the test bool in getnewvalue() ?
Here is my code :
test = False
class myclass():
def changevalue()
test = True
getnewvalue()
def getnewvalue():
print(test)

If you want to have data inside your class, it's a good idea to use the __init__()
and save it like that. More here in the Python tutorial: Class Objects.
And use the __init__ to initialize the class with desired values.
Your code should look something like this:
test = False
class myclass():
def __init__(self, test):
self.test = test # self keyword is used to access/set attrs of the class
# __init__() gets called when the object is created, if you want to call
# any function on the creation of the object after setting the values
# you can do it here
self.changevalue()
def changevalue(self): # if you want to access the values of the class you
# need to pass self as a argument to the function
self.test = not test
self.getnewvalue()
def getnewvalue(self):
print(self.test) # use self to access objects test value
_class = myclass(False)
Or if you just want to have a class with functions, you can do something like this:
test = False
class myclass():
#staticmethod
def changevalue(val)
return not val
#staticmethod
def getnewvalue(test):
print(test)
_class = myclass()
test = _class.changevalue(test)
This way it won't print your value on call because it's just setting your value to return of that function. You'll have to do it yourself but that shouldn't be a problem.
More about staticmethods here: #staticmethod

Add
global test
to both functions. The resulting code would be...
test = False
class myclass():
def changevalue():
global test
test = True
getnewvalue()
def getnewvalue():
global test
print(test)
global allows the function to access variables outside of itself.
Hope this helps!

Related

Python - Class object as function argument: Object only - Class not in argument

I am trying to write a function taking a string as an argument and using this argument as a class object.
Note that my explanantion might be strangely formulated sice I could not find an answer online. The MWE below should clarify what I mean, the problematic line is indicated.
Edit: in the MWE, "print" is an example. I need to be able to call the object to update it, print it or, in the case of a list, append to it. I need access to the object itself, not the value of the object.
MWE
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Define function
def myFunction (parameter):
print(myObject.parameter)##### This line is currently not possible.
# Use class
myObject = myClass()
# Use function
myFunction("one")
I am not trying to append a new object to the class, only to call an existing object.
Is this even possible?
Looks like you need the built-in function called getattr
my_object = myClass()
def my_function(parameter):
print(getattr(my_object, parameter, None))
also this is not the best practice to call objects from outer scope like that. i'd suggest to use dict magic methods:
class MyClass:
def __init__(self):
self.one = "Test"
self.two = "Plop"
def __getitem__(self, parameter):
return getattr(self, parameter, None)
def __setitem__(self, parameter, value):
return setattr(self, parameter, value)
my_obj = MyClass()
parameter = "x"
print(my_obj[parameter])
my_obj[parameter] = "test"
print(my_obj.x)
You need to use getarttr():
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Use class
myObject = myClass()
# Define function
def myFunction(parameter):
print(getattr(myObject, parameter))##### This line is currently possible.
# Use function
myFunction("one")

How to use Mock to replace an instance variable without a getter method in Pytest

I am trying to write a test for a method of class "Process" like this:
[main.py]
class Process:
def run(self):
p = Print()
if p.get_foo() is True:
p.print_hoge()
class Print:
def __init__(self):
# I would like to replace this variable to use mock
self.foo = True
# I would not like to declare
def get_foo(self):
return self.foo
def print_foo(self):
print(self.foo)
Here is my test code.
import main
import pytest
from pytest import mark
def test_run(mocker):
test = mocker.patch("main.Print.print_hoge")
mocker.patch("main.Print.get_foo", return_value=False)
p = main.Process()
p.run()
test.assert_called()
As you know, I change the value True "self.foo" to False use "mocker.patch" for "Print.get_foo".
It would seem like not simple as I replace the value "self.foo" directly like mock an instance variable.
I would not like to declare a method "get_foo".
Is there any better way to meet what I want to do?

Setting class variable

I have noticed the following in setting a class variable:
from ingest.models import WBReport
wb=WBReport()
wb.date = '2019-01-09'
The above does not set the date for the class. For example, calling this method, it prints None:
#classmethod
def load_asin(cls):
print cls.date
However, if I add another method to set that variable it does work. For example:
#classmethod
def set_date(cls, date):
cls.date=date
from ingest.models import WBReport
wb=WBReport()
wb.set_date('2019-01-09')
Why does the first method (wb.date=X)not work but the second one (wb.set_date(X)) does?
Instance variables and class variables exist separately. wb.date = '2019-01-09' sets an instance variable on the object wb, not the class variable WBReport.date, which is what the class method set_date sets.
The call to the class method is roughly equivalent to WBReport.date = '2019-01-09'.

Python Variables across Class functions - how to call them?

Instead of using a global variable, I'm trying to make an instance of a variable in a class, as it seems to be best practice. How do I reference this variable across other functions in the class? I would have thought that Test.running_sum would work or at least running_sum in test_function, but I'm not having any luck with either. Thanks very much!
class Test:
def __init__(self):
self.root = None
running_sum = 0
def test_function(self):
print(Test.running_sum)
return
x = Test()
x.test_function()
Error:
Traceback (most recent call last):
File "so.py", line 1, in <module>
class Test:
File "so.py", line 10, in Test
x = Test()
NameError: name 'Test' is not defined
Use self parameter provided in the method signature.
Note that what you wrote is not a method, but an external function using class Test. To write a method of Test, the def should be at one level of indentation inside class Test as following:
class Test:
def __init__(self):
self.running_sum = 0
def test_function(self):
print(self.running_sum)
There are several things to add if you want an explanation behind this "best practice".
Assuming you write the following code:
class Test:
numbers = []
def add(self, value):
self.numbers.append(value)
The Test.numbers list is instantiated once and shared accross all instances of Test. Therefore, if 2 different instances add to the list, both act on the same list:
a = Test()
b = Test()
a.add(5)
b.add(10)
assert a.numbers == b.numbers == Test.numbers
When creating instance variables in the __init__ function, __init__ will be run at each instantiation, and therefore, the list will no longer be shared because they will be created for each individual instances.
class Test:
def __init__(self):
self.numbers = []
def add(self, number):
self.numbers.append(number)
a = Test()
b = Test()
a.add(5)
b.add(10)
assert a != b
As an object attribute: each object gets its own.
Test is the class; self is the Test object that invoked the method.
class Test:
def __init__(self):
self.root = None
self.running_sum = 0
def test_function(self):
self.running_sum += 1
print(self.running_sum)
return
x = Test()
y = Test()
x.test_function()
y.test_function()
Output:
1
1
As a class attribute: all objects share the same variable.
self.__class__ is the class of the invoking object (i.e. Test).
class Test:
running_sum = 0
def __init__(self):
self.root = None
def test_function(self):
self.__class__.running_sum += 1
print(self.__class__.running_sum)
return
x = Test()
y = Test()
x.test_function()
y.test_function()
Output:
1
2
how do I reference this variable across other functions in the class
Several things I see wrong here. First of all, you are calling running_sum on the class itself which doesn't make sense since you are declaring running_sum as an attribute of an instance of Test. Second, from the way you formatted your question, it seems that test_function is outside of the class Test which doesn't make sense since you are passing self to it, implying it is an instance method. To resolve you could do this:
class Test:
def __init__(self):
self.running_sum = 0
def test_function(self):
print(self.running_sum)
Then again this also is weird... Why would you need a "test_function" when you can simply test the value of running_sum by simply doing:
x = Test()
x.running_sum
In your __init__ function, you've created a local variable. That variable will no longer exist after the function has completed.
If you want to create a variable specific to the object x then you should create a self.running_sum variable
class Test:
def __init__(self):
self.root = None
self.running_sum = 0
def test_function(self):
print(self.running_sum)
If you want to create a variable specific to the class Test then you should create a Test.running_sum variable.
class Test:
running_sum = 0
def __init__(self):
self.root = None
def test_function(self):
print(Test.running_sum)

Is there a python construct that is a dummy function?

Is there a python construct that corresponds to a function taking no argument, doing nothing and returning nothing ? Something similar to object None but that would be a function instead of an object ?
The context
I want to define a class where the constructor gets a function as an argument and references it to a class attribute. Upon instanciation, the user decides whether he/she wants that function to be an actual function which he/she defines him/herself or leave the default which is to call a dummy function which does nothing.
Here is what I have now :
def sayHello():
print("hello world !")
def doNothing():
pass
class myClass:
def __init__(self, myFunc):
self.doIt = myFunc
myInstance = myClass(sayHello)
myInstance.doIt()
myInstance = myClass(doNothing) # Works but requires defining function doNothing()
myInstance.doIt()
#myInstance = myClass(None) # Returns error "'NoneType' object is not callable"
myInstance.doIt()
How about lambdas?
myInstance = myClass(lambda:None)
Sure you can pass is as default to your __init__ function:
class myClass:
def __init__(self, myFunc = lambda:None):
self.doIt = myFunc
This should work:
class myClass:
def __init__(self, myFunc = lambda : None):
self.doIt = myFunc
myInstance = myClass()
I used the following:
a=lambda:None
a()
print a()
The latter line prints None.
This worked for me:
def none(function=True):
if function==True:
return None
else:
function()

Categories

Resources