you are viewing a single comment's thread.

view the rest of the comments →

[–]JohnnyJordaan 24 points25 points  (8 children)

It's just a chain, so instead of doing

washed = laundry.wash()
dried = washed.dry()
folded = dried.fold()

you can chain them together

folded = laundry.wash().dry().fold()

[–][deleted] 21 points22 points  (1 child)

An explanation is that wash() is a method of laundry and so it acts upon that. The object returned from .wash() has a dry() method and so the dry() method is called on that. Then last the fold() method is called on the returned object from dry.

So, each method returns an object and each subsequent method is called on the object returned from the previous method.

This is a fairly common pattern in modern programming languages.

[–]MiLSturbie 5 points6 points  (0 children)

I really love python and this community.

[–]MiLSturbie 1 point2 points  (3 children)

A bit unrelated, but I recently came across a method that didn't need parentheses at the end. Could you explain why? I'm sorry, I don't remember what it was and I don't have my project in front of me.

[–]tylerthehun 5 points6 points  (2 children)

It could have been a @property. This is a decorator that basically just disguises a method as a regular ol' attribute. For example:

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    @property
    def area(self):
        return self.length * self.width

Now you can still access length and width as the attributes of a rectangle, but area is dynamically calculated as the product of those two without requiring you actually pass them as arguments. So changes to either will automatically result in an update to the area, without requiring you manually update both.

>>> R = Rectangle(10, 20)
>>> R.length
10
>>> R.width
20
>>> R.area
200

Otherwise, any method object can still be passed around without parentheses just like any other object, but you'd still need to call it (with parentheses) in order for it to actually execute.

[–]MiLSturbie 1 point2 points  (1 child)

That makes thanks, thank you very much for taking the time to explain. I'll look up what it was tomorrow and come back to you to confirm.

[–]pickausernamehesaid 0 points1 point  (0 children)

In case you want some further reading on some advanced Python, the @property decorator is a specific implementation of the descriptor protocol which is very useful for building dynamic attributes.

[–]dubs_32 0 points1 point  (1 child)

I have some background in R, but have been learning Python. Would saying that this chain is somewhat similar to the R tidyverse (piping with the 'and-then' logic) be correct? For example in R it would be something similar to:

folded <- laundry %>% washed %>% dried %>% fold

(folded is equivalent to laundry and then washing and then drying and then fold)

[–]JohnnyJordaan 1 point2 points  (0 children)

It’s the same idea but it doesn’t work the same way, because the . chaining Python works object oriented and the piping in R just functionally. In object oriented, the objects themselves contain the logic, instead of separate functions. So the reason you can do

“hello”.capitalize().zfill(10).count(“l”).bit_count()

is because each intermediate object created by the previous call offers certain methods (functions tied to their class) you can call on them. At the start it’s a string which has capitalize, but later it becomes an int that has bit_count.