Question

I'm refactoring some code, and I thought I could use a bit of Reflection! So, I have this for now:

def f(self, clazz):
    [...]
    boolean = False
    if hasattr(clazz_instace, 'some_attribute'):
        setattr(clazz_instace, 'some_attribute', True)
        boolean = True

    if boolean:
        result = getattr(clazz_instace, 'another_method')(None, request=request)
        return result['objects']

    sorted_objects = getattr(clazz_instace, 'One_more_method')(request)
    result = getattr(clazz_instace, 'another_method')(sorted_objects, request=request)

    return [...]

My question is about the strings I used to indicate which method I'm searching for regarding to the clazz_instance. I'd like to know if there's another and very best way to do what I did (In a dinamic way to be specific)? I mean, intead of putting method's name like strings directly as I did, would be really nice if I could verify dinamically those methods, differently.

Could you give some nice ideas? How would you do it?

Thanks in advance!!!

Was it helpful?

Solution

An instance's method is nothing more than a function object stored in the instace's __dict__. This said, you are doing correct to find them, except that maybe, the class indeed has the attribute corresponding to your argument string, but is not a function, is just another type instead.

If you depend on this, I recommend you refactor the instance's function looking code into a helper method:

import types
def instance_has_method(instance, name):
    try:
        attr = getattr(instance, name)
        return isinstance(attr, types.FunctionType)
    except AttributeError:
        return False

Once you have this function, your code will be more concise because now you're sure that the attribute is indeed a function and can be callable.

The code above checks if the attribute is a function. If you want something wider, you can check if it's a callable like this: return hasattr(attr, '__call__').

In python, this is basically how you check for attributes inside classes. I don't think there's nothing wrong with your approach and not another more clever way to do reflection.

Hope this helps!

OTHER TIPS

It's not easy to understand what you are trying to achieve.

getattr(clazz_instace, 'One_more_method')(request) is just a fancy way to say clazz_instace.One_more_method(request).

Use of getattr is reasonable when you don't know the method name in advance, that is, if your method name is variable.

Also, setattr(clazz_instace, 'some_method_inside_this_class', True) turns alleged some_method_inside_this_class into a scalar attribute inside that class, having a True value. Probably this is not what you planned to have.

My best effort to understand your code is this:

def f(clazz):
  # if clazz is capable of better_processing, use it:
  if hasattr(clazz, 'better_processing'):
    return clazz.better_processing(...)
  else:
    return clazz.basic_processing(...)

BTW what getattr gives you is a callable method, you can directly use it, like this:

method = getattr(clazz, 'better_method', clazz.default_method)
# if 'better_method' was available, it was returned by getattr;
# if not, the default method was returned.
return method(clazz_instance, some_data...)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top