Cameron Atkinson
Cameron Atkinson

Reputation: 101

Method chaining in python like in java?

I vaguely remember from my days of Minecraft modding that in java, you can set multiple class variables in one line, like this:

SomeBlock.hardness(0.5).isOpaque(True).blastResistance(2).etc.etc

Well I was wondering if there was a way to do something similar in python. I have tried doing the same thing in python, but the second one ends up thinking it is supposed to modify the return of the first one instead of the original class.

Is there a way to do this?

Upvotes: 1

Views: 332

Answers (3)

hpaulj
hpaulj

Reputation: 231738

the second one ends up thinking it is supposed to modify the return of the first one instead of the original class. Yes that is the normal Python syntax. Returning self does not create a special syntax. It just ensures the returned object is the correct one for chaining.

Your initialization task is more commonly coded as

class SomeBlock():
    def __init__(self, hardness=None, opaque=False, blastResistance=None):
        self.hardness = hardness
        self.opaque = opaque
        self.blastResistance = blastResistance

ablock = SomeBlock(hardness=0.5, opaque=True, blastResistance=2)

And because Python does not require methods for accessing attributes, you can also write

ablock = SomeBlock()
ablock.hardness = 0.5
...

So if a method does return self, it's usually to implement a more complex that setting attributes.

It's more common to have method return a new object of the same class. This is typical, for example, of many of the numpy array methods. A.dot(B) returns new array, the result of taking the dot product of A and B. A.dot(B).dot(C) may look like chaining, but is just a sequence of actions on successive arrays.

Upvotes: 0

markusw
markusw

Reputation: 2065

This is just a fluent interface, which is desgined to be like that. It is mostly created by returning the same object:

class Test:
  def setX(self, x):
    self.x = x
    return self

  def setY(self, x):
    self.y = y
    return self


 t = Test()
 t.setX(12).setY(11)

Upvotes: 2

George Karpenkov
George Karpenkov

Reputation: 2124

Yes, you can, in fact it is done the same way it is done in Java: by returning the self reference.

class SomeBlock(object):
    def hardness(self, blah):
        self.hardness = blah
        return self
    def isOpaque(self, value):
        self.isOpaque = value
        return self

a = SomeBlock()
a.hardness(0.5).isOpaque(true)

Upvotes: 4

Related Questions