2009-05-13 5 views
0

Est-ce que python a une fonction comme call_user_func() en PHP?Est-ce que python a un call_user_func() comme PHP?

Version PHP:

call_user_func(array($object,$methodName),$parameters)  

Comment puis-je obtenir ce qui précède en Python?

+0

Vous pouvez simplement l'appeler comme ceci: obj.nom_méthode (paramètres). Qu'essayez-vous d'accomplir? –

+0

Soit il y a deux de classes- classe Spam (objet): ... classe Egg (objet): ... J'ai une variable: cls_name #will être soit Spam ou Egg Je veux pour pouvoir appeler la méthode __init __() de la classe dont le nom est stocké dans la méthode cls_name. J'espère avoir été clair. – rubayeet

+0

Pourquoi appelleriez-vous l'initialiseur d'une classe déjà initialisée? En tout cas, c'est une question très différente. S'il vous plaît modifier votre question pour convenir. – Arafangion

Répondre

1

Picking quel objet à instancier n'est pas si difficile. Une classe est un objet de première classe et peut être affectée à une variable ou transmise en tant qu'argument à une fonction.

class A(object): 
    def __init__(self, arg1, arg2): 
     etc. 

class B(object): 
    def __init__(self, arg1, arg2): 
     etc. 

thing_to_make = A 
argList= (some, pair) 
thing_to_make(*argList) 

thing_to_make = B 
argList- (another, pair) 
thing_to_make(*argList) 

def doSomething(class_, arg1, arg2): 
    thing= class_(arg1, arg2) 
    thing.method() 
    print thing 

Tout fonctionne bien sans trop de douleur. Vous n'avez pas besoin d'une sorte de "call_user_function" en Python

+0

a aimé cette idée. Je vous aurais donné le droit de vote si le débordement de la pile me permettait de le faire. merci – rubayeet

8

Je ne vois pas le problème, sauf si methodName est une chaîne. Dans ce cas getattr fait le travail:

>>> class A: 
...  def func(self, a, b): 
...   return a + b 
... 
>>> a = A() 
>>> getattr(a, 'func')(2, 3) 
5 

Si object est également une chaîne, cela fonctionnerait, en utilisant globals ou locals (mais vous pouvez avoir d'autres, plus grands, problèmes):

>>> getattr(locals()['a'], 'func')(2, 3) 
5 
>>> getattr(globals()['a'], 'func')(2, 3) 
5 

Modifier: pour votre clarification. Pour initialiser un objet basé sur une chaîne:

>>> class A: 
...  def __init__(self): print('a') 
... 
>>> class B: 
...  def __init__(self): print('b') 
... 
>>> clsStr = 'A' 
>>> myObj = locals()[clsStr]() 
a 

Je ne sais pas si cela est vraiment ce que vous voulez bien ... sauf si vous avez beaucoup de classes différentes, pourquoi ne pas simplement effectuer une correspondance de chaîne?


Une autre édition: Bien que les travaux ci-dessus, vous devriez sérieusement envisager d'aller avec une solution telle que fournie par Ignacio Vazquez-Abrams. D'une part, en stockant toutes les classes possibles dans un dict, vous évitez un comportement étrange qui peut résulter de la transmission d'un argument de chaîne incorrect qui correspond au nom d'une classe non apparentée dans la portée actuelle.

+1

eval est le mal. Mieux vaut utiliser globals() ou locals() à la place. – muhuk

+0

muhuk: Comment pourriez-vous * instancier * un nouvel objet de sa classe, en lui donnant un exemple d'objet? – Arafangion

+0

@muhuk: Vous avez raison. J'ai décidé d'enlever eval() de ma réponse (ceux qui sont intéressés peuvent toujours voir l'historique des changements). – Stephan202

1

Pour un objet donné 'obj', une méthode nom de 'meth', et un ensemble de args "de les arguments donnés:

obj.__getattribute__(meth)(*args) 

Si vous y.

Bien sûr, il va sans dire - Que diable voulez-vous faire?

0

Vous pouvez appeler utiliser getattr avec la population locale() ou globals() à faire quelque chose de similaire

# foo.method() is called if it's available in global scope 
getattr(globals()['foo'], 'method')(*args) 

# Same thing, but for 'foo' in local scope 
getattr(locals()['foo'], 'method')(*args) 

Voir aussi: Plongez au coeur de Python sur getattr(), sur locals() and globals()

+0

N'a pas répondu à la question - sauf si $ object est l'espace de noms global. – Arafangion

+0

(la version éditée) Fait la même chose. $ object doit exister quelque part pour l'exemple PHP (soit dans la fonction soit dans la portée globale) – Imran

+0

Je supprimerais mon vote négatif si le débordement de la pile me le permettait, car il semble maintenant bon. (Apparemment, c'est trop vieux). – Arafangion

4

Si vous avez besoin d'utiliser des classes de lieux lointains (et en fait, si vous avez besoin de cours du tout), alors il vaut mieux créer et en utilisant un dictionnaire pour eux:

funcs = {'Eggs': foo.Eggs, 'Spam': bar.Spam} 

def call_func(func_name, *args, **kwargs): 
    if not func_name in funcs: 
     raise ValueError('Function %r not available' % (func_name,)) 
    return funcs[func_name](*args, **kwargs) 
+0

Dans la plupart des cas, cette solution doit être préférée à l'astuce (quoique plus générale) locale()/globals(). – Stephan202

+0

... c'est pourquoi j'ai maintenant référencé cette réponse dans ma réponse, avec un argument supplémentaire pour son utilisation. – Stephan202

Questions connexes