I'm trying to create a python class that can work as a list of lists. However, all I've managed to develop so far is,
class MyNestedList(list):
...
I'm aware that the above code will work as,
my = MyNestedList()
my[0] = 1
...
But I want my class to work as,
my[0][0] = 1
...
Will anyone please guide me further?
EDIT: I want the class to pass as a type for the deap framework, as my individual. I can't pass list of lists as my type as it would break my structure.
Here is an example. You have to initialize the nested list with enough elements, or you'll get index errors.
class NestedLst(object):
def __init__(self, x, y):
self.data = [[None]*y]*x
def __getitem__(self, i):
return self.data[i]
nlst = NestedLst(2, 2)
nlst[0][0] = 10
print nlst[0][0]
Related
Say I would like to create a python class that behave as array of another class. While the __init__ is called, it recognizes itself as an array (iterable); however, when I call it again through some other method, or even call by the index, the object becomes non-iterable. I wonder which part I got it wrong, or perhaps, there's DO and DON'T for python class?
Last but not least, this is an attempt to simplify one object type to another (trying to cast from one class to another). Perhaps the code below will give a better clarification.
The example is below:
Say I have an object FOO
FOO.name = "john"
FOO.records[0].a = 1
FOO.records[0].b = 2
FOO.records[1].a = 4
FOO.records[1].b = 5
And I create a python class
class BAR:
__init__(self, record):
self.a = int(record.a)
self.b = int(record.b)
and another class which would like to store BAR class as array
class BARS:
__init__(self,bars):
self = numpy.array([]) # regardless the array type whether python native or Numpy it does not work
for item in bars:
self = numpy.append(self, BAR(item))
so what I would expect this code to perform would be that if I call
A = BARS(FOO.records)
I would get an iterable A. But this does not work, though if I call SELF in BARS __init__, it would see SELF as iterable object.
If one should not expect python class to behave in this manner, at least I hope you could help pointing me out, what would be the alternative logical and pythonic way to achieve it.
Perhaps answering my own question after a hint from comment above would be good.
It turns out that assining self in class as itself is a DON'T (silly me trying to get a shortcut).
To achieve an iterable class, one would require __iter__ method alongside with __next__, and __getitem__ to fulfill (maybe some others methods as well, but let's stick to these three for now).
So, the code above should look like this
class BARS:
def __init__(self, records):
self.records = [] # Use list for simplicity
for record in records:
self.records.append(BAR(record))
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n < len(self.records):
result = self.records[self.n]
self.n += 1
return result
else:
raise StopIteration
def __getitem__(self, key):
return self.records[key]
Eventually, this will yield a iteration and index accessible object.
I get a Runtime error (maximum recursion) when I execute the following code.
I'm trying to generate a list of instances; then I would like to print each one. I'm not sure what's going on here.
Anyway, what is the correct way to access each instance from the instance list?
I do realize I'm using a string of digits to name the instances and this is not cool. But say each number on the list is associated with a bunch of information. Then having attributes for each could make things accessible. I tried using a dict but I end up with nested dicts and I just didn't like it.
Thanks in advance.
class MyClass(object):
def __str__(self):
stuff= str(self)
return stuff
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass() for i in mylist]
print inslist[0]
The problem is in your __str__. If you call str(self), it will call itself. I think you meant was this:
class MyClass(object):
def __init__(self, i):
self.i = i
def __str__(self):
return str(self.i)
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass(i) for i in mylist]
print inslist[0]
I have this example code
my_list = ["a","b","c","d"]
class A:
def __repr__(self):
return ', '.join(my_list)
def add(self, num):
my_list.append(num)
class_list = []
for x in range(5):
class_list.append(A())
class_list[x].add("class_%s" % (x))
print class_list[x]
The non-example code of mine is more complicated, but the idea is that I have multiple instances of the classes off doing a "thing". The global my_list is utilized across all instances. When certain logic is met within a class, that instance will modify the list. The rest of the classes will utilize that list to perform their logic as well. Any instance can add to the list, and all instances should be able to utilize the updated value.
Now in this example, the my_list is shared, but is this the correct way to do it?
A class attribute is usually better than a global, because then they're just sharing it with each other, rather than with everyone in the world.
To do that, move the my_list = ["a","b","c","d"] line under the class A:, and change every reference to my_list to self.my_list or A.my_list:
class A(object):
shared_list = []
def add(self, num):
self.my_list.append(num)
However, an instance attribute is often even better. If you assign the same list to a bunch of different variables, it's still just one list; changing it affects all those variables. So, you can do something like this:
class A(object):
def __init__(self, shared_list):
self.shared_list = shared_list
def add(self, num):
self.shared_list.append(num)
Now it's up to the code that uses the A objects to decide whether to give them all the same list. You can even create 20 instances that share one list, and 10 that share a different one:
list1 = []
group1 = [A(list1) for _ in range(20)
list2 = []
group2 = [A(list2) for _ in range(10)
The question is whether the caller, or the A class, or nobody at all is the one who should be making the decision of how "shared" the list is. The answer is different for different applications, so it's hard to give an answer for an abstract example with names like A and my_list.
I've looked for quite a while but couldn't find a proper answer to my question:
I have a class containing methods which operate on arrays and I want dynamically create methods with a similar name in another class with a modified output.
I've got something like this so far, can anyone guide me ?
Thanks
Class A():
def__init__(self,array):
self.data = array
def method1(self,*args):
newarray = whatever(self.data,*args)
return newarray
def method2(self,*args):
newarray = whatever2(self.data,*args)
return newarray
I want to be able to use those methods to generate new ones in a more complex class, say:
class B(C): #inherits from C
def __init__(self,[arg1,array]):
#initialize from parent class
C.__init__(self,[arg1,array])
#create new methods for this class using same name
methodnames = [element for element in dir(A) if element[0] != '_']
for methodname in methodnames:
##following works but this is not the output I want here
#self.__dict__[methodname] = getattr(A(array),methodname)
#following doesn't work... at least not as I expect it to
#case1
#self.__dict__[methodname] = [arg1,getattr(A(array),methodname)]
#case2
self.__dict__[methodname] = list([arg1,getattr(A(array),methodname)])
a = array
#following returns a list of [arg1, method] but what I really want is [arg1,newarray]
C([arg1,array]).method1(*args)
OK, so let's try to be clearer:
Class A contains filters, takes an array and applies filter as method, returns filtered data.
Class filters()
def__init__(self,array):
self.data = array
def filter1(self,*args):
newarray = median(self.data,*args)
return newarray
def filter2(self,*args):
newarray = gaussian(self.data,*args)
return newarray
...
In another module, I have class SpecialData, which operates on a list of x,y data (where x and y are iterables, i.e. lists, arrays...). So something like
Class SpecialData():
def __init__(self,[x,y]):
self.data = [x,y]
def power(self,power):
ypow = self.data[1]**power
return [x,pow]
def porod(self):
return [x**4,x**4*y]
....
Now, what I want is to add the filter methods contained in class filters to class SpecialData.
I could, of course do this by re-coding all filters with proper format for SpecialClass. but what I really want, is that each time a new filter is added to class filters, to make it available at runtime in class SpecialData without having to re-hard code the new filter.
So, not being very clever, I tried to read the list of available filters in class filters by:
import filters
filternames = [element for element in dir(filters) if element[0] != '_']
for fitlername in filternames:
generate_filters_in_class_SpecialClass
How do I do this properly ?
I found a number of posts related to this, some using super(), others using SpecialData.dict or even setattr. Since the 2nd seemed more understandable to me, I focused on this one and came up with:
import filters
Class SpecialData():
def __init__(self,[x,y]):
self.data = [x,y]
filternames = [element for element in dir(filters) if element[0] != '_']
for fitlername in filternames:
self.__dict__[fitlername ] = [self.data[0],getattr(filters(self.data[1]),fitlername)]
Of course, this doesn't work, because the list is not callable. If I change the last line to :
self.dict[fitlername ] = list([self.data[0],getattr(filters(self.data[1]),fitlername)])
it returns the method as the 2nd element, rather than the result.
Note that the following works, but this is not what I want...
self.dict[fitlername ] = getattr(filters(self.data[1]),fitlername)
Hope this is clearer now...
I think you are trying to make an advanced use of Python without using/knowing its advanced features, like you are borrowing techniques from another language.
This is not a criticism, but you should have a look on Python tutorial, Python introspection or metaclasses.
I think that if you just complete your knowledge on Python functions you will be easily able to solve your problem in a much simpler way.
Rather than generating a proposed solution, you should make it clearer what you are trying to achieve. Class A is a clear example of the starting point; please post an example of your desired ending point, e.g.
Class B():
def__init__(self,array):
self.data = array
def method1(self,*args):
newarray = ComplexWhatever(self.data,*args)
return newarray
def method2(self,*args):
newarray = EvenBiggerWhatever2(self.data,*args)
return newarray
a = A(input_array)
b = B(input_array)
print(a.method1(args))
print(b.method1(args))
What isn't clear is how you want to "dynamically generate" the new function "ComplexWhatever()" instead of writing the function by hand.
I'm trying to make a class that will get a list of numbers then print them out when I need. I need to be able to make 2 objects from the class to get two different lists. Here's what I have so far
class getlist:
def newlist(self,*number):
lst=[]
self.number=number
lst.append(number)
def printlist(self):
return lst
Sorry I'm not very clear, I'm a bit new to oop, can you please help me cos I don't know what I'm doing wrong. Thanks.
In Python, when you are writing methods inside an object, you need to prefix all references to variables belonging to that object with self. - like so:
class getlist:
def newlist(self,*number):
self.lst=[]
self.lst += number #I changed this to add all args to the list
def printlist(self):
return self.lst
The code you had before was creating and modifying a local variable called lst, so it would appear to "disappear" between calls.
Also, it is usual to make a constructor, which has the special name __init__ :
class getlist:
#Init constructor
def __init__(self,*number):
self.lst=[]
self.lst += number #I changed this to add all args to the list
def printlist(self):
return self.lst
Finally, use like so
>>> newlist=getlist(1,2,3, [4,5])
>>> newlist.printlist()
[1, 2, 3, [4,5]]
You should use "self.lst" instead of "lst". Without the "self", it's just internal variable to current method.