I created a dict:
scores = {5: 35044.51299744237, 25: 29016.41319191076, 50: 27405.930473214907, 100: 27282.50803885739, 250: 27893.822225701646, 500: 29454.18598068598}
I can use min function with it using:
min(scores.keys(),key = lambda x: scores[x])
min(scores, key=scores.get)
but when I try to use:
min(scores.keys(),key = scores.values())
I get an error :
'dict_values' object is not callable
Could someone please explain why?
key must be a function callable with one parameter. values() is not a function, it's a view, a sequence of all values in the dict. And while scores.values is a function it's not callable with a parameter.
It's also unclear as to what you think your snippet would actually do even if it worked. What would looking for a key in the set of values do exactly?
You get 'dict_values' object is not callable because the key argument in min requires a callable object (an object that has __call__ method). In your case scores.values() returns an object with type <class 'dict_values'> that is not callable.
>>> dct = {}
>>> type(dct.values())
<class 'dict_values'>
>>> callable(dct.values())
False
If you wish to get the key with the minimal value, you should try something like this.
min(scores.items(), key=lambda x: x[1])[0]
Or with operator.itemgetter:
from operator import itemgetter
min(scores.items(), key=itemgetter(1))[0]
In other words, min applies key function to the elements provided by scores.items().
If you try scores.keys(), as in your question, min function knows nothing about its values. Though you still can do this:
min(scores.keys(), key=lambda key: scores[key])
But I wouldn't recommend this solution, because key function contains scores inside that can lead to undefined behavior in some cases.
Related
I have this piece of code and I am trying to understand it and get the output, but I get the error:
AttributeError: 'int' object has no attribute 'items'
def my_func(A: Set[int], B: List[Dict[int, C]]) -> \
List[Dict[int, C]]:
D = []
for b in B:
E = dict()
for a, m in b.items():
if a in A:
E[a] = m
D.append(E)
return D
A is a set :
A={1,2}
and C is a dictionary:
my_dic = {
1: C(
X=11.0,
Y=34.25,
a=1
),
2: C(
X=51.76,
Y=50.63,
a=2,
)
}
I call the function
X=my_func(A,my_dic)
but it gives me error. I also converted the dictionary to the list and it still gives me error but this time: 'tuple' object has no attribute 'items'. Would you please help me to understand the code better and be able to run it?
You define your func as follows:
def my_func(A: Set[int], B: List[Dict[int, C]])
You say that B will be a list of dict's. But then you call:
X=my_func(A,my_dic)
Where you pass in a single dict instead of the list defined before.
However, later in the func, you refer to .items(), which is a method callable on a dict, but not on a list or an int. When you pass in a single dict instead of a list of dicts, your code is trying to iterate over the element you passed in. Normally you would iterate over the elements of the list. But since you've passed in a dict, it will iterate over the keys of the dict. But your keys are set as int's, so then the .items() call fails.
So you just have to tighten up your call structure.
To quickly comply, you can change:
X=my_func(A,my_dic)
to:
X=my_func(A, [my_dic,])
That should help... At least now you'll be passing in a list of dicts, even if it is just a list of length one.
Because you passed a dictioanry where you were expecting a list (of dictionaries), for b in B: is now looping over the keys of that dictionary. Each key is an int, which you call items on, leading to the error you're seeing.
Try:
X = my_func(A, [my_dic])
Note that Python type signatures in this scenario are not being enforced at runtime. You have specified a list of dictionaries with ints as keys, and C as the value type. Python will not step you from calling: my_func(A, 42) but you will get a runtime error.
I've got a list of objects, that have a function which does some calculations on several member variables and returns a value. I want to sort the list according to this return value.
I've found how to sort a list of objects by member variables but I want to keep them private (_variable_name).
Is there an easy way to accomplish this similar to the method of sorting the list directly by the members of the objects?
Just use the key argument to the sorted() function or list.sort() method:
sorted_list = sorted(list_of_objects, key=function_that_calculates)
The function_that_calculates is called for each entry in list_of_objects and its result informs the sort.
If you meant that each object has a method, you can use a lambda or the operator.methodcaller() object to call the method on each element:
sorted_list = sorted(list_of_objects, key=lambda obj: obj.method_name())
or
from operator import methodcaller
sorted_list = sorted(list_of_objects, key=methodcaller('method_name'))
Note that in Python, there is no such thing as a private attribute; your sorting function can still just access it. The leading underscore is just a convention. As such, sorting by a specific attribute can be done with either a lambda again, or using the operator.attrgetter() object:
sorted_list = sorted(list_of_objects, key=lambda obj: obj._variable_name)
or
from operator import attrgetter
sorted_list = sorted(list_of_objects, key=attrgetter('_variable_name'))
I am trying to sort a list of objects in Python 3.4 based on the value of the data attribute of each object. If I use
db[count].sort(key=lambda a: a.data)
everything works fine. However, I want the sort to be case insensitive so I use
db[count].sort(key=lambda a: a.data.lower)
but then I get
db[count].sort(key=lambda a: a.data.lower)
TypeError: unorderable types: builtin_function_or_method() < builtin_function_or_method()
Any ideas?
key has to be a callable that returns a value to be sorted. In your case it returns another callable a.data.lower. You need to call lower in order to get the value, so the correct form is:
db[count].sort(key=lambda a: a.data.lower())
You are passing a reference to the lower method instead of calling it.
Try this:
db[count].sort(key=lambda a: a.data.lower())
I have a long and complicated method, I'll give the important parts:
def get_itter(self, sort_by=0): #sort_by is set to 0 for debugging purposes
...
r = self.parser(self.in_file) # parse a csv file
...
if type(sort_by) == int:
r = [i for i in r]
sort = sorted(r, key=sort_by)
...
Now my problem is that when I run this code it gives me an error: TypeError: 'int' object is not callable. Why is it giving me this error?
P.S. I am relatively new to Python and am trying to add some functionality to code that I did not write.
You set:
sort_by=0
check it's an int
if type(sort_by) == int: # note: isinstance(sort_by, int) is preferred here
then use it:
sorted(r, key=sort_by)
When you pass a key to sorted, it tries to apply that key to all items in the sequence it's sorting, trying to call it with each item, something like:
sortvalues = [key(i) for i in seq]
If key is an integer, you can't call it:
0(1)
gives the TypeError you are seeing.
It's not clear exactly what you're trying to do, but if you want to sort by the sort_byth item in a sequence, you can use operator.itemgetter:
from operator import itemgetter
sorted(r, key=itemgetter(sort_by))
You set sort_by to 0 and then pass that as the key function to sorted. Python will call key as a function to define the sorting key, which isn't possible for 0.
suppose i have object has key 'dlist0' with attribute 'row_id' the i can access as
getattr(dlist0,'row_id')
then it return value
but if i have a dictionary
ddict0 = {'row_id':4, 'name':'account_balance'}
getattr(ddict0,'row_id')
it is not work
my question is how can i access ddict0 and dlist0 same way
any one can help me?
Dictionaries have items, and thus use whatever is defined as __getitem__() to retrieve the value of a key.
Objects have attributes, and thus use __getattr__() to retrieve the value of an attribute.
You can theoretically override one to point at the other, if you need to - but why do you need to? Why not just write a helper function instead:
Python 2.x:
def get_value(some_thing, some_key):
if type(some_thing) in ('dict','tuple','list'):
return some_thing[some_key]
else:
return getattr(some_thing, some_key)
Python 3.x:
def get_value(some_thing, some_key):
if type(some_thing) in (dict,tuple,list):
return some_thing[some_key]
else:
return getattr(some_thing, some_key)
Perhaps a namedtuple is more suitable for your purpose
>>> from collections import namedtuple
>>> AccountBalance=namedtuple('account_balance','row_id name')
>>> ddict0=AccountBalance(**{'row_id':4, 'name':'account_balance'})
>>> getattr(ddict0,'row_id')
4
>>> ddict0._asdict()
{'row_id': 4, 'name': 'account_balance'}