Is it possible to parametrize a method being called by dot notation?

Viewed 55

Just what the title says, I'm trying to figure out if you can parametrize a method being call via dot notation.

def funk(x,a_class_method):
    return [i.a_class_method() for i in x]
    
a_class_method = upper
funk(x,a_class_method)

input

x = ['hi', 'my', 'name', 'is', 'frank']

desired output

['HI', 'MY', 'NAME', 'IS', 'FRANK']

As written this results in

NameError: name 'upper' is not defined

3 Answers

As a general rule, passing around the name of a function is not a good way to think about/do things. Just pass functions:

def funk(x, f):
    return [f(i) for i in x]

funk(['hi', 'my', 'name', 'is', 'frank'], str.upper) # pass the method itself
# str.upper(x) is the same as x.upper() for any str x
# or write
funk(['hi', 'my', 'name', 'is', 'frank'], lambda x: x.upper()) # pass a function that calls the method
# (lambda x: x.upper())(y) is the same as y.upper()
# you could also write the following (but why would you?)
def oneOffFunction(x):
    return x.upper()
funk(['hi', 'my', 'name', 'is', 'frank'], oneOffFunction) # pass another function that calls the method

Using the first form requires you know the type of the objects you're calling the method on. Using the second and third you call the method purely by name, regardless of type. You would rarely want/need the getattr way.

Note that funk(xs, f) is equivalent to list(map(f, xs)).

As long as the return value of the method matches the data type in the position on the parameter definition.

Regards,

I found a workaround:

def funk(x,a_class_method):
    return [getattr(i, a_class_method)() for i in x]
    
a_class_method = upper
funk(x,a_class_method)


Related