call variable in method within the same class - python

In this example code:
class new:
def __init__(self, list):
self.list = list
def math(self):
average = sum(self.list)/len(self.list)
total = sum(self.list)
return len(self.list)
def values(self):
return self.list
list = new([1,2,3,4])
is there a way to call the average and total variables in the math method without putting it in the return function (I want the math function to only return the length of the list)? I tried this:
list.math().average
but this gives an error. I want to be able to call the variables in one line. Any suggestions?

You can put them in instance attributes.
class new:
def __init__(self, l):
self.list = l
def math(self):
self.average = sum(self.list)/len(self.list)
self.total = sum(self.list)
return len(self.list)
def values(self):
return self.list
mylist = new([1,2,3,4])
mylist.math()
print(mylist.average, mylist.total)
BTW, don't use list as a variable name, it replaces the built-in function with that name.

try this:
class new:
def __init__(self, list):
self.list = list
def average(self):
return sum(self.list)/len(self.list)
def total(self):
return sum(self.list)
def get_length(self):
return len(self.list)
list = new([1,2,3,4])
list.average()
list.sum()
list.get_length()

You can use the global keyword:
class new:
def __init__(self, list):
self.list = list
def math(self):
global average
global total
average = sum(self.list)/len(self.list)
total = sum(self.list)
return len(self.list)
def values(self):
return self.list

Related

Keep getting the ID from items in a list which is in a class

class EditorState:
def __init__(self, content):
self.content = content
class Editor:
def __init__(self):
self.content = ""
def __str__(self):
return f'{self.content}'
def setContent(self, value):
self.content = value
def createContent(self):
return EditorState(self.content)
def restore(self, new_value):
self.content = new_value
def getcontent(self):
return self.content
class History:
def __init__(self):
self.history = []
def __repr__(self):
return self.history
def push(self, value):
self.history.append(value)
def remove(self):
my_list = self.history
my_list.pop()
last_index = my_list[-1]
return last_index
def getvalue(self):
my_list = self.history
return self.history
editor = Editor()
history = History()
editor.setContent("a")
history.push(editor.createContent())
editor.setContent("b")
history.push(editor.createContent())
editor.setContent("c")
history.push(editor.createContent())
editor.setContent("D")
history.push(editor.createContent())
editor.restore(history.remove())
print(history.getvalue())
print(editor.getcontent())
OUTPUT that I get when I check the Items in the list: [<main.EditorState object at 0x0000017B77360040>, <main.EditorState object at 0x0000017B773600D0>, <main.EditorState object at 0x0000017B77360130>]
The output I want: [a,b,c]
I've learned how to use the Memento pattern in java, and I wanted to try the pattern with python. I does work but the problem is that when I'm returning the last item from my list in the history class, so it keeps showing me its id not the value. It's the same when I print the list using the getvalue() method.
I've tried to use the magic methods sush as str or repr but it did'nt work, also I've tried to set the attribut to a variable but no results.
Fixed it :
class EditorState:
#change here
def returnContent(self,content):
return content
class Editor():
content = '' #change here
def __init__(self):
self.content = ""
def __str__(self):
return f'{self.content}'
def setContent(self, value):
self.content = value
def createContent(self):
return EditorState.returnContent(self,self.content) #Change here
def restore(self, new_value):
self.content = new_value
def getcontent(self):
return self.content
class History:
history = [] #change here
def __init__(self):
self.history = []
def __repr__(self):
return self.history
def push(self, value):
self.history.append(value)
def remove(self):
my_list = self.history
my_list.pop()
last_index = my_list[-1]
return last_index
def getvalue(self):
my_list = self.history
return my_list
editor = Editor()
history = History()
editor.setContent("a")
history.push(editor.createContent())
editor.setContent("b")
history.push(editor.createContent())
editor.setContent("c")
history.push(editor.createContent())
editor.setContent("D")
history.push(editor.createContent())
editor.restore(history.remove())
print(history.history) #change here
print(editor.getcontent())
Output:
This function (in 2nd pic below) returned an object of the class instead on the variable because init() functions return only empty/None datatype(This is a Rule and the arrow mark show what datatype is being returned), so it basically returned an object which was pushed into your list
Here you can see init() returns nothing.
Here you can see what datatype is being pushed into the list
Also try creating variables globally in a class to access them easily when needed anywhere.

Python, delete a list item from class method

I have my class.
I want to create a method inside to delete a list item by code attribute.
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
print("The code: {self.__code} was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
print(list)
lista.deleteitem(123)
How I can create a method who deletes the code that I send?
Regards
You can try this below :
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
# Logic for deletion
for obj in list:
if obj.code == code:
list.remove(obj)
print("The code: "+code+" was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
myclass = MyClass(None, None)
myclass.__deleteitem__(123)

Is it possible to create a list where types in it cannot be changed, but the value itself can?

I'm wondering if it exists a way to create a list where variables inside could be changed to other variables but exclusively if they are of the same type.
for instance
a=[0, 1.0, 'blabla']
a[0] = 0 # is possible
a[1] = 2. # is possible
a[2] = 'albalb' # is possible
a[0] = 1.2 # is not possible
a[1] = 'no' # is not possible
a[2] = 1 # is not possible
I cannot use tuple to do that because it is immutable.
My goal is to create a list where the number of value in it can vary, so append, insert and pop will be useful. I also want slicing available in order to select a part of the list.
At the end, the list will contain my own classes which describe neuronal models. I have different models possible, so different classes.
With the list, I would like to do what we can do with Lists but I don't want the type of a variable in the list to change, except if I insert a neuron at a position. In that case, every variable after that position is shifted too the right.
for instance:
class A():
def __init__(self):
self.A = 0
class B():
def __init__(self):
self.A = 1
class C():
def __init__(self):
self.A = 2
class D():
def __init__(self):
self.A = 3
MyList = [A(),B(),C()]
print([M.A for M in MyList])
#insert
MyList.insert(1,D())
print([M.A for M in MyList])
#slicing
MyList2 = MyList[1:3]
print([M.A for M in MyList2])
#replace if the variable is the same type that the variable of the list to replace
MyList[0] = A()
print([M.A for M in MyList])
#So this should not be possible
MyList[0] = B()
print([M.A for M in MyList])
I would like something really close from the List object, so I expected that it could already exist.
Solution 1 Wrap all methods which modify the list in-place and override __setitem__()
class RewritingLockedTypeList(list):
def __init__(self, original_list):
super().__init__(original_list)
self.types = [type(n) for n in original_list]
def __setitem__(self, key, value):
if self.types[key] != type(value):
raise TypeError(f"Value at index {key} should be {self.types[key]}!")
super().__setitem__(key, value)
def wrap_method(method_name):
orig_method = getattr(RewritingLockedTypeList, method_name)
def new_method(self, *args, **kwargs):
result = orig_method(self, *args, **kwargs)
self.types = [type(n) for n in self]
return result
setattr(RewritingLockedTypeList, method_name, new_method)
for method in ["append", "clear", "extend", "insert", "pop", "remove", "reverse", "sort"]:
wrap_method(method)
Solution 2 Override all methods which modify the list in-place and override __setitem__() too
class LockedTypeList(list):
def __init__(self, original_list):
super().__init__(original_list)
self.types = [type(n) for n in original_list]
def __setitem__(self, key, value):
if self.types[key] != type(value):
raise TypeError(f"Value at index {key} should be {self.types[key]}!")
super().__setitem__(key, value)
def __delitem__(self, key):
del self.types[key]
super().__delitem__(key)
def append(self, thing):
self.types.append(type(thing))
super().append(thing)
def clear(self):
self.types.clear()
super().clear()
def extend(self, objects):
self.types.extend(type(o) for o in objects)
super().extend(objects)
def insert(self, idx, obj):
self.types.insert(idx, type(obj))
super().insert(idx, obj)
def pop(self, index=0):
self.types.pop(index)
super().pop(index)
def remove(self, value):
idx = self.index(value)
self.pop(idx)
def reverse(self):
self.types.reverse()
super().reverse()
def sort(self, key=lambda n: n, reverse=False):
super().sort(key=key, reverse=reverse)
self.types = [type(n) for n in self]
The second solution is longer, but faster for long lists.
Usage
a=LockedTypeList([0, 1.0, 'blabla'])
But you maybe should think about using a class and properties with type checking instead of this ugly list.

Accessing class methods inside another class at same scope

Trying to get a work around for getting access to a class method in another class while being inside a class. Code below will probably explain my goal.
class Access(object):
def __init__(self):
pass
def select(self, value):
Store.keep(value)
class Store(object):
def __init__(self):
self.store_value = 0
def keep(self, value):
self.store_value = value
x = Access()
y = Store()
x.select(10)
y.store_value
##Want the output of 10
I don't see any way to do what you want without Access having a reference to a Store object.
The closest thing you can do is
class Access(object):
def __init__(self):
pass
def select(self, value):
Store.keep(value)
class Store(object):
#classmethod
def keep(cls, value):
cls.store_value = value
x = Access()
y = Store()
x.select(10)
print y.store_value #will print 10
#but
z = Store()
print z.store_value #will print 10 too
Where store_value is shared by all instances of Store.
You could pass an instance to select also and use Store.keep(inst, value):
class Access(object):
def __init__(self):
pass
def select(self, inst, value):
Store.keep(inst, value)
class Store(object):
def __init__(self):
self.store_value = 0
def keep(self, value):
self.store_value = value
x = Access()
y = Store()
x.select(y, 10)
print(y.store_value)
10

How to implement selection sort using forward iterators?

I'm working on a homework assignment where I shall implement selection sorting using forward iterators for both python lists and linked lists(single).
Here are some codes I have for iterators:
from abc import *
class ForwardIterator(metaclass=ABCMeta):
#abstractmethod
def getNext(self):
return
#abstractmethod
def getItem(self):
return
#abstractmethod
def getLoc(self):
return
#abstractmethod
def clone(self):
return
def __eq__(self, other):
return self.getLoc() == other.getLoc()
def __ne__(self, other):
return not (self == other)
def __next__(self):
if self.getLoc() == None:
raise StopIteration
else:
item = self.getItem()
self.getNext()
return item
class ForwardAssignableIterator(ForwardIterator):
#abstractmethod
def setItem(self, item):
"""Sets the item at the current position."""
return
class PythonListFAIterator(ForwardAssignableIterator):
def __init__(self, lst, startIndex):
self.lst = lst
self.curIndex = startIndex
def getNext(self):
self.curIndex += 1
def getItem(self):
if self.curIndex < len(self.lst):
return self.lst[self.curIndex]
else:
return None
def setItem(self, item):
if self.curIndex < len(self.lst):
self.lst[self.curIndex] = item
def getLoc(self):
if self.curIndex < len(self.lst):
return self.curIndex
else:
return None
def clone(self):
return PythonListFAIterator(self.lst, self.curIndex)
The LinkedListFAIterator is similar to PythonListFAIterator, plus getStartIterator, and __iter__ method.
I don't know how I can write codes to implement selection sort with one paraemter, a FAIterator (the forward iterator). Please help me. I know I shall find the minimum element and put it at the beginning of the list. I also know that I shall use the clone method to create multiple iterators to keep track of multiple locations at once. But I don't know how to write the code.
Please give me some hints.

Categories