python class method different from non-class function - python

I suspect that the action of the class methods on some set of variables is different from the action of the corresponding non-class function. Here is an example. Assume we have a set of variables: A, B, C and we want to modify them over time according to some algorithms. There are 2 possible implementations:
1) with class:
class variables:
def __init__(self):
self.A = 0.0
self.B = 0.0
self.C = 0.0
def changeA(self):
self.A = some function of A, B and C
def changeB(self):
self.B = some function of A, B and C
def changeC(self):
self.C = some function of A, B and C
And call many times:
ob = variables()
i = 0
while i<N:
ob.changeA()
ob.changeB()
ob.changeC()
i = i + 1
2) without classes
A, B, C = 0.0, 0.0, 0.0
def changeA(A,B,C):
A = some function of A, B and C (same as in class method)
return A
def changeB(A,B,C):
B = some function of A, B and C (same as in class method)
return B
def changeC(A,B,C):
C = some function of A, B and C (same as in class method)
return C
And call many times:
i = 0
while i<N:
A = changeA(A,B,C)
B = changeB(A,B,C)
C = changeC(A,B,C)
i = i + 1
In my opinion, the results of 2 approaches must be identical. The only difference is the namespace where the variables A, B and C are known (either local in object or globally for function implementation - but in both cases method have access to required variables). However, the results of two methods seem to be different. So my question is there anything i'm missing in class method implementation/understanding?
To be more specific, an example of implementation of methods changeA:
As a class method:
(... inside the class)
def changeA(self):
self.A = self.A + 2.0*self.B - 3.0*self.C*(self.B-self.A)
As a function:
def changeA(A,B,C):
A = A + 2.0*B - 3.0*C*(B-A)
return A

I'd say that in the 1st case, each time a new variables instance is created the values of A, B and C are reset, which is not the case in the 2nd approach where they seem to be global. Depending on how you use these instances, results can be impacted.
EDIT: after OP's question in comment, here is how to define class variables:
>>> class Variables:
A = 0.0
B = 0.0
C = 0.0
def changeA(self):
Variables.A = Variables.A + Variables.B * Variables.C
>>> v = Variables()
>>> v.changeA()
>>> v.A
0.0
>>> Variables.A
0.0
>>>
As you can see, no need to define an __init__ method any longer. And you can access these variables by either instance.A or class.A.

Related

In Python is there any way to define the default value of a parameter to be based in other given parameter?

I'm trying to do something like this:
def some_func(a, b = a):
if not a:
return b
return a + b + some_func(a-1)
so, because it's called recursively, I can't get b inside the function, I want b to be the value of a at the first time the function is called. But I don't know how to do this because the way I tried it can't reach the value of a in the default assignment
would something like this work?
a = 1
b = 2
def some_func(a, b):
if not a:
return b
return a + b + some_func(a-1, b)
some_func(a, b)
I've reached what I wanted doing
def some_func(a, b = None):
if b is None:
b = a
if not a:
return b
return a + b + some_func(a-1, b)
this way it only assigns b at the first time the function is called, like if some_func(7) is called, then b will be 7 until the end of the recursion, thanks for the comments y'all

Optional parameter for class changes in all instance of the class [duplicate]

This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 2 years ago.
I do the following:
class Test:
def __init__(self, a, b, c=[]):
self.a = a
self.b = b
self.c = c
t1 = Test(1,2)
t2 = Test(3,4)
t1.c.append(5)
t2.c
Out: [5]
t1 == t2
Out: False
t1.c == t2.c
Out: True
Why is changing property c of instance t1 also changing the property c of instance t2?
What can I do to avoid this behaviour?
Thank You for your answers
This is just a reposting of O O's comment as an answer.
The argument c=[] is defined once at compile time, so all Test objects will share the same array. You need to set it to a None value and then test if c is None and create a new array:
class Test:
def __init__(self, a, b, c=None): # at compile time.
if c is None:
c = [] # runs when the object is created.
self.a = a
self.b = b
self.c = c
Both instances were pointing to the same list. Your keyword argument has mutable object as the default value, this is generally not recommended and you should either use immutable objects or simply a None. This issue may also happen if you use a dictionary.
Here is a fix for this particular issue:
class Test:
def __init__(self, a, b, c=None):
self.a = a
self.b = b
self.c = c or []
t1 = Test(1,2)
t2 = Test(3,4)
t1.c.append(5)
t2.c
Out: []

Same name for instance method and static method in python

I am writing some small library and I want to provide users two approaches for the same functionality, by instance method and static method. Here is a simplified example:
class ClassTimesAdd(object):
def __init__(self, a, b):
self.a = a
self.b = b
def TimesAdd(self, c):
return self.a * self.b + c
#staticmethod
def TimesAdd(a, b, c):
return a * b + c
print(ClassTimesAdd.TimesAdd(1, 3, 7))
ins = ClassTimesAdd(2, 5)
print(ins.TimesAdd(7))
And you can find that the earlier function will be overwritten and only the last one is valid. I'm wondering if there is some simple method that I can use to make the two approaches both work.

Changing Method called without new instance of Python Class

I'm new to Python OOP and for the purpose of this question I have simplified my problem to this:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
# some arbitrary change
return self.a + self.b
def subtract(self):
# some arbitrary change
return self.a - self.b
a = Foo(a=1, b=2).add()
b = Foo(a=1, b=3).subtract()
So I have an object, which has 2 methods which do different things, in order for me to get some output, I have created 2 separate instances of Foo as the value b has changed.
Is there a way for me to just dynamically set b and the obj.method() without just listing them one after the other? I.E: some sort of generic class that I can use to dynamically set the attributes and the methods that are present in the object? or is there anything built in I can use...
Edit
Here is another example:
class Foo:
def __init__(self, a, b):
self.a = list(a)
self.b = list(b)
def method1(self):.
# some arbitrary change in data
return self.a * 2
def method2(self):
return self.b + [5, 6, 4]
a = Foo(a=[1, 2, 3], b=[]).method1()
b = Foo(b=[1, 2, 3], a=[]).method2()
print(a)
print(b)
So here, the input list changes based on the method called, is there a way for me to package this up so I could feed just one instance some data and then it 'knows' that list a is for method1(), list b is for method2() - I want to use the word reflection but I feel like that might not be accurate.
Again I'm new to OOP so any advice is appreciated
class Foo:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
fo = Foo()
a = fo.add(1,2)
b = fo.subtract(1,3)
you don't need 2 instances of Foo to achieve this.
Just do something like this:
foo = Foo(a = 1, b = 2)
# Perform addition (now 'a' is 1 and 'b' is 2)
a = foo.add()
# Change 'b'
foo.b = 3
# Now perform subtraction (now 'a' is 1 and 'b' is 3)
b = foo.subtract()

c = a + b; How can I make c always reflect any changes made to a or b?

I am not sure the proper way to phrase this question. I would like to assign/bind some arithmetic (with references/pointers to other "subVariables") to a variable and have the value of the variable update if any of the contributing "subVariables" are updated.
>>> a = 1
>>> b = 2
>>> c = a + b
>>> c
3
>>> a = 2
>>> c
3
In the ideal situation c would have a value of 4 at the end of this code sample.
--
Additional information: I am generating the arithmetic randomly and would like to be able to nest these variables (ex: d = a + c would be the same as d = a + (a + b) where d would reflect any changes that happen to a or b)
What you want isn't possible with immutable built-in types like int. Because a and b are bound to immutable types (int), even if some hypothetical class preserved references to its inputs, those inputs never change (a can be rebound to a new value, but a would no longer have anything to do with the value it was previously bound to, and the class that aliased the old value of a would remain unchanged; it doesn't preserve a direct tie to a itself).
The only way this could possibly work is if a and b were of a mutable type where the contents could be updated or reassigned, and they had an overload of __add__/__radd__ that produced yet another class that stored references to instances of said mutable type and/or instances of itself (to allow the nested case). Either way, implementing such a suite of classes is way beyond the scope of a simple answer; I'd strongly recommend finding a different solution to your problem.
Make c as a function which returns a+b value
Simple numbers in Python are immutable references. You can't do it that directly.
You could create objects with that kind of behavior in various ways. Here's an approximation using simple function calls.
>>> a = 1
>>> b = 2
>>> def c():
return a + b
>>> c()
3
>>> a = 2
>>> c()
4
You can avoid the () at the cost of a dot by using __getattribute__
>>> class CallsAttrs:
def __getattribute__(self, attr):
return object.__getattribute__(self, attr)()
>>> Q = CallsAttrs()
>>> a = 1
>>> b = 2
>>> Q.c = lambda: a + b
>>> Q.c
3
>>> a = 2
>>> Q.c
4
And, of course, the lambdas can get the variables from Q too.
>>> Q.a = lambda: 1
>>> Q.b = lambda: 2
>>> Q.c = lambda: Q.a + Q.b
>>> Q.c
3
>>> Q.a = lambda: 40
>>> Q.c
42
You could also override the globals dict to work this way,
>>> class ThunkDict(dict):
def __getitem__(self, key):
return super().__getitem__(key)()
>>> exec("""
a = lambda: 1
b = lambda: 2
c = lambda: a + b
print(c)
a = lambda: -10
print(c)
""", ThunkDict())
3
-8
but it's not as interactive if you have to use exec.

Categories

Resources