Extending peewee expressions throws 'Expression' object is not iterable - python

I want to dynamically create where-clauses in peewee. I learned I need to use expressions, but cannot get this to run. Here my code:
clauses = [
(Docs.language_frst == 0),
(Docs.body_len <= max_body_len),
(Docs.body_len >= min_body_len)
]
if len(aValid_ids_used):
clauses.extend( (Docs.id.not_in(aValid_ids_used)) )
docids = Docs.select(Docs.id).where(reduce(operator.and_, clauses))
As long as aValid_ids_used is empty the code runs fine. Once aValid_ids_used is not empty any longer and I am asking the clauses to be extended I get an error:
Traceback (most recent call last): File "xyz.py", line 170, in <module>
clauses.extend( (Docs.id.not_in(aValid_ids_used)) )
TypeError: 'Expression' object is not iterable

You need to pass a list to extend with. You're currently passing an Expression
clauses.extend( (Docs.id.not_in(aValid_ids_used), ) )
e.g.
>>> c = []
>>> c.extend((2))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> c.extend((2,))
>>> c
[2]

You probably want to use list.append rather than list.extend. extend takes a list as an argument, while append takes a single item.

Related

Why am i getting this error when i am trying to insert a string into a list?

i am running the following code.
a = ["hello","bye","where","am","i"]
ls_capitalize = [x.capitalize() for x in a]
reverse = reversed(ls_capitalize)
reverse.insert(2,"Extra")
print(reverse,"\n",ls_capitalize )
I am trying to insert a string in the list after reversing it and i am getting the following error.
Traceback (most recent call last):
File "<input>", line 4, in <module>
AttributeError: 'list_reverseiterator' object has no attribute 'insert'
If insert() is not working for this what could i use?
The problem is reversed doesn't return a list, it returns an iterator. That's why it says list_reverseiterator doesn't have insert. Try
a = ["hello","bye","where","am","i"]
ls_capitalize = [x.capitalize() for x in a]
reverse = list(reversed(ls_capitalize))
reverse.insert(2,"Extra")
print(reverse,"\n",ls_capitalize )

Different ValueError for the same operation in List and Tuple

I am curious why ValueErrors are different in List and Tuple when I try to get an index. ValueError of a list returns in well format with actual argument "ValueError: 'ITEM' is not in list", whereas tuple returns something like this "ValueError: tuple.index(x): x not in tuple".
I think List and Tuple both are calling same index() method then why it is raising different ValueErrors?
>>> jframe_li
['Angular', 'React', 'Vue.js', 'Ember.js', 'Mereor', 'Node.js', 'Backbone.js']
>>> jframe_tu
('Angular', 'React', 'Vue.js', 'Ember.js', 'Mereor', 'Node.js', 'Backbone.js')
>>> jframe_li.index('React')
1
>>> jframe_tu.index('React')
1
>>> jframe_li.index('react')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'react' is not in list
>>> jframe_tu.index('react')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: tuple.index(x): x not in tuple
There are implementation differences in the index methods for lists and tuples, including in the text of a raised ValueError.
See ValueError string for tuple.index and ValueError string for list.index

python TypeError: frozenset expected at most 1 arguments, got 4

I'm getting this error when trying to make a frozen set:
class Transcriber:
DNA_BASES = frozenset('A','T','G','C')
...
And this is the Traceback:
~/python/project5$ python wp_proj5.py
Traceback (most recent call last):
File "wp_proj5.py", line 5, in <module>
class Transcriber:
File "wp_proj5.py", line 7, in Transcriber
DNA_BASES = frozenset('A','T','G','C')
TypeError: frozenset expected at most 1 arguments, got 4
What is wrong here? Can't I initialize a frozenset with more than one string?
You need to pass an iterable like a list:
frozenset(['A','T','G','C'])
You can read about it here: http://docs.python.org/2/library/stdtypes.html#frozenset

Cases where use of tuple is a must

In Python, the only difference between a list and a tuple that I know of is "lists are mutable but tuples are not". But as far as I believe, it depends on whether the coder wants to risk mutability or not.
So I was wondering whether there are any cases where the use of a tuple over a list is a must. Things that can not be done with a list but can be done with a tuple?
You can use tuples as keys in dictionaries and insert tuples into sets:
>>> {}[tuple()] = 1
>>> {}[list()] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Which is basically a result of a tuple being hashable while a list isn't:
>>> hash(list())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(tuple())
3527539
The answer by #Otto is very good. The only thing I have to add to it is that when you open things up to 3rd party extensions, you really need to consult the documentation. Some functions/methods may expect one or the other data-type (or have different results depending on which one you use). One example is using tuples/lists to index a numpy array:
import numpy as np
a=np.arange(50)
a[[1,4,8]] #array([1, 4, 8])
a[(1,4,8)] #IndexError
EDIT
Also, a quick timing test shows that tuple creation is MUCH FASTER than list creation:
import timeit
t=timeit.timeit('[1,2,3]',number=10000000)
print (t)
t=timeit.timeit('(1,2,3)',number=10000000)
print (t)
which is good to keep in mind. In other words, do:
for num in (8, 15, 200):
pass
instead of:
for num in [8, 15, 200]:
pass
Also, the now obsolete string formatting using the % operator requires the argument list to be a tuple. A list would be treated as single argument:
>>> "%s + %s" % [1, 2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not enough arguments for format string
>>> "%s + %s" % (1, 2)
'1 + 2'

clarification on comparing objects of different types

The following sentences are a cause of confusion for me(from Guido's Tutorial on python.org):
"Note that comparing objects of
different types is legal. The outcome
is deterministic but arbitrary: the
types are ordered by their name. Thus,
a list is always smaller than a
string, a string is always smaller
than a tuple, etc."than a tuple, etc."
That means that for :
a=[90]
b=(1)
a<b
the result should be True. But it is not so!
Can you help me out here?than a tuple, etc."
Also, what is meant by "The outcome is deterministic but arbitrary"?
(1) is an int. You probably meant (1,), which is a tuple.
Please note that you should not rely upon this behavior anymore. Some built-in types cannot be compared with other built-ins, and new data model provides a way to overload comparator functionality.
>>> set([1]) > [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only compare to a set
Moreover, it was removed in py3k altogether:
>>> [1,2] > (3,4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: list() > tuple()
>>> [1,2] > "1,2"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: list() > str()

Categories

Resources