Instance variable as function of other instance variables - python

Is it possible to define an instance variable in a class as a function of another? I haven't gotten it to work unless you redefine the "function instance variable" all the time.
Basically you could have a scenario where you have one instance variable that is a list of integers, and want to have the sum of these as an instance variable, that automatically redefines every time the list is updated.
Is this possible?
class Example:
list_variable = []
sum_variable = sum(list_variable)
def __init__(self, list_variable):
self.list_variable = list_variable
return
This will result in sum_variable = 0 unless you change it.
I understand that this is far from a major issue, you could either define sum_variable as a method or redefine it every time you change list_variable, I'm just wondering if it's possible to skip those things/steps.

Python offers the property decorator for a syntatically identical use of your example:
class Example:
list_variable = []
def __init__(self, list_variable):
self.list_variable = list_variable
return
#property
def sum_variable(self):
return sum(self.list_variable)
e = Example(list_variable=[10, 20, 30])
e.sum_variable # returns 60

Related

Passing an object to an object in a list of objects

I'm trying to create a list of objects (Called Super in this example) and pass an object to that object (Called Sub in this example).
However, whenever I do that, Python recognizes that each of the Super classes are individual objects, but the sub classes within are all the same. It looks like the one Sub object is the last one to be passed through and each one that gets passed through overwrites the previous.
The goal is that I would get the number back (0 - 4), but because they are all the same object, I just get the last one (4) back. What would be a solution or workaround?
driver.py
from Super import *
from Sub import *
class1 = []
class2 = []
for a in range(0,5):
class1.append(Sub(a))
for a in range(0,5):
class2.append(Super(class1[a]))
for a in range(0,5):
class2[a].printnumber()
Super.py
class Super:
def __init__(self, a):
global class1
class1 = a
def printnumber(self):
print(class1.getnumber())
Sub.py
class Sub:
def __init__(self, a):
global number
number = a
def getnumber(self):
return number
You may be confusing global variables with member variables. If each instance of a class should have its own copy of a variable, you should do it like this:
class Sub:
def __init__(self, a):
self.number = a
def getnumber(self):
return self.number
The self describes that you assign it to your object.
If you use global, the variable is shared over all instances. Generally you should avoid using global, since it is almost always possible to achieve the same thing in a significantly cleaner way!

Python: Getting value from calling function

In Python, is there a simple way for an invoked function to get a value from the calling function/class ? I'm not sure if I'm phrasing that right, but I'm trying to do something like this:
class MainSection(object):
def function(self):
self.var = 47 # arbitrary variable
self.secondaryObject = secondClass() # Create object of second class
self.secondaryObject.secondFunction(3) # call function in that object
and
class secondClass(object):
def secondFunction(self, input)
output = input + self.var # calculate value based on function parameter AND variable from calling function
return output
#Access self.var from MainSection
This might be my lack of knowledge about Python, but I'm having a hard time finding a clear answer here. Is the best way to do that just passing the variable I want in as another second parameter to the second class?
These are in separate files, if that makes a difference.
Is the best way to do that just passing the variable I want in as another second parameter to the second class?
Yes, especially if there's only a transient relationship between the objects:
class secondClass(object):
def secondFunction(self, input, var_from_caller)
output = input + var_from_caller # calculate value based on function parameter AND variable from calling function
return output
You can even pass around the whole object if you like:
class secondClass(object):
def secondFunction(self, input, calling_object)
output = input + calling_object.var # calculate value based on function parameter AND variable from calling function
return output
If the relationship is more permanent, you could consider storing references to the related objects in instance variables:
class MainSection(object):
def function(self):
self.var = 47 # arbitrary variable
self.secondaryObject = secondClass(self) # Create object of second class
self.secondaryObject.secondFunction(3) # call function in that object
...
class secondClass(object):
def __init__(self, my_friend):
self.related_object = my_friend
def secondFunction(self, input)
output = input + self.related_object.var # calculate value based on function parameter AND variable from calling function
return output
#Access self.var from MainSection

Performing Calculation on Objects in python class

I have a class in python that will need to perform calculations on objects which get their data from lists that loop though and add a new row from a csv every time.
How can I call the objects defined in __init__() into the calcA(), calcB(), calcC() methods to perform a calculation for every row stored in it and then write the results back into the object defined in Calculation without changing the data already stored in __init__?
I will then use the objects from __init__ and Calculation to write to columns in a csv
class CreateObjects():
def __init__(self, OjectID, ObjectPrice, ObjectNum, Objectzone, ObjectTicket, Multiplier):
self.OjectID= OjectID
self.ObjectPrice= ObjectPrice
self.ObjectTicket= ObjectTicket
self.ObjectNum= ObjectNum
self.Objectzone= Objectzone
self.Multiplier = Multiplier
def Calculation(self, A, B, C):
self.A = A
self.B = B
self.C = C
def calcA():
pass
def calcB():
pass
def calcC():
pass
Assuming that calcA() is a method, then it should have a first parameter (called self by convention). You can use that to access all properties / attributes of the class instance.
For example:
class CreateObjects:
...
def calcA(self):
# this will allways work, because '__init__()' is allways
# called before this method
print(self.OjectID)
# this will only work if the method 'Calculation()' was called
# before this, because otherwise 'A' will not be defined yet
print(self.A)

Python method/function chaining

In python, is it possible to chain together class methods and functions together? For example, if I want to instantiate a class object and call a method on it that affects an instance variable's state, could I do that? Here is an example:
class Test(object):
def __init__(self):
self.x = 'Hello'
#classmethod
def make_upper(y):
y.x = y.x.upper()
What I'm wanting to do is this:
h = Test().make_upper()
I want to instantiate a class object and affect the state of a variable in one line of code, but I would also like to be able to chain together multiple functions that can affect state or do something else on the object. Is this possible in python like it is in jQuery?
Yes, sure. Just return self from the instance methods you are interested in:
class Test(object):
def __init__(self):
self.x = 'Hello'
def make_upper(self):
self.x = self.x.upper()
return self
def make_lower(self):
self.x = self.x.lower()
return self
h = Test().make_upper()
print(h.x)
Output:
HELLO
Yes and no. The chaining certainly works, but h is the return value of make_upper(), not the object returned by Test(). You need to write this as two lines.
h = Test()
h.make_upper()
However, PEP-572 was recently accepted for inclusion in Python 3.8, which means someday you could write
(h := Test()).make_upper()
The return value of Test() is assigned to h in the current scope and used as the value of the := expression, which then invokes its make_upper method. I'm not sure I would recommend using := in this case, though; the currently required syntax is much more readable.

Python method changing self value (dict-inherited class) [duplicate]

I have a class (list of dicts) and I want it to sort itself:
class Table(list):
…
def sort (self, in_col_name):
self = Table(sorted(self, key=lambda x: x[in_col_name]))
but it doesn't work at all. Why? How to avoid it? Except for sorting it externally, like:
new_table = Table(sorted(old_table, key=lambda x: x['col_name'])
Isn't it possible to manipulate the object itself? It's more meaningful to have:
class Table(list):
pass
than:
class Table(object):
l = []
…
def sort (self, in_col_name):
self.l = sorted(self.l, key=lambda x: x[in_col_name])
which, I think, works.
And in general, isn't there any way in Python which an object is able to change itself (not only an instance variable)?
You can't re-assign to self from within a method and expect it to change external references to the object.
self is just an argument that is passed to your function. It's a name that points to the instance the method was called on. "Assigning to self" is equivalent to:
def fn(a):
a = 2
a = 1
fn(a)
# a is still equal to 1
Assigning to self changes what the self name points to (from one Table instance to a new Table instance here). But that's it. It just changes the name (in the scope of your method), and does affect not the underlying object, nor other names (references) that point to it.
Just sort in place using list.sort:
def sort(self, in_col_name):
super(Table, self).sort(key=lambda x: x[in_col_name])
Python is pass by value, always. This means that assigning to a parameter will never have an effect on the outside of the function. self is just the name you chose for one of the parameters.
I was intrigued by this question because I had never thought about this. I looked for the list.sort code, to see how it's done there, but apparently it's in C. I think I see where you're getting at; what if there is no super method to invoke? Then you can do something like this:
class Table(list):
def pop_n(self, n):
for _ in range(n):
self.pop()
>>> a = Table(range(10))
>>> a.pop_n(3)
>>> print a
[0, 1, 2, 3, 4, 5, 6]
You can call self's methods, do index assignments to self and whatever else is implemented in its class (or that you implement yourself).

Categories

Resources