Comment puis-je modifier l'espace de noms local d'une fonction en python? Je sais que les habitants () renvoie l'espace de noms local de la fonction lorsqu'il est appelé à l'intérieur de cela, mais je veux faire quelque chose comme ça (j'ai une raison pour laquelle je veux faire cela où g n'est pas accessible à F, mais il est plus rapide de donner Un exemple trivial et stupide pour illustrer le problème):
7 Réponses :
Étant donné que la fonction n'est pas invoquée, elle n'a pas encore de cadre de pile "local". La solution la plus simple consiste à utiliser un contexte global: ou vous pouvez définir g sur l'objet de fonction: p> mais je ' Je ne sais pas comment vous pouvez obtenir l'objet de fonction dans la fonction elle-même. Si c'était une méthode, vous utiliseriez auto code>. P> p>
Si vous vraiment i> voulait utiliser l'objet de fonction à l'intérieur de la fonction, vous pouvez utiliser Inspecter: Import Inspecter Importer pPrint def Fn Fn (): image = inspect.CurrentFrame () Imprimer image.f_globals [cadrent. CO_NAME] .g fn.g = 'hello' fn ()
C'est cassé pour des fonctions de classe, des fonctions imbriquées / des fermetures et des lambdas, et tout ce qui est décoré - il retournera la fonction d'emballage du décorateur, pas la fonction réelle.
Et si f code> est une méthode de classe / instance?
Une fonction qui n'exécute pas n'a aucun local; Le contexte local est créé lorsque vous exécutez la fonction et détruit lors de son sortie, il n'ya donc aucun "espace de noms local" à modifier de la fonction extérieure.
Vous pouvez faire quelque chose comme ça, bien que: P>
def f(): g = [1] def func(): print g[0] return func, g f, val = f() f() val[0] = 2 f()
Ce site devrait vraiment exiger des explications pour -1 votes, afin que les gens ne puissent donc pas voter de manière anonyme de réponses correctes sans raison.
Je pense que vous pourriez résoudre le problème de la résoudre d'un point complètement différent.
Les fonctions sont des objets, avec leurs dictionnaires; Par conséquent, vous pouvez ajouter g to f, et l'utiliser:
def g(): print "g" def f(): f.g() f.g = g
Cela ne fonctionne que pour les fonctions globales; Il n'y a aucun moyen d'accéder à FE de manière fiable à partir de f.
Pourriez-vous développer cela? Les fonctions Python sont des objets et il n'y a pas de différence si local ou global - sauf si vous voulez dire Méthodes i> Mais c'est une histoire complètement différente, et pas ce que l'OP ne demandait pas.
Et si f code> est une méthode de classe / instance?
Pourquoi ne pas simplement ajouter un argument à f () code> et transmettez une référence à
g () code>?
def g():
pass
def f(func):
func()
f(g)
Je suppose que vous voulez faire cela, car la fonction F est définie non par vous, mais par un autre module. Donc, vous voulez changer comment F () fonctionne. En particulier, vous voulez changer ce que l'on appelle quand g est appelé.
Je vais suggérer ceci: p> Ceci changera le Global G pour le module troisièmeparyporypackage . Alors, quand troisièmepartorypackage.f () est appelé maintenant, il appellera myNewg () au lieu de g (). P> si cela ne le résout pas, peut-être que g () est en fait importé à partir de F ( ), ou quelque chose. Ensuite, la solution est la suivante: p> c'est-à-dire que vous remplacez complètement F () avec une version modifiée qui fait ce que vous voulez. P> p>
Vous avez quelques options. Premièrement, notez que g dans votre exemple n'est en réalité pas une locale à la fonction (c.-à-d. Non attribuée à celle-ci), c'est un global (c'est-à-dire n'a pas été attribué à une variable locale). Cela signifie que cela sera recherché dans le module que la fonction est définie. Ceci est chanceux, car il n'ya aucun moyen de modifier les locaux à l'extérieur (à court de correction du bytecode), car ils sont attribués lorsque la fonction fonctionne, pas avant. < P> Une option est simplement d'injecter votre fonction dans l'espace de noms du module de la fonction. Cela fonctionnera, mais affectera toutes les fonctions de ce module qui accède à la variable, plutôt que la seule fonction unique. P>
Pour affecter une seule fonction, vous devez plutôt faire valoir que func_globals ailleurs. Malheureusement, il s'agit d'une propriété en lecture seule, mais vous pouvez faire ce que vous voulez en recréant la fonction avec le même corps, mais un espace de noms global différent: p> f sera maintenant Soyez indicial, sauf qu'il recherchera des globaux dans la dicte fournie. Notez que cela rebinets l'espace de noms global entier - s'il y a des variables là-bas que f le em> lève les yeux, assurez-vous de les fournir aussi. Ceci est également assez hacky cependant, et peut ne pas fonctionner sur des versions de Python autres que CPPHON. P> P>
Je ne sais pas si c'est "bon" code, mais c'était exactement ce que je voulais. Je convertissez une base de code à un autre et je voulais pouvoir simuler une construction de langues de l'autre langue. L'autre langue peut emballer le code et ajouter ou supprimer ce code de l'espace de noms. Il est utile de remplacer différentes fonctions. Il manipule donc l'espace de noms dans une pile comme la mode. C'est la chose la plus proche que je puisse trouver cela me permettrait de le faire efficacement. Merci
Quel est ce nouvelle code> bibliothèque?
Cela semble fonctionner
Cela ne fonctionne pas dans une fonction. Il n'ajoute pas la valeur à l'espace de noms.
Quel est votre objectif ultime en utilisant cette technique étrange? Pourquoi vous ne pouvez pas simplement définir g () avant f ()?
J'ai essayé de jouer avec l'espace de noms d'une fonction à l'exécution précédemment (pour tester / moquer) et échoué ... juste fyi.
Qu'est-ce que diable est
add_to_locals code>? Cela ne semble pas exister pour moi.
attributError: "fonction" objet n'a aucun attribut 'add_to_locals' code>
@Charlieparker Ça n'existe pas. C'est ce qu'il tente de mettre en œuvre / demander s'il existe une solution à faire.
Avez-vous réussi à obtenir cela pour travailler?