def suffix(stng):
list = []
length = len(stng)
for i in range(length):
x = stng[i:length] ## This gives a Memory Error..See below
list.append(x)
return list
This piece of code is a part of my solution of a problem on interviewstreet.com but when i submit it i get a Memory error...i want to know how to correct it?
This is the traceback:
Original exception was:
Traceback (most recent call last):
File "/run-1342184337-542152202/solution.py", line 35, in
listofsuffix=suffix(var)
File "/run-1342184337-542152202/solution.py", line 13, in suffix
x=stng[i:length]
MemoryError
A MemoryError means you have consumed all your RAM. You are creating a list containing all trailing parts of an original string. If your original string is too long, you will consume a lot of memory.
One possibility is to use a generator to produce the suffixes one at a time instead of creating a list of all of them:
def suffixes(stng):
for i in xrange(len(stng)):
yield stng[i:]
If the caller of suffixes simply iterates over the result, you don't even have to change the caller. If you truly needed an explicit list, then you'll need a different solution.
"I need to return a list" -- This is highly unlikely. You just need to return an object which looks enough like a list to make it work.
class FakeList(object):
def __init__(self,strng):
self.string=strng
self._idx=0
def __getitem__(self,i):
return self.strng[:i]
def __len__(self):
return len(self.string)
def __iter__(self):
return self
def __contains__(self,other):
return other in self.string
def next(self):
if(self._idx<len(self)):
self._idx+=1
return self[self._idx-1]
else:
raise StopIteration
a=FakeList("My String")
print a[3]
print a[4]
for i in a:
print i
This creates an object which you can access randomly and iterate over like a list. It also will allow you to call len(my_fake_list). It doesn't support slicing, and a myriad of other methods pop, append, extend ... Which of those you need to add depends on which ones you use.
Related
I would like to get a list of indexes for SeqRecords that are in list f. I tried this:
for x in f:
ind = f.index(x)
print(ind)
But I get the error:
0
Traceback (most recent call last):
File "C:\Users\Adrian\Desktop\Sekwencje\skrypt 1.py", line 43, in <module>
ind = f.index(x)
File "C:\Users\Adrian\anaconda3\lib\site-packages\Bio\SeqRecord.py", line 803, in __eq__
raise NotImplementedError(_NO_SEQRECORD_COMPARISON)
NotImplementedError: SeqRecord comparison is deliberately not implemented. Explicitly compare the
attributes of interest.
Thanks for any answer.
Explanation
You can't get the index of and SeqRecord in list, because "SeqRecord comparison is deliberately not implemented" (you got the explanation in error message - NotImplementedError). The index() method returns the lowest index in list that obj appears. But to do it, it needs a specific comparsion method, that is not implemented in Seq module.
Hard method
Since python is a dynamic language, you can add a comparsion method to class. Even the error message is giving you the answer (Explicitly compare the
attributes of interest). Here is a code:
from Bio.SeqRecord import SeqRecord
def equal_seqs(self, other):
if not isinstance(other, SeqRecord):
raise NotImplementedError('Comparsion on wrong types!')
else:
return self.seq == other.seq # You can change it to whatever you want.
SeqRecord.__eq__ = equal_seqs
foo = SeqRecord('ATGCGCAT')
bar = SeqRecord('GACGATCA')
print(foo == bar)
# False
l = [foo, bar]
print(l.index(bar))
# 1
Other possibility
I don't know if I understood you correctly, but if you wanted to print ID of a sequence, then you can do it as following:
for seq in sequences:
print(f'{seq.id} {seq.name}')
Is that what you wanted?
More info
If you want to read more info about rich comparsion methods, then you can find it here
For example, I have the following list:
method = [fun1, fun2, fun3, fun4]
Then I show a menu where the user must select a number from 1-4 (len(method)). If the user selects i, I have to use the function funi. How can I do that?
Eg.
A=['hello','bye','goodbye']
def hello(n):
print n**2
def bye(n):
print n**3
def goodbye(n):
print n**4
If I want to call the function bye by the array A, using
>>>A[1](7)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
A[2](5)
TypeError: 'str' object is not callable
How can I use the names saved in A to call my functions? because every method is saved in a string.
Let's see...
You call a function fn by using parens () as in fn()
You access an item from a list by the indexing operator [] as in lst[idx]
So, by combining the two lst[idx](*args)
EDIT
Python list indices are zero-based, so for the first item is 0, the second 1, etc... If the user selects 1-4, you'll have to subtract one.
EDIT
Given the clarification, the following can be done
def method1():
pass
def method2():
pass
methods = [method1, method2]
And you can use the logic above. This way you won't have to mess with actual resolving the string of a name of the function to the actual function.
Keep in mind that functions in python are first class so you can store a reference of them to a list (what we do in methods=[] line)
In your list are not functions but strings (which have "randomly" the same name as the functions). Just put the functions inside the list:
def hello():
pass
mylist = [hello]
mylist[0]()
If you need the name of a function you can use a.__name__ e.g.
def hello():
pass
mylist = [hello]
print("Available functions:")
for function in mylist:
print(function.__name__)
I wanted to remove a substring from a string, for example "a" in "a,b,c" and then return "b,c" to me, it does not matter what's the order of a in string(like "a,b,c", "b,a,c", and so one).
DELIMITER = ","
def remove(member, members_string):
"""removes target from string"""
members = members_string.split(DELIMITER)
members.remove(member)
return DELIMITER.join(members)
print remove("a","b,a,c")
output: b,c
The above function is working as it is expected.
My question is that accidently I modified my code, and it looks as:
def remove_2(member, members_string):
"""removes target from string"""
members = members_string.split(DELIMITER).remove(member)
return DELIMITER.join(members)
You can see that I modified
members = members_string.split(DELIMITER)
members.remove(member)
to
members = members_string.split(DELIMITER).remove(member)
after that the method is broken, it throws
Traceback (most recent call last):
File "test.py", line 15, in <module>
remove_2("a","b,a,c")
File "test.py", line 11, in remove_2
return DELIMITER.join(members)
TypeError
Based on my understanding, members_string.split(DELIMITER) is a list, and invokes remove() is allowed and it should return the new list and stores into members, but
when I print members_string.split(DELIMITER) it returns None, it explains why throws TypeError, my question is , why it returns None other than a list with elements "b" and "c"?
remove() does not return anything. It modifies the list it's called on (lists are mutable, so it would be a major waste of cpu time and memory to create a new list) so returning the same list would be somewhat pointless.
This was already answered here.
Quote from the pythondocs:
You might have noticed that methods like insert, remove or sort that only modify the list have no return value printed – they return the default None. This is a design principle for all mutable data structures in Python.
Mutable objects like lists can be manipulated under the hood via their data-manipulation methods, like remove(),insert(),add().
Immutable objects like strings always return a copy of themselves from their data-manipulation methods, like with replace() or upper().
Method chaining
The next sample shows that your intended method-chaining works with strings:
# Every replace() call is catching a different case from
# member_string like
# a,b,member
# member,b,c
# a,member,c
DELIMITER = ","
def remove(member, member_string):
members = member_string.replace(DELIMITER + member, '').replace(member + DELIMITER, '').replace(DELIMITER + member + DELIMITER, '').upper()
return members
# puts out B,C
print remove("a","b,a,c")
List comprehension
Now for clever lists manipulation (it is even faster than for-looping) the pythonians invented a different feature named list comprehension. You can read about it in python documentation.
DELIMITER = ","
def remove(member, members_string):
members = [m.upper() for m in members_string.split(DELIMITER) if m != member]
return DELIMITER.join(members)
# puts out B,C
print remove("a","b,a,c")
In addition you could google for generators or look into pythondocs. But don't know about that a lot.
BTW, flame me down as a noob but, I hate it when they call python a beginner language, as above list-comprehension looks easy, it could be intimidating for a beginner, couldn't it?
In case I have a really big list (>100k elements) that can be retrieved from some object through function call, is there a way to wrap that list to make it immutable to the caller without copying it to tuple?
In the following example I have only one list field, but the solution should work for any number of list fields.
class NumieHolder(object):
def __init__(self):
self._numies = []
def add(self, new_numie):
self._numies.append(new_numie)
#property
def numies(self):
# return numies embedded in immutable wrapper/view
return ??? numies ???
if __name__ == '__main__':
nh = NumieHolder()
for numie in xrange(100001): # >100k holds
nh.add(numie)
# messing with numies should result in exception
nh.numies[3] = 4
# but I still want to use index operator
print '100th numie:', nh.numies[99]
I would know how to write adapter that behaves that way, but I'm interested if there is already some standard solution (i.e. in standard library or widely known library) I'm not aware of.
Unfortunately, there is no such wrapper in the standard library (or other prominent libraries). The main reason is that list is supposed to be a mutable sequence type with index access. The immutable sequence type would be a tuple as you already said yourself. So usually, the standard approach to make a list immutable would be to make it into a tuple by calling tuple(lst).
This is obviously not what you want, as you want to avoid to copy all the elements. So instead, you can create a custom type that wraps the list, and offers all non-modifying methods list also supports:
class ImmutableList:
def __init__ (self, actualList):
self.__lst = actualList
def __len__ (self):
return self.__lst.__len__()
def __getitem__ (self, key):
return self.__lst.__getitem__(key)
def __iter__ (self):
return self.__lst.__iter__()
def __reversed__ (self):
return self.__lst.__reversed__()
def __contains__ (self, item):
return self.__lst.__contains__(item)
def __repr__ (self):
return self.__lst.__repr__()
def __str__ (self):
return self.__lst.__str__()
>>> original = [1, 2, 3, 4]
>>> immutable = ImmutableList(original)
>>> immutable
[1, 2, 3, 4]
>>> immutable[2]
3
>>> for i in immutable:
print(i, end='; ')
1; 2; 3; 4;
>>> list(reversed(immutable))
[4, 3, 2, 1]
>>> immutable[1] = 4
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
immutable[1] = 4
TypeError: 'ImmutableList' object does not support item assignment
The alternative would be to subtype list and override __setitem__ and __delitem__ to raise an exception instead, but I would suggest against that, as a subtype of list would be expected to have the same interface as list itself. ImmutableList above on the other hand is just some indexable sequence type which happens to wrap a real list itself. Apart from that, having it as a subtype of list would actually require you to copy the contents once, so wrapping is definitely better if you don’t want to recreate all those items (which seems to be your point—otherwise you could just use tuple).
See Emulating Container Types for the "special" methods you'd want to implement or override. Namely, you'd want to implement __setitem__ and __delitem__ methods to raise an exception, so the list cannot be modified.
A large entity (list) is created in one method (foo) and bound to self.result.
The attempt to access this entity in a second method (transmit) fails starting at a certain size (something between 150,000 and 155,000 characters in the list). Printing (print self.result) from inside transmit leaves me with None.
I guess this is important: self.foo is directly called in a separate thread.
Please help. How do I get such "large" entity from a separate thread back into the main thread without such limitation?
...
def apply(self):
self.get_data()
self.start_foo_thread()
def start_foo_thread(self):
self.foo_thread = threading.Thread(target=self.foo)
self.foo_thread.daemon = True
self.progressbar.start()
self.foo_thread.start()
self.master.after(20, self.check_foo_thread)
def check_foo_thread(self):
if self.foo_thread.is_alive():
self.master.after(20, self.check_foo_thread)
else:
self.progressbar.stop()
def foo(self):
s = self.stringinput
n = self.numberinput
list = multiply_str_into_list(s, n)
self.result = list_to_text(list)
print self.result # output is not None
def transmit(self):
print self.result # output is None for more than about 155,000 characters in the list
return self.result
def multiply_str_into_list(string, n): #takes a string and multiplies it by n and writes into list
n_string = []
for i in range(0,n):
n_string.append(string)
return n_string
def list_to_text(list): #takes a list as input and joins it into str with each list item on a new line
a = '\n'.join(list)
return a
You don't really provide enough information to reproduce the problem, let alone debug it, but my guess is that at some point, you are doing something like this:
self.result = self.result.append(x)
Since .append() modifies the list in place, and returns None, this will clobber the reference to the list. It needn't be .append() either -- all of the methods that mutate lists return None.
As to why it is happening only at a certain size, perhaps you have some code like the above that is triggered only at a certain size, or else it is a red herring.