William
William

Reputation: 542

Reducing a function using dictionary

I have two functions that are very similar:

def hier_group(self):
    if self.sku:
        return {f"{self.hierarchic}": f"${self.hierarchic}", "id": "$id", "ix": "$ix"}
    else:
        return {f"{self.hierarchic}": f"${self.hierarchic}", "ix": "$ix"}

def hier_group_merge(self):
     if self.sku:
         return {f"{self.hierarchic}": f"${self.hierarchic}", "id": "$id"}
     else:
         return {f"{self.hierarchic}": f"${self.hierarchic}"}

I am trying to reduce into 1 function that has only one if/else.

The only difference in both functions is "ix": "$ix".

What I am trying to do is the following:

def hier_group(self, ix=True):
       if self.sku:
           return {f"{self.hierarchic}": f"${self.hierarchic}", "id": "$id" f'{',"ix": "$ix"' if ix == True else ""}'}
       else:
           return {f"{self.hierarchic}": f"${self.hierarchic}"  f'{',"ix": "$ix"' if ix == True else ""}'}

But it's getting trick to return , "ix": "$ix".

Upvotes: 0

Views: 42

Answers (2)

chepner
chepner

Reputation: 532093

Build a base dictionary, then add keys as appropriate.

def hier_group(self, ix=True):
    d = { f'{self.hierarchic}': f'${self.hierarchic}' }
    if self.sku:
        d['id'] = '$id'
    if ix:
        d['ix'] = '$ix'
    return d

However, there are many who believe using two functions, rather than having one function behave like two different functions based on a Boolean argument, is preferable.

def hier_group(self):
    d = { f'{self.hierarchic}': f'${self.hierarchic}' }
    if self.sku:
        d['id'] = '$id'
    return d

def hier_group_with_ix(self):
    d = self.hier_group()
    d.update('ix': '$ix')
    return d

You might also use a private method that takes an arbitrary list of attribute names.

# No longer needs self, so make it a static method
@staticmethod
def _build_group(attributes):
    return {f'{x}: f'${x} for x in attributes}


def build_group(self, ix=True):
    attributes = [self.hierarchic]
    if ix:
        attributes.append('ix')
    if self.sku:
        attributes.append('id')
    return self._build_group(attributes)

You will probably ask: why is using a Boolean attribute here OK? My justification is that you aren't really altering the control flow of build_group with such an argument; you are using it to build up a list of explicit arguments for the private method. (The dataclass decorator in the standard library takes a similar approach: a number of Boolean-valued arguments to indicate whether various methods should be generated automatically.)

Upvotes: 2

Thierry Lathuille
Thierry Lathuille

Reputation: 24279

You can avoid repeating common parts:

def hier_group(self, ix=True):
    out = {f"{self.hierarchic}": f"${self.hierarchic}"}
    if self.sku:
        out["id"] = "$id"
    if ix:
        out["ix"] = "$ix"

Upvotes: 1

Related Questions