TypeError: 'top_list' object does not support indexing - python

I would like to print out the list sorted by the second element.
TypeError: 'top_list' object does not support indexing
Is there anyone that can help me?
class top_list(object):
def __init__(self, name, hit_rate):
self.name = name
self.hit_rate = float(hit_rate)
def __str__(self):
return "{0} {1}".format(self.name, self.hit_rate)
def top_ten():
"""Prints out the list"""
top10 = []
file = open("high_score.txt")
for i in range(0,1):
x = file.readlines()
for line in x:
line = line.split(",")
lista = top_list(line[0], float(line[1]))
top10.append(lista)
a = sorted(top10, key=lambda line: line[1])
print(a)

In your code
a = sorted(top10, key=lambda line: line[1])
you are trying to access the top_list element using subscript notation. If that is what you want to do, implement a __getitem__ method. __getitem__ allows you to use the subscript operator - list[1] translates to list.__getitem__(1).
def self.__getitem__(self, key):
if key == 1:
return self.name
else:
return self.hit_rate
Or modify the lambda function to access the element you want without using a subscript:
a = sorted(top10, key=lambda line: line.hit_rate)
Also note that using context manager for file is safer and more pythonic. You can also read the lines by iterating over the Python file object:
with open('high_score.txt', 'r') as file:
for line in file:
...
but extra caution needs to be taken to handle newlines (stripping them possibly).

Related

Get a parameter of a file .txt using python

I'm trying to get parameters of a .txt like that:
a=10
b=15
c=20
How can i do a function called get() that takes from this file called parameters.txt the parameter b and return 15??
It's to build a module that works like a getter of parameters.
To simplify and explain information: the .txt conatains parameters with and int value. The get() function will obtain the integer value associated to the parameter.
Since you say you want "to build a module that works like a getter of parameters", you should just parse the whole file into an internal dictionary:
class Config(dict):
def __init__(self, file_name):
with open(file_name) as f:
for line in f:
key, value = line.strip().split("=")
self[key] = value
Example usage:
c = Config("test.txt")
print(c)
# {'a': '10', 'b': '15', 'c': '20'}
print(c['b'])
# 15
If all your values are numerical, you might want to modify this to do self[key] = float(value) or similar. Otherwise you might want to define a try_parse_numeric function:
def try_parse_numeric(s):
try:
return int(s)
except ValueError:
pass
try:
return float(s)
except ValueError:
pass
return s
class Config(dict):
def __init__(self, file_name, value_parser=try_parse_numeric):
self.value_parser = value_parser
with open(file_name) as f:
for line in f:
key, value = line.strip().split("=")
self[key] = self.value_parser(value)
And if it gets more complicated than that, you probably want to use configparser instead of rolling your own.
def get(param):
with open(filename, "r") as infile: #Read file
for line in infile: #Iterate over each line
if line.startswith(param): #Check if line starts with input param
return line.split("=")[1] #Return Value
print(get("b"))
def get(par):
with open("parameters.txt",'r') as file:
return next(e for e in file.readlines() if par in e).split("=")[1]
Try this
Something like this sould work:
def get(filename,variable):
with open(filename) as f:
for line in f.readlines():
if line[:len(variable)] == variable:
return line.split("=")[-1]
return None
print(get("test.txt","b"))

TypeError: 'list' object is not callable, error calling extend from inherited list class

I wrote the following code,
#sanitize fuction
def sanitize(time_string):
if '-' in time_string:
splitter = '-'
elif ':' in time_string:
splitter = ':'
else:
return(time_string)
(mins, secs) = time_string.split(splitter)
return(mins + '.' + secs)
class AthleteList(list):
def __init__(self, a_name, a_dob=None, a_times=[]):
list.__init__([])
self.name = a_name
self.dob = a_dob
self.extend = a_times
def top3(self):
return(sorted(set([sanitize(t) for t in self]))[0:3])
#get coach data fuction
def get_coach_data(filename):
try:
with open(filename) as f:
data = f.readline()
templ = data.strip().split(',')
return(AthleteList(templ.pop(0), templ.pop(0), templ))
except IOError as ioerr:
print('File error: ' + str(ioerr))
return(None)
sarah = get_coach_data("sarah2.txt")
julie = get_coach_data("julie2.txt")
james = get_coach_data("james2.txt")
mikey= get_coach_data("mikey2.txt")
vera = AthleteList('vera')
vera.append('1.33')
vera.extend(['1.74','1.46','1.42','1.40'])
print(vera.top3())
When I run this code, it shows the following error.
But it only shows error when I use extend method.
I can use append method with no probs.
vera.extend(['1.74','1.46','1.42','1.40'])
TypeError: 'list' object is not callable
Follow the execution path from AthleteList('vera'), noting how self.extend gets initialized to a list, which shadows the function you expect.
what's happening is essentially this:
>>> extend = []
>>> extend(['foo'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
To Access list you need to use the square brackets ([]) and not the parenthesis (()).
instead of
vera.extend(['1.74','1.46','1.42','1.40'])
use
aList = ['1.74','1.46','1.42','1.40']
vera.extend(aList)
You're basically trying to call a list (self.extend = a_times and a_times = []), which is impossible.
What you'd need to do, is use:
vera.extend.extend(['1.74','1.46','1.42','1.40'])
Or either this (as mentioned before):
vera.extend = ['1.74','1.46','1.42','1.40']
But actually this is not exactly correct either (given we need vera list and not vera.extend one [missed this when first posted, sorry!]), as shown here:
>>> vera = AthleteList("vera")
>>> vera.extend = ['1.74','1.46','1.42','1.40']
>>> print(vera.top3())
[]
>>> vera.extend.extend(['1.74','1.46','1.42','1.40'])
>>> print(vera.top3())
[]
The correct answer would be remove self.extend from AthleteList class so it works the way you want it (vera.extend(['1.74','1.46','1.42','1.40'])).
>>> vera = AthleteList("vera")
>>> vera.extend(['1.74','1.46','1.42','1.40'])
>>> print(vera.top3())
['1.40', '1.42', '1.46']
So, class should be like this:
class AthleteList(list):
def __init__(self, a_name, a_dob=None, a_times=[]):
list.__init__([])
self.name = a_name
self.dob = a_dob
def top3(self):
return(sorted(set([sanitize(t) for t in self]))[0:3])
Hope it helps!
According to your code, you have initialized a class variable extend to an empt list.
self.extend = a_times
where a_times = []
It is a variable, not a function according to your code. That is why it is throwing an error of 'not callable'
Change the following line of code:
vera.extend(['1.74','1.46','1.42','1.40']) to vera.extend = ['1.74','1.46','1.42','1.40'].
Hope it helps!
I think the problem is in the definition of class AtheleteList
self.extend = a_times should be change to self.extend(a_times)

Why does this print the memory location of an object rather than what I want?

I'm not sure what's happening when I print my dictionary.
In Python 3, I have a dictionary of parse_blast objects called transSwiss. Each object's proteinID is the key with the entire object as the value.
I can print transSwiss in it's entirety and I can also print blasto.protein, but not when I combine them to get a dictionary value. I'm not sure what is happening when I use:
print(transSwiss[blasto.protein])
<__main__.parse_blast object at 0x000000373C5666A0>
Here is the code
class parse_blast(object):
def __init__(self, line):
#Strip end-of-line and split on tabs
self.fields = line.strip("\n").split("\t")
self.transcriptId, self.isoform = self.fields[0].split("|")
self.swissStuff = self.fields[1].split("|")
self.swissProtId = self.swissStuff[3]
self.percentId = self.fields[2]
def filterblast(self):
return float(self.percentId) > 95
class parse_matrix(object):
#Consider __init__ as a Constructor
def __init__(self, matrix_lines):
(self.protein,
self.Sp_ds,
self.Sp_hs,
self.Sp_log,
self.Sp_plat) = matrix_lines.strip("\n").split("\t")
def separate_tuples(one_tuple):
return "\t".join(one_tuple)
blastmap = map(parse_blast, blast_output.readlines())
filtered = filter(parse_blast.filterblast, blastmap)
matrixmap = map(parse_matrix, matrix_output.readlines()[1:])
transSwiss = {blasto.transcriptId:blasto for blasto in filtered}
for matrixo in matrixmap:
print(transSwiss[matrixo.protein])
Because your object is defined by you, you also need to tell python how you want it to print. You can do this by defining a function called "__str__" that returns how you want to print your object.
https://en.wikibooks.org/wiki/Python_Programming/Classes#str

Building a dictionary from a file in a class python

I am trying to build a class that builds a dictionary from a file that takes the first item in the list and makes it the key and the rest of the items in the list values. So at the end when I call this like
neighbors=Neighbors(FileName.txt)
but then when I say
neighbors['New York']
it doesn't return the values for that key
class Neighbors(dict):
def __init__(self, fname):
states=[]
states1=[]
states2=[]
self.fname=open(fname)
for line in self.fname:
line=line[:-1]
states.append(line)
for line in states:
states1.append(line.split(','))
for line in states1:
item=[x.strip(' ') for x in line]
states2.append(item)
a=dict([(t[0],t[1:]) for t in states2])
neighbors = Neighbors("us_states_adjacency.txt")
print neighbors
def neighbors(fname):
def make_line(adjacent_cities):
line = [city.strip() for city in adjacent_cities.split(",")]
return line[0],line[1:]
return dict(map(make_line,open(fname)))
is how I would do this I think ...
there is no reason to use a class for this ... you just want a dictionary
however if you really wanted it to be a class
class Neighbors(dict):
def __init__(self,fname):
def make_line(adjacent_cities):
line = [city.strip() for city in adjacent_cities.split(",")]
return line[0],line[1:]
dict.__init__(self,map(make_line,open(fname)))
if you dont wnat to impove your original class and you just want to fix it you just need to call the super inits method
class Neighbors(dict):
def __init__(self, fname):
states=[]
states1=[]
states2=[]
self.fname=open(fname)
for line in self.fname:
line=line[:-1]
states.append(line)
for line in states:
states1.append(line.split(','))
for line in states1:
item=[x.strip(' ') for x in line]
states2.append(item)
dict.__init__(self,[(t[0],t[1:]) for t in states2]) # call super constructor on our dict ...
here is a simpler class that overrides dict ...
class dummy(dict):
def __init__(self,initializer):
dict.__init__(self,initializer)
d = dummy([('a',2),('b',4)])
print d['a']
print d['c']

Error accessing class objects in python

I am having some problem accessing class instances. I am calling the class from a procedure, name of instance is defined in some variable. I want the instance name to be created of that value and then want to access it, but when i access it is giving error. Can some one please help to resolve this issue.
class myclass:
def __init__(self,object):
self.name = object
def mydef():
global a1
b = "a1"
b = myclass(b)
mydef()
print a1.name
Second Problem:
In my actual script, I have to create a large number of such instances from this function (around 100). So defining their name as global would be painful, is there a way i could access those instances outside function without having to declare them as global.
Modification:
class myclass:
def __init__(self,object,typename):
self.name = object
self.typeid = typename
def mydef():
file_han = open(file,"r")
while True:
line = file_han.readline()
if not line:
break
start = line.find('"')
end = line.find('"',start+1)
string_f = line[start+1:end]
myclass(string_f,'a11')
mydef(file)
print def.name
print def.typeid
File Contents are :
a11 "def"
a11 "ghi"
a11 "eff"
Here's how I'd do it. I don't know why you're messing around with globals, if you'd care to explain, I'll update my answer.
class Myclass(object):
def __init__(self, name):
self.name = name
def mydef():
return Myclass("a1")
a1 = mydef()
print a1.name
Gather your instances in a list:
instances = []
for x in range(1000):
instances.append(Myclass("Instance {0}".format(x)))
print instance[42].name
Note the changes:
Class names should be capitalized
Use object as the base class of your classes (since python 2.2, but no longer necessary in 3.x)
Don't shadow the built-in object with your parameter name
Just use the string "a1" directly as a parameter instead of assigning it to a variable
Return something from the function instead of passing the result by global variable
RE: Comment
You haven't said anything about the format of these files, so I'll just give an example where the file to be read contains one class name per line, and nothing else:
def mydef(filename):
ret = []
with open(filename) as f:
for line in f:
# Call `strip` on line to remove newline and surrounding whitespace
ret.append(Myclass(line.strip()))
return ret
So if you have several files and wish to add all your instances from all your files to a large list, do it like this:
instances = []
for filename in ["myfile1", "myfile2", "myfile3"]:
instances.extend(mydef(filename))
RE: OP Edit
def mydef(filename):
ret = []
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
ret.append(Myclass(string_f))
return ret
i = mydef("name_of_file")
RE: Comment
Oh, you want to access them by name. Then return a dict instead:
def mydef(filename):
ret = {}
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
ret[string_f] = Myclass(string_f)
return ret
i = mydef("name_of_file")
print i["ghi"].name # should print "ghi"
RE: Comment
If I understand you correctly, you want to have it both ways -- index by both line number and name. Well then why don't you return both a list and a dictionary?
def mydef(filename):
d = {}
L = []
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
instance = Myclass(string_f)
d[string_f] = instance
L.append(instance)
return L, d
L, d = mydef("name_of_file")
print d["ghi"].name
print L[3]
print L.index(d["ghi"])
You could use class as repository for your instances, for example
class Named(object):
def __init__(self,name):
self.name = name
def __new__(cls,name):
instance = super(type,cls).__new__(cls,name)
setattr(cls,name,instance)
return instance
def __repr__(self):
return 'Named[%s]'%self.name
Named('hello')
Named('x123')
Named('this is not valid attribute name, but also working')
print(Named.hello,Named.x123,getattr(Named,'this is not valid attribute name, but also working'))

Categories

Resources