Simple update class instance - python

I would like to create a very simple class in Python such that, starting from an initial list of elements [3,7,2,7,81], an other list of numbers can be added, in this case a single element 40. Here is my solution:
class Add_elements:
def add(self, elements):
list = [self.list,elements]
return list
add_elements = Add_elements()
add_elements.add([3,7,2,7,81])
add_elements.add([40])
This should return something like:
[[3,7,2,7,81],40]
The issue with this is that the list of elements is reset every time, there is no memory of the previous elements added. Any solution?

You probably need an initialiser to initialise self.list:
class Add_elements:
def __init__(self):
self.list = None
def add(self, elements):
if self.list is None:
self.list = elements
else:
self.list = [self.list,elements]
return self.list
This will make list an attribute of Add_elements - part of its state. And when you call add, it changes that state.
EDIT:
If you want to remove the square brackets when calling add, you can do something like this:
def add(self, *elements):
if self.list is None:
self.list = list(elements)
else:
self.list = [self.list,list(elements)]
return self.list

Related

Referencing other objects of same class in a method of a class in Python

I am new to programming and learning Python. Right now I am trying to figure out howto write a value to another object of the same class inside of a method definition inside the class. I mean something like this:
class myClass:
def __init__(self, attribute, lst = True):
self.attribute = attribute
if lst is True:
self.lst = []
def add_amount(self, amount):
self.lst.append(dict(Amount = amount))
def total:
self.total = []
for each in self.lst:
self.total.append(each.get("Amount"))
self.total = sum(self.total)
#def transfer(self, amount, attribute):
#here I would like to be able to add
#a value (for example self.total) to
#the lst [] of a different instance of
#this class
firstInstance = myClass("First")
secondInstance = myClass("Second")
firstInstance.add_amount(10)
firstInstance.add_amount(20)
##firstInstance.transfer(15, "Second")
#How can I write the transfer
#function so that it will add
#the value of the first argument
#to the empty list of the instance
#object with the attribute "Second"
#(in this case secondInstance)?
How do I have to program that? I hope I explained my problem in an understandable way, hope you guys can help me! Thanks in advance! :)
Kind regards
You would have to pass the secondInstance as an argument to your transfer function. You could potentially do something like this:
class myClass:
def __init__(self, attribute, lst = True):
self.attribute = attribute
if lst is True:
self.lst = []
def add_amount(self, amount):
self.lst.append(dict(Amount = amount))
def subract_amount(self, amount):
# TODO
pass
def total:
self.total = []
for each in self.lst:
self.total.append(each.get("Amount"))
self.total = sum(self.total)
def transfer(self, amount, other):
self.subtract_amount(amount)
other.add_amount(amount)
firstInstance = myClass("First")
secondInstance = myClass("Second")
firstInstance.add_amount(10)
firstInstance.add_amount(20)
firstInstance.transfer(15, secondInstance)

how to check if the attribute of an instance is member of a queue in O(1)?

I'm trying to design a Queue data structure with python 3.6
The queue has the aim to keep track node objects with these attributes:
class node(object):
def __init__(self, state, parent):
self.state = state
self.parent = parent
I want avoid to incorporate nodes with the same state in the queue. So I design the following queue:
class queue(object):
def __init__(self):
self.list = []
self.explored = set()
def insert(self, element):
self.list = [element] + self.list
self.explored.add(str(element.state))
return self.list
def pop(self):
oldest_element = self.list.pop()
self.explored.remove(str(oldest_element.state))
return oldest_element
def empty(self):
return len(self.list) == 0
def check_member(self, other):
return other in self.explored
In order to check if a state of a node is in the queue, I use the check_member method with the attribute state as a string type to see if is contained in the set with all the string state of the members. But this is still slowly.
So it is possible to check if an instance has the same attribute of another instance that could differ in other attributes? For example, two nodes, same state attributes but different parents attributes.
How can keep the order of the elements and still checking if some element is in the queue in O(1) without using the additional explored set?
You need a set/dict type object to achieve O(1) contains-check complexity. The easiest would be to use an OrderedDict as your underlying data container. Use state as key and the node as the value. That way, the states are enforced to be unique, and the order is maintained nonetheless:
from collections import OrderedDict
class queue(object):
def __init__(self):
self.q = OrderedDict()
def insert(self, element):
s = str(element.state)
if s not in self.q:
self.q[s] = element # adds to the end
def pop(self):
return self.q.popitem(0)[1] # returns the node from beginning
def empty(self):
return not self.q
def check_member(self, element):
return str(element.state) in self.q

Python: How to sum up all elements from a list in the CLASS

class Neuron:
def __init__(self, inbound_neurons=[], label=''):
self.label = label
self.inbound_neurons = inbound_neurons
self.outbound_neurons = []
self.value = None
for n in self.inbound_neurons:
n.outbound_neurons.append(self)
def forward(self):
raise NotImplemented
class Input(Neuron):
def __init__(self):
Neuron.__init__(self)
def forward(self, value=None):
if value is not None:
self.value = value
class Add(Neuron):
def __init__(self, *inputs):
Neuron.__init__(self, inputs)
def forward(self):
for n in self.inputs:
self.value = self.value + n
Add() is the subclass of class Neuron, I have met some difficulties to use loop to add all the elements of the inputs array.
class Add(Neuron):
def __init__(self, *inputs):
Neuron.__init__(self, inputs)
def forward(self):
self.value = 0
for n in self.inbound_neurons:
self.value = self.value + n.value
return(self.value)
The function 'forward' in Class Add has a loop to sum all elements of inbound_neurons.
Firt off this line of code should be:
for n in self.inbound_neurons:
self.outbound_neurons.append(self)
self.inputs was never defined in your Class. In order to loop through the inputs, you'd have to have:
def __init__(self, *inputs):
self.inputs = inputs
Neuron.__init__(self, inputs)
However, it looks like inputs would be a list with two items, another list and maybe a string in it. These will not concate together. It looks like instead you want to sum the total of self.inbound_neurons.
It's not related to your question, but VERY important: you should NOT use mutable data types (as list) for function/method defaults.
Your code should be updated like this:
class Neuron:
def __init__(self, inbound_neurons=None, label=''):
self.inbound_neurons = inbound_neurons or []
# ...
Why you should do this way is explained here: "Least Astonishment" and the Mutable Default Argument

How to iterate through instances in a tree?

I have a problem with a self-written tree class in python:
class Tree:
def __init__(self, parent=0, value=0):
self.value = value
self.parent = parent
def __iter__(self): return self
def next(self):
tmp = self.value
try:
self.parent = self.parent.parent
self.value = self.parent.value
except AttributeError:
raise StopIteration
return tmp
def sum(self):
list_ = [item for item in self]
print list_
return sum(list_)
Actually, the "tree" is not fully written, but the current problem blocks further progress.
The structure has only two instance variables (value, parent).
I would like to sum values from the current instance to the first parent with iterators (if it is all together possible). The sum method is used for that (additional list_ variable is unnecessary, but helps further to explain the problem).
When running a test case
parent = Tree()
child = Tree(parent=parent, value=8)
child2 = Tree(parent=child,value=10)
print child2.sum()
I obtain the following:
[10]
10
Please, could anybody explain why the list of values contains only one number though it should look like [10,8]? Seems the problem is in the implementation of iter and next, but I can't understand how to repair the solution.
Thank you in advance.
I'm not sure you can call this a Tree. One would expect parent node(s) and multiple leaf nodes, and not just a linear connection of objects.
See: A general tree implementation?
On another note, if you want to implement a linkedlist, suggestions made in the comment to your question by Barny should be considered and as well, you can give an eye to: Python Linked List
Coming to your current implementation, you'll need some sort of loop, to walk from the current child node up until the head parent node. And when the next parent attribute is not found, stop the iteration. The following puts the logic in the __iter__ method of the class, which is now a generator function:
class Tree:
def __init__(self, parent=None, value=0):
self.value = value
self.parent = parent
def __iter__(self):
_parent = self.parent
yield self.value
while True:
try:
yield _parent.value
_parent = _parent.parent
except AttributeError:
break
def sum_from_node(self):
list_ = [item for item in self]
print list_
return sum(list_)
Demo:
parent = Tree()
child = Tree(parent=parent, value=8)
child2 = Tree(parent=child,value=10)
child3 = Tree(parent=child2,value=4)
print child3.sum_from_node()
# [4, 10, 8, 0]
# 22
Here you go:
class Tree:
def __init__(self, parent=None, value=0):
self.value = value
self.parent = parent
def __iter__(self):
yield self.value
root = self
while root.parent is not None:
yield root.parent.value
root = root.parent
raise StopIteration
def tree_sum(self):
return sum(list(self))
parent = Tree()
child = Tree(parent=parent, value=8)
child2 = Tree(parent=child,value=10)
I've changed the default parent value to None.
for i in child2:
print(i)
10
8
0 # 0 is here because the parent value is 0 by default.

Can I use a class method to set attributes of the class in Python?

I have a class with certain attributes.
I would like to define a method which sets other attributes based on the ones that have already been set. Something like this:
class Test:
def __init__(self, name):
self.name = name
self.list = []
max = None
def get_max(self)
self.max = max(list)
This doesn't work. I have a feeling I am doing something very wrong but I can't work out what. Please someone put me out of my misery.
Updated code gives me an Attribute error:
class Test:
def __init__(self, name):
self.name = name
self.lst = []
self.mx = None
def get_max(self)
self.mx = max(self.lst)
When I call the method, no exceptions are returned, but the self.mx attribute are not updated.
>>>t = Test('testname')
>>>t.lst = [1,2,3]
>>>t.get_max
>>>t.name
'testname'
>>>t.lst
[1,2,3]
>>>t.mx
AttributeError: Test instance has no attribute 'mx'
It would be self.list to refer to the attribute, list is referring to the python builtin list.
You would need to do something like:
class Test:
def __init__(self, name,lst):
self.name = name
self.lst = lst
self.mx = None # use self to create an attribute
def get_max(self):
self.mx = max(self.lst)
You can also simply just call max on the list whenever you want to get the max, you don't need to create an attribute and method simply to return or get the max of the list.
You should simply return the max of the list in the method if you really wanted to use a method to get the max:
class Test:
def __init__(self, name, lst):
self.name = name
self.lst = lst
def get_max(self):
return max(self.lst)
t = Test("foo", [1,2,3,4])
print(t.get_max())
4
The design of your class really depends on what exactly you want to do in it but you don't getters or setters in python.
If you want to do something based on the max element in the list you don't need an attribute:
class Test:
def __init__(self, name,lst):
self.name = name
self.lst = lst
def some_meth(self):
if max(self.lst) > 2:
# do something

Categories

Resources