2016-04-04 1 views
2

Je le code suivant:utiliser une fonction à getattr soit pour des fonctions ou des attributs réguliers

In [38]: %paste 
def set_session_attribute(obj, attribute): 
    if attribute.endswith('()'): 
     attribute = attribute.replace('()', '') 
     return getattr(obj, attribute)() 
    else: 
     return getattr(obj, attribute) 


class Thing(object): 
    def __init__(self): 
     self.legs = 4 
    def length(self): 
     return 6 

## -- End pasted text -- 

In [39]: x = Thing() 

In [40]: y = set_session_attribute(x, 'legs') 

In [41]: y 
Out[41]: 4 

In [42]: z = set_session_attribute(x, 'length()') 

In [43]: z 
Out[43]: 6 

En effet, appeler avec "length()" ne fonctionnait pas (AttributeError, no attribute length())

Y at-il une plus courte, plus manière maintenable de faire des fonctions comme celle-ci? Je vous remercie.

Répondre

5

Solution 1

Vous pouvez faire length un property:

class Thing(object): 
    def __init__(self): 
     self.legs = 4 
    @property 
    def length(self): 
     return 6 

>>> thing = Thing() 
>>> thing.legs 
4 
>>> thing.length 
6 

Si vous voulez vraiment utiliser votre fonction:

def set_session_attribute(obj, attribute): 
    return getattr(obj, attribute) 

>>> set_session_attribute(thing, 'legs') 
4 
>>> set_session_attribute(thing, 'length') 
6 

Si vous ne pouvez pas modifier directement la source de thing, vous pouvez le faire après l'importation de la classe:

class Thing(object): 
    def __init__(self): 
     self.legs = 4 
    def length(self): 
     return 6 

ici:

Thing.length2 = property(Thing.length) 

>>> thing = Thing() 
>>> thing.length2 
6 

Solution 2

Alternativement, vous pouvez vérifier si l'attribut est appelable:

class Thing(object): 
    def __init__(self): 
     self.legs = 4 
    def length(self): 
     return 6 

def set_session_attribute(obj, attribute): 
    attr = getattr(obj, attribute) 
    if hasattr(attr, '__call__'): # may use `callable()` 
     return attr() 
    return attr 

>> thing = Thing() 
>>> set_session_attribute(thing, 'legs') 
4 
>>> set_session_attribute(thing, 'length') 
6 
+0

Je ne peux pas changer la fonction que je suis en train d'appeler – codyc4321

+1

Voulez-vous dire la fonction 'set_session_attribute' ou une méthode dans la classe' Thing 'ou une autre fonction? –

+0

Je ne peux rien changer dans les classes auxquelles j'accède, comme Thing(), un énorme système dépend de ceux – codyc4321

1

Décore ces méthodes avec @property, qui selon vous, devrait avoir une sémantique de données plutôt que d'une méthode.

class Thing: 
    @property 
    def length(self): 
     return somedata 

    @property.setter 
    def length(self, value): 
     somename = value 

t = Thing() 
l0 = t.length 
t.length = l1 

C'est donc un getter. Il y a aussi un poseur @property.setter, où vous pouvez faire t.length = somedata au lieu de quelque chose comme t.set_length(somedata)