HJ-1549
HJ-1549

Reputation: 9

Are you allowed to put multiple methods on the same piece of data?

For example:

foo = ["Bar", "Baz", "A", "F", ]
foo.sort().reverse()

or:

bar = "Foo bar baz was not very useful in the year seventeen ninety-three ".split()
bar.reverse().lower().title()

Is this allowed?

Upvotes: 0

Views: 59

Answers (3)

BeRT2me
BeRT2me

Reputation: 13242

This has everything to do with which method you're using, and as mentioned, you have to know what the output of each method is.

This brings up the question? How can you know? There's always looking up the documentation online, but that can be time consuming and complicated. Python's, and most major module's creators, know this is an issue... so they've created good help() documentation.


Given foo = ["Bar", "Baz", "A", "F", ]

Let's look at the output of help(foo.sort)

Help on built-in function sort:

sort(*, key=None, reverse=False) method of builtins.list instance
    Sort the list in ascending order and return None.

    The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
    order of two equal elements is maintained).

    If a key function is given, apply it once to each list item and sort them,
    ascending or descending, according to their function values.

    The reverse flag can be set to sort in descending order.

We're interested in what the function returns. In this case, we can read it returns None and does the sort in-place. We also find the reverse flag I mentioned in a comment.

Let's look at help(foo.reverse)

Help on built-in function reverse:

reverse() method of builtins.list instance
    Reverse *IN PLACE*.

Again, an inplace function, that isn't going to work if we chain something after it.


However, some of your other examples might work:

Given bar = "Foo bar baz was not very useful in the year seventeen ninety-three "

Let's look at help(bar.lower)

Help on built-in function lower:

lower() method of builtins.str instance
    Return a copy of the string converted to lowercase.

It returns a copy, that can be chained.

What about help(bar.split)?

Help on built-in function split:

split(sep=None, maxsplit=-1) method of builtins.str instance
    Return a list of the words in the string, using sep as the delimiter string.

    sep
      The delimiter according which to split the string.
      None (the default value) means split according to any whitespace,
      and discard empty strings from the result.
    maxsplit
      Maximum number of splits to do.
      -1 (the default value) means no limit.

It returns a list, so it can be chained, but we have to make sure that the chained method can be used on a list.

bar.split().lower() outputs:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'lower'

Because lower isn't a method that applies to a list.

If you want to apply a method to every element in a list, one simple way is using either list comprehension as shown by Samwise.

Or using map like so:

>>> list(map(str.lower, bar.split()))
['foo', 'bar', 'baz', 'was', 'not', 'very', 'useful', 'in', 'the', 'year', 'seventeen', 'ninety-three']

Upvotes: 1

Mike garseia
Mike garseia

Reputation: 11

You can check the methods that is callable for a list by this :

foo = ["Bar", "Baz", "A", "F", ]

methods = [ method for method in dir(foo) if callable(getattr(foo, method)) ]
print(methods)

Upvotes: 0

Samwise
Samwise

Reputation: 71522

You can chain function calls, but you need to be aware of exactly what each function returns so that you can call a method on that object, or call a function that takes that object as an argument. sort() doesn't return the list, it sorts the list in-place and returns None. The same is true of reverse(). None isn't a list, so you can't call list methods on it.

The functions sorted() and reversed(), however, return new objects (sorted returns a list, and reversed returns an iterator that you can in turn convert into a list). So you can do:

>>> foo = ["Bar", "Baz", "A", "F", ]
>>> list(reversed(sorted(foo)))
['F', 'Baz', 'Bar', 'A']

Note that because these functions return new objects, the original foo is unchanged:

>>> foo
['Bar', 'Baz', 'A', 'F']

For the example with bar, you need to use a list comprehension in order to call the title() method on each individual string:

>>> bar = "Foo bar baz was not very useful in the year seventeen ninety-three ".split()
>>> [i.title() for i in reversed(bar)]
['Ninety-Three', 'Seventeen', 'Year', 'The', 'In', 'Useful', 'Very', 'Not', 'Was', 'Baz', 'Bar', 'Foo']

Upvotes: 2

Related Questions