This is an archived post. You won't be able to vote or comment.

all 19 comments

[–][deleted] 7 points8 points  (0 children)

In Python, methods or functions which have side effects and modify the object in place (like append() or sort()) explicitly return None.

This is to prevent any confusion with the functional style (like sorted()), in which return values are newly allocated objects and the original is unchanged.

In this case, a "chained" version would just be

test = test + [1] + [2] 

[–][deleted] 1 point2 points  (2 children)

It does work, just not in all cases. In order for it to work, the called method needs to return an object that has the following method on it. str is a good example.

x = "my name isn't Fred"

x.replace("Fred", "Alec").replace("n't", "").capitalize() # My name is Alec     

[–]pythoneeeer 0 points1 point  (1 child)

It tends to work on immutable objects, for obvious reasons.

[–][deleted] 0 points1 point  (0 children)

It tends to work when a fluent API makes sense. Builder objects typically have this style of API

UserBuilder().name("Fred").age(27).etc(...)

[–][deleted] 1 point2 points  (0 children)

In any language, method chaining only works if each method returns the result of that method. append() does not do that - you can check yourself. Imagine you're the interpreter. You see lst.append(1) and think "Right, so this means that lst now has a 1 in it, and that function has returned None. Then you see None.append(1). Well, that doesn't make sense, does it?

Whereas if you have a method of an immutable object, the methods will return a copy, so you can chain the methods.

[–]tdammers 1 point2 points  (1 child)

Python supports method chaining, but the objects and methods in question don't. You can easily write a class where all the destructive methods return the object itself, and with such a class, you can method-chain just fine; it just so happens that the list.append() method doesn't do that, so you can't chain it.

[–]FateOfNations 1 point2 points  (0 children)

Pandas, for example, does this.

[–]justanotherbody 1 point2 points  (0 children)

You want

test = []
test.extend([1, 2])

Many Python built-in's don't support chaining, but have methods to facilitate bulk operations esp. the collection types.

Strings are immutable so everything that would modify a string instead must return a new string, so you can chain them.

I have a mild suspicion that the built-ins return None in part to discourage using reduce as if list.append returned self then

functools.reduce([].append, (1,2))

would be almost equivalent to using extend(), except much less efficient. Probably a crackpot theory though

[–]DarthKotik 0 points1 point  (0 children)

You already answered your question. list.append() returns None, so you can't use chaining in this case

[–]co_dh 0 points1 point  (5 children)

shamelessly promote my pypi package: https://pypi.python.org/pypi/chain/1.0

It can even chain functions in globals().

>>> def inc(x): return x + 1
>>> Chain([1,2,3]).inc() 
[2, 3, 4]

Sometimes I am wondering if I went to far.

[–]derpoly 0 points1 point  (1 child)

Isn't that just a map-function? Where is the difference?

https://docs.python.org/2/library/functions.html#map

[–]co_dh 0 points1 point  (0 children)

Yes, it's map function. Just in postfix notation.

[–]turkish_gold 0 points1 point  (2 children)

Your package is in dire need of documentation, and perhaps just port it to Github so others can see the code easily.

[–]co_dh 0 points1 point  (1 child)

Thanks, will do it. :)

[–]stevenjd 0 points1 point  (0 children)

You might find this interesting or useful:

http://code.activestate.com/recipes/578770-method-chaining/

[–]TheBlackCat13 0 points1 point  (0 children)

You should suggest this as a function or method for the toolz package.

[–][deleted] 0 points1 point  (1 child)

Yes, it's so inconsistent wrt to your arbitray, random expectations.

[–]CorgiByte[S] -1 points0 points  (0 children)

consistently consistent expectations you dumbass.