Is it possible to use function calls as default arguments in other functions?

28 views Asked by At

It seems like Python doesn't accept function calls as default arguments, at least I seem unable to make it work. Following my recent project as an example.

I try to create a simple procedural generated world map using Turtle. As the player moves, square tiles of different colors are created in and around his path following a logic from the function 'choose_terrain(self, coordinates)'. As some colors are not traversable, the player should always start out on a green tile.

def __init__(self):
    self.tiles = {}
    self.create_tile((0, 0), 'green')

def create_tile(self, coordinates, terrain_type=self.choose_terrain(coordinates)):
    print(f'Created at {coordinates}.')
    new_tile = Turtle('square')
    new_tile.color(terrain_type)
    new_tile.penup()
    new_tile.goto(coordinates)


#this is the code in the main-update loop
create_tile(coordinates)

This setup unfortunately doesn't work. The inverse version though, making 'green' the default and specifying the function works though.

def __init__(self):
    self.tiles = {}
    self.create_tile((0, 0))

def create_tile(self, coordinates, terrain_type='green'):
    print(f'Created at {coordinates}.')
    new_tile = Turtle('square')
    new_tile.color(terrain_type)
    new_tile.penup()
    new_tile.goto(coordinates)


#this is the code in the abbreviated main-update loop
create_tile(coordinates, self.choose_terrain(coordinates))

As creating specifically a green tile is the exception and random ones according to the 'choose_terrain'-function the rule, I would like to make the function the default argument and not the other way around. Is there a workaround to make this possible?

Thanks

1

There are 1 answers

0
cdlane On

I could see you doing something like the following:

from turtle import Screen, Turtle

class Tile():
    def __init__(self):
        self.tiles = {}
        self.create_tile((0, 0), lambda self, coordinates: 'green')

    def choose_terrain(self, coordinates):
        # in actual code, compute/lookup this result!
        return 'red'

    def create_tile(self, coordinates, terrain_method=choose_terrain):
        print(f'Created at {coordinates}.')

        new_tile = Turtle('square')
        new_tile.color(terrain_method(self, coordinates))
        new_tile.penup()
        new_tile.goto(coordinates)

        self.tiles[coordinates] = new_tile.pencolor()

screen = Screen()

tiler = Tile()  # a green initial tile

# this is the code in the main-update loop
tiler.create_tile((100, 100)) # an additional red tile

screen.mainloop()

That is, don't pass the result of calling the choose_terrain method but rather one or more alternative methods themselves as arguments.