Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

AttributeError: 'list' object has no attribute 'lower'

461 views
Skip to first unread message

Token Type

unread,
Sep 8, 2012, 1:13:21 PM9/8/12
to
On page 77 of the book natural language processing with Python, we have such an exercise: The polysemy of a word is the number of senses it has. Using WordNet, we can determine that the noun doghas seven senses with len(wn.synsets('dog', 'n')).
Compute the average polysemy of nouns, verbs, adjectives, and adverbs according
to WordNet.http://nltk.googlecode.com/svn/trunk/doc/book/ch02.html

I wrote the following function to solve it. However, it pops up "AttributeError: 'list' object has no attribute 'lower'". Quite confused, I supposed [synset.lemma_names for synset in synset_list] has made all the lemma into a list, hasn't it?

>>> def average_polysemy(pos):
synset_list = list(wn.all_synsets(pos))
lemma_list = [synset.lemma_names for synset in synset_list]
sense_number = 0
for lemma in lemma_list:
sense_number_new = len(wn.synsets(lemma, pos))
sense_number = sense_number + sense_number_new
return sense_number/len(synset_list)

>>> average_polysemy('n')

Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
average_polysemy('n')
File "<pyshell#53>", line 6, in average_polysemy
sense_number_new = len(wn.synsets(lemma, pos))
File "C:\Python27\lib\site-packages\nltk\corpus\reader\wordnet.py", line 1191, in synsets
lemma = lemma.lower()
AttributeError: 'list' object has no attribute 'lower'

Thanks for your tips

Token Type

unread,
Sep 8, 2012, 1:32:59 PM9/8/12
to
I don't know why lemma_list = [synset.lemma_names for synset in synset_list] will lead to such an error.

I have to use extend to solve the problem for lemma_list. The following codes are successful, take all the nouns as an example:

>>> def average_polysemy(pos):
synset_list = list(wn.all_synsets(pos))
sense_number = 0
lemma_list = []
for synset in synset_list:
lemma_list.extend(synset.lemma_names)
for lemma in lemma_list:
sense_number_new = len(wn.synsets(lemma, pos))
sense_number = sense_number + sense_number_new
return sense_number/len(synset_list)

>>> average_polysemy('n')
3

Roy Smith

unread,
Sep 8, 2012, 1:45:39 PM9/8/12
to
In article <df7ab5f7-c273-4a62...@googlegroups.com>,
Token Type <type...@gmail.com> wrote:

> I wrote the following function to solve it. However, it pops up
> "AttributeError: 'list' object has no attribute 'lower'". Quite confused, I
> supposed [synset.lemma_names for synset in synset_list] has made all the
> lemma into a list, hasn't it?

I'm not familiar with that library, but here's a few general ideas to
help you figure out what's going on.

First, I don't understand this code:

> synset_list = list(wn.all_synsets(pos))
> lemma_list = [synset.lemma_names for synset in synset_list]

It looks like you're taking an iterable, converting it to a list, just
so you can iterate over it again. Why not the simpler:

> lemma_list = [synset.lemma_names for synset in wn.all_synsets(pos)]

? But, I'm also confused about what lemma_list is supposed to end up
being. The name "lemma_names" is plural, making me think it returns a
list of something. And then you build those up into a list of lists?

In fact, I'm guessing that's your problem. I think you're ending up
with a list of lists of strings, when you think you're getting a list of
strings.

My suggestion is to print out all the intermediate data structures
(synset_list, lemma_list, etc) and see what they look like. If the
structures are simple, just plain print will work, but for more
complicated structures, pprint.pprint() is a life saver.

Another possibility is to assert that things are what you expect them to
be. Something like:

assert isinstance(synset_list, list)
assert isinstance(lemma_list, list)
assert isinstance(lemma_list[0], str)

and so on.

Cameron Simpson

unread,
Sep 8, 2012, 7:26:46 PM9/8/12
to Roy Smith, pytho...@python.org
On 08Sep2012 13:45, Roy Smith <r...@panix.com> wrote:
| First, I don't understand this code:
|
| In article <df7ab5f7-c273-4a62...@googlegroups.com>,
| Token Type <type...@gmail.com> wrote:
| > synset_list = list(wn.all_synsets(pos))
| > lemma_list = [synset.lemma_names for synset in synset_list]
|
| It looks like you're taking an iterable, converting it to a list, just
| so you can iterate over it again. Why not the simpler:
|
| > lemma_list = [synset.lemma_names for synset in wn.all_synsets(pos)]

Speaking for myself, when I write something like that it is because I
need to iterate over it twice or more. Often I'll make a tuple instead
of a list in that case, too, to avoid certain types of accidents.

| ? But, I'm also confused about what lemma_list is supposed to end up
| being. The name "lemma_names" is plural, making me think it returns a
| list of something. And then you build those up into a list of lists?
|
| In fact, I'm guessing that's your problem. I think you're ending up
| with a list of lists of strings, when you think you're getting a list of
| strings.

In my case, I have most often had this error (<list>.lower or its
equivalent) when I've accidentally converted a string into a list
of characters; easy to do because strings are themselves iterables,
yielding a sequence of single character strings:-)

It is usually an accident from getting my nesting wrong somewhere.

| My suggestion is to print out all the intermediate data structures
| (synset_list, lemma_list, etc) and see what they look like. If the
| structures are simple, just plain print will work, but for more
| complicated structures, pprint.pprint() is a life saver.
|
| Another possibility is to assert that things are what you expect them to
| be. Something like:
|
| assert isinstance(synset_list, list)
| assert isinstance(lemma_list, list)
| assert isinstance(lemma_list[0], str)
|
| and so on.

+1 to all of this, too.

Cheers,
--
Cameron Simpson <c...@zip.com.au>

Too much of a good thing is never enough. - Luba

Token Type

unread,
Sep 9, 2012, 9:50:16 AM9/9/12
to
Thanks very much for all of your tips. Take noun as an example. First, I need find all the lemma_names in all the synsets whose pos is 'n'. Second, for each lemma_name, I will check all their sense number.

1) Surely,we can know the number of synset whose pos is noun by
>>> len([synset for synset in wn.all_synsets('n')])
82115

However, confusingly it is unsuccessful to get a list of lemma names of these synsets by
>>> lemma_list = [synset.lemma_names for synset in wn.all_synsets('n')]
>>> lemma_list[:20]
[['entity'], ['physical_entity'], ['abstraction', 'abstract_entity'], ['thing'], ['object', 'physical_object'], ['whole', 'unit'], ['congener'], ['living_thing', 'animate_thing'], ['organism', 'being'], ['benthos'], ['dwarf'], ['heterotroph'], ['parent'], ['life'], ['biont'], ['cell'], ['causal_agent', 'cause', 'causal_agency'], ['person', 'individual', 'someone', 'somebody', 'mortal', 'soul'], ['animal', 'animate_being', 'beast', 'brute', 'creature', 'fauna'], ['plant', 'flora', 'plant_life']]
>>> type(lemma_list)
<type 'list'>

Though the lemma_list is a list in the above codes, it contains so many unnecessary [ and ]. How come it is like this? But what we desire and expect is a list without this brackets. Confused, I am really curious to know why.

2) Then I have to use a loop and extend to get all the lemma_names from synset:
>>> synset_list = list(wn.all_synsets('n'))
>>> lemma_list = []
>>> for synset in synset_list:
lemma_list.extend(synset.lemma_names)
>>> lemma_list[:20]
['entity', 'physical_entity', 'abstraction', 'abstract_entity', 'thing', 'object', 'physical_object', 'whole', 'unit', 'congener', 'living_thing', 'animate_thing', 'organism', 'being', 'benthos', 'dwarf', 'heterotroph', 'parent', 'life', 'biont']

3) In this case, I have to use loop to get all the lemma_names instead of [synset.lemma_names for synset in wn.all_synsets('n')]. The following is a working solution:

>>> def average_polysemy(pos):
synset_list = list(wn.all_synsets(pos))
sense_number = 0
lemma_list = []
for synset in synset_list:
lemma_list.extend(synset.lemma_names)
for lemma in lemma_list:
sense_number_new = len(wn.synsets(lemma, pos))
sense_number = sense_number + sense_number_new
return sense_number/len(synset_list)

>>> average_polysemy('n')
3

Thanks again.

Token Type

unread,
Sep 9, 2012, 10:00:34 AM9/9/12
to

> In fact, I'm guessing that's your problem. I think you're ending up
>
> with a list of lists of strings, when you think you're getting a list of
>
> strings.
>
Thanks. You guess right. It turns out that lemma_list is a list of list, as I tested in the previous post.

Token Type

unread,
Sep 9, 2012, 10:19:42 AM9/9/12
to

> structures are simple, just plain print will work, but for more
>
> complicated structures, pprint.pprint() is a life saver.
>

I did try . However,

>>> pprint.pprint(lemma_list)

Traceback (most recent call last):
File "<pyshell#74>", line 1, in <module>
pprint.pprint(lemma_list)
NameError: name 'pprint' is not defined
>>> pprint.pprint(synset_list)

Traceback (most recent call last):
File "<pyshell#75>", line 1, in <module>
pprint.pprint(synset_list)
NameError: name 'pprint' is not defined
>>>

Roy Smith

unread,
Sep 9, 2012, 10:29:11 AM9/9/12
to
In article <43a68990-d6cf-4362...@googlegroups.com>,
Token Type <type...@gmail.com> wrote:

> Thanks very much for all of your tips. Take noun as an example. First, I need
> find all the lemma_names in all the synsets whose pos is 'n'. Second, for
> each lemma_name, I will check all their sense number.
>
> 1) Surely,we can know the number of synset whose pos is noun by
> >>> len([synset for synset in wn.all_synsets('n')])
> 82115
>
> However, confusingly it is unsuccessful to get a list of lemma names of these
> synsets by
> >>> lemma_list = [synset.lemma_names for synset in wn.all_synsets('n')]
> >>> lemma_list[:20]
> [['entity'], ['physical_entity'], ['abstraction', 'abstract_entity'],
> ['thing'], ['object', 'physical_object'], ['whole', 'unit'], ['congener'],
> ['living_thing', 'animate_thing'], ['organism', 'being'], ['benthos'],
> ['dwarf'], ['heterotroph'], ['parent'], ['life'], ['biont'], ['cell'],
> ['causal_agent', 'cause', 'causal_agency'], ['person', 'individual',
> 'someone', 'somebody', 'mortal', 'soul'], ['animal', 'animate_being',
> 'beast', 'brute', 'creature', 'fauna'], ['plant', 'flora', 'plant_life']]
> >>> type(lemma_list)
> <type 'list'>
>


> Though the lemma_list is a list in the above codes, it contains so many
> unnecessary [ and ]. How come it is like this? But what we desire and expect
> is a list without this brackets. Confused, I am really curious to know why.

It looks like synset.lemma_names gets you a list. And then you're
taking all those lists and forming them into a list of lists:

>>> lemma_list = [synset.lemma_names for synset in wn.all_synsets('n')]

I think what you want to study is the difference between list.append()
and list.extend(). When you use the list builder syntax, you're
essentially writing a loop which does append operations. The above is
the same as if you wrote:

lemma_list = list()
for synset in wn.all_synsets('n'):
lemma_list.append(synset.lemma_names)

and I think what you're looking for is:

lemma_list = list()
for synset in wn.all_synsets('n'):
lemma_list.extend(synset.lemma_names)

Roy Smith

unread,
Sep 9, 2012, 10:32:33 AM9/9/12
to
In article <dea2fdd1-ad19-4254...@googlegroups.com>,
OK, I can see how this can be confusing. In "pprint.pprint()", the two
"pprint"s mean different things. The first one is the name of a module.
The second one is the name of a function in that module. In general, I
dislike this style of naming since it just leads to this kind of
confusion.

In any case, you need to do one of two things.

Style 1:

import pprint
pprint.pprint(foo)

Style 2:

from pprint import pprint
pprint(foo)

Jean-Michel Pichavant

unread,
Sep 10, 2012, 5:52:34 AM9/10/12
to Token Type, pytho...@python.org
I often noticed people around me that are not that familiar with python
are dismissing the error stack so quickly ; they probably knows the
machine is trying to communicate with them but they don't seem to
understand the message. Error stacks may be difficult to read at first
glance but you can solve a lot of problems just by reading it.

So next time you see 'X' has no attribute 'Y', you'll know that you've
accessed an attribute/method of an object that does not exist, either
you made a typo in the attribute name, or you object is not actually
what you think it is.

Advice : if you have so time, install ipython and execute your scripts
in an ipython shell with the %pdb faeture on. This will automatically
call the debugger upon unhandled exceptions and you'll be able to
inspect your objects live from the prompt.

JM






Token Type

unread,
Sep 14, 2012, 11:01:11 AM9/14/12
to Token Type, pytho...@python.org
Thanks. By the way, do we have a list of explanations of error message? If so, whenever we come across error message, we can refer to it and solve the problem accordingly.

Token Type

unread,
Sep 14, 2012, 11:01:11 AM9/14/12
to comp.lan...@googlegroups.com, pytho...@python.org, Token Type

Steven D'Aprano

unread,
Sep 14, 2012, 11:18:27 AM9/14/12
to
Forget about a "list of explanations of error message[s]". There is no
such list, and there never will be, because there is no limit to the
number and kind of possible error messages.

Instead, you should actually read the error message you see. Python is
telling you what the problem is. Pay attention to it.

AttributeError: 'list' object has no attribute 'lower'

This tells you that you tried to access something.lower, but "something"
is a list, and lists don't have an attribute or method "lower".

Normally, Python will show you the line of source code with the error, so
you will even see the name of the variable.


--
Steven

Chris Angelico

unread,
Sep 14, 2012, 11:19:24 AM9/14/12
to pytho...@python.org
On Sat, Sep 15, 2012 at 1:01 AM, Token Type <type...@gmail.com> wrote:
> Thanks. By the way, do we have a list of explanations of error message? If so, whenever we come across error message, we can refer to it and solve the problem accordingly.

Not really, but if you paste the message into Google or DuckDuckGo or
another web search engine, you'll usually find something helpful.
Possibly add a few keywords about what you're doing, if the message
alone is too general.

By the way, you don't need to include both comp.lang.python and
python-list in your addressees; they mirror each other, so sending to
one will make it arrive on the other too.

Have fun!

ChrisA
0 new messages