1

I have a class that transforms some values via a user-specified function. The reference to the function is passed in the constructor and saved as an attribute. I want to be able to pickle or make copies of the class. In the __getstate__() method, I convert the dictionary entry to a string to make it safe for pickling or copying. However, in the __setstate__() method I'd like to convert back from string to function reference, so the new class can transform values.

class transformer(object):
    def __init__(self, values=[1], transform_fn=np.sum):
        self.values = deepcopy(values)
        self.transform_fn = transform_fn
    def transform(self):
        return self.transform_fn(self.values)
    def __getstate__(self):
        obj_dict = self.__dict__.copy()
        # convert function reference to string
        obj_dict['transform_fn'] = str(self.transform_fn)
        return obj_dict
    def __setstate__(self, obj_dict):
        self.__dict__.update(obj_dict)
        # how to convert back from string to function reference?

The function reference that is passed can be any function, so solutions involving a dictionary with a fixed set of function references is not practical/flexible enough. I would use it like the following.

from copy import deepcopy
import numpy as np

my_transformer = transformer(values=[0,1], transform_fn=np.exp)
my_transformer.transform()

This outputs: array([ 1. , 2.71828183])

new_transformer = deepcopy(my_transformer)
new_transformer.transform()

This gives me: TypeError: 'str' object is not callable, as expected.

worldcitizen
  • 65
  • 2
  • 8

2 Answers2

2

You could use dir to access names in a given scope, and then getattr to retrieve them.

For example, if you know the function is in numpy:

import numpy

attrs = [x for x in dir(numpy) if '__' not in x] # I like to ignore private vars

if obj_dict['transform_fn'] in attrs:
    fn = getattr(numpy, obj_dict['transform_fn'])
else:
    print 'uhoh'

This could be extended to look in other modules / scopes.

If you want to search in the current scope, you can do the following (extended from here):

import sys

this = sys.modules[__name__]

attrs = dir(this)

if obj_dict['transform_fn'] in attrs:
    fn = getattr(this, obj_dict['transform_fn'])
else:
    print 'Damn, well that sucks.'

To search submodules / imported modules you could iterate over attrs based on type (potentially recursively, though note that this is an attr of this).

Community
  • 1
  • 1
sapi
  • 9,944
  • 8
  • 41
  • 71
2

I think if you are asking the same question, I came here for.

The answer is simply use eval() to evaluate the name.

>>> ref = eval('name')

This is going to return what 'name' references in the scope where the eval is executed, then you can determine if that references is a function.

Darrel Lee
  • 2,372
  • 22
  • 22