I know that I can add a variable to the global namespace "by name" with something like:
def getNewVar(name,val):
globals()[name]=val
The things is, I would like to do this in a local namespace. I have already tried and failed in using locals() instead of globals(). Someone probably wants to know why I would do something like this. OK, in my use case, the argument to the function is actually a dictionary, and I would like to do something like:
def processDictEntries(dict):
for varname in dict.keys():
locals()[varname]=dict[varname] # won't work, of course
This way, further down in the function, I won't have to keep typing
result1=dict['var1']+5.
result2=dict['var2']*dict['var7']
over and over again. I can just type
result1=var1+5
result2=var2*var7
And, if there is a way to do this in a small loop like I have written, then I don't have to do:
var1=dict['var1']
var2=dict['var2'] etc.
either. I'm really just looking for economy of code; it's a big dictionary.
BTW, the entries of the dictionary are never altered; it is strictly input. And, yes, I know that if the input dictionary lacks one of the variables the function needs, I will be in touble, but I think that can be dealt with. Thanks!
If you can change how you call the function:
def processDictEntries(var1=None,var2=None,**kwargs):
#do stuff with var1,var2 ...
And then call the function as:
processDictEntries(**dict)
and of course, if you can't do that, you can always use processDictEntries as a wrapper:
def _processDictEntries(var1=None,var2=None,**kwargs):
...
def processDictEntries(d):
return _processDictEntries(**d)
As a side note, it's not a good idea to name a variable dict as then you shadow the builtin function
Related
Does anyone know how to call a child function that belongs to a parent function using the dot operator, but where the child function's name is stored in a string variable.
def parent_function():
# do something
def child_function():
# do something else
Now imagine I have a string called 'child_function'. Is there a way to do this:
method_name = 'child_function'
parent_function.method_name()
I understand that method_name is a string and so it is not callable. The syntax above is clearly wrong, but I wanted to know if there was a way to do this?
Thank you!
As others have pointed out in comments there will need to be a little more setup to actually call an inner function, such as a parameter like this:
def parent_function(should_call=False):
# do something
def child_function():
print("I'm the child")
if should_call:
child_function()
That being said, and to answer your specific question, you technically can call the inner function directly. I should note this is bad and you should not be doing this. You can access the inner function via the outer function's code object
exec(parent_function.__code__.co_consts[1])
As opposed to many comments, you can actually access inner functions even if the outer function is not in the system memory anymore. This technique in python is called closure.
To know more about closure, visit Programiz
Coming to your requirement, you need to call the nested method outside the nesting function.
What are we leveraging?
Closure technique of python
locals() method which returns all the local properties and methods inside an enclosing method.
lambda x: x, A anonymous (Lambda) function
def parent_function():
# do something
def child_function():
# do something else
print("child_function got invoked")
return {i: j for i, j in locals().items() if type(j) == type(lambda x: x)}
# locals() returns all the properties and nested methods inside an enclosing method.
# We are filtering out only the methods / funtions and not properties / variables
parent_function()["child_function"]()
The below is the output.
>>> child_function got invoked
Better Solution:
Instead of using nested methods, leverage the concept of classes provided by Python.
Enclose the nested functions as methods inside a class.
If you include global child_function in parent_function, then once you run parent_function, you can call child_function in the main program. It's not a very clean way of defining functions, though. If you want a function defined in the main program, then you should define it in the main program.
Consider the following case:
def parent_function():
a = 1
Can you access a from the global scope? No, because it is a local variable. It is only existent while parent_function runs, and forgotten after.
Now, in python, a function is stored in a variable just like any other value. child_function is a local variable just like a. Thus, it is in principle not possible to access it from outside parent_function.
Edit: unless you make it available to the outside somehow, e.g. by returning it. But then, still the name child_function is internal to parent_function.
Edit 2: You can get functions given by name (as string) by using the locals() and globals() dictionaries.
def my_function():
print "my function!"
func_name = "my_function"
f = globals()[func_name]
f()
when should we actually create a function that has parameters / arguments?
today I made a programming project. Then it occurred to me when should I actually create a function that has parameters .. I usually create it when there is a global value / variable and that value must exist in some function then I make that value the argument of the function .. did I do it right? or wrong? if wrong what are the best practices for doing it?
varGlobal = "test"
def foo():
print(varGlobal)
# or
def foo(parm):
print(parm) # parm -> varGlobal
def foo():
ask = input("ask")
print(ask)
# or
def foo(parm):
print(parm) # parm -> global user input
It's usually a good idea to use parameters. Consider what the purpose of the function is. Parameterized functions are more generally useful than non-parameterized functions.
If the first case, is whatever foo does applicable only to a single value, or could it be useful for arbitrary values, regardless of what variable might refer to them? In the former case, you are stuck using varGlobal. In the latter, the call can always use foo(varGlobal) if that's the necessary argument.
In the second, might foo be useful to someone who already has a value, and doens't need to call input? In the former case, you are stuck calling input. In the latter, the caller can always use foo(input()) or the like if they really need to call input.
I would strongly suggest that you should use parameters and arguments in every function. it simply makes the whole process of design simpler.
You can clear see what data the function uses, and what it returns.
The only use of global values (either module globals, or globals imported from other modules are :
Module or application wide constants
Module or application wide function or classes (which are in Python efectively module level 'globals'.
Your functions should always return values and never change a global value (by definition if you stick to the above list that you wont be changing anything).
In my opinon using the 'global' keyword is never needed (in 8 years of coding I have never needed it, or identified a reason to use it).
Using global variables is bad practice in any language GlobalVariablesAreBad
Global variables can be used if you need to access or modify the variable in several methods/classes in the same module.
Remember you need to point global my_global_variable to modify the variable.
Parameters are variables needed in the method to do the processing. These variables should live locally in the method. If you need to retrieve something from the method, you should add a return statement. Also, if you need to return several variables you can return as tuple.
So, in this way, you're organizing your code, making all variables visible to other people. Also I recommend you to use docstrings to fully document your methods, variables and processing.
When we need to solve the same sort of question but with different arguments. So you don't have to write the same function over and over again. Let's say you want to write a function that will return the square of the provided number as an argument.
So you write
def square(num):
return num*num
So every time you need to have square of a number..you just put that number in place of the argument and not write the whole function again.
For example
class c:
var = 15
getattr(c, 'var')
or
i = 0
globals()['i'] = 25
why here our variable writing like string type.
I saw this in some built-in functions and in Django and i think this make code much difficulty for understanding isn't it?
globals() returns a dictionary, so you have to use the variable name as string for looking at it. In globals()['var'], 'var' is just a key in globals() returned dict, so it must be given as string.
getattr(c, 'var') looks for attribute "var" in c.__dict__.
Remember: Python makes a heavy us of dicts.
If you know the variable names beforehand, and they are constant, then you can do both these things in a different way:
getattr(c, 'var')
This is a shorthand for:
try:
return c.var
except AttributeError:
if have_default: # hand-wavey "more to this" for a later lesson
return default
raise
and
globals()['i'] = 25
is a nasty way of doing
global i
i = 25
The method you've given is essentially reaching into the internals and fiddling around with them. using the global keyword is the better way to declare that you are use a variable in the global scope, because when the function is interpreted python knows that the variable is from a different scope at that point.
However if you don't know the name of the variable beforehand, then you'd be forced to do it the way in your examples. (but please, please think twice before using the globals one. Putting arbitrary variables in a module's global namespace at runtime? *shudders*)
How do I iterate through a list whose name will be dynamically generated?
boneList_head =['def_neck', 'def_armbase']#hard coded list
itemType='head'# result of a user button press
...
def selectBones():
global itemType
bones =('boneList_'+itemType)# evaluates as a string , not name of a list
for bone in bones:
cmds.select(bone, tgl=True)
the problem is bones is getting evaluated as a string, when I need it to evalute as the name of a list.
Dynamically generating variable names is almost always a bad approach. Use a dictionary!
bonedict = {'boneList_head': ['def_neck', 'def_armbase']}
itemType='head'
def selectBones(itemType):
bones = bonedict['boneList_' + itemType]
for bone in bones:
cmds.select(bone, tgl=True)
Please ignore my previous answer (visible in my edit history) which was stupid -- boneheaded, even. But I blame its stupidity on dynamic variable name generation!
Let me elaborate on why dynamic variable name generation is a bad idea.
Because dynamic variable generation masks variable name definitions. It's hard to tell what has been defined and what hasn't, so it's easy to accidentally redefine a variable. This is a major source of potential bugs.
Because dynamic variable manipulation hides state changes under another layer of obfuscation. To some degree, this is true anytime you create a dictionary or a list. But one expects lists and dictionaries to demand a little extra thinking. Variable names, on the other hand, should be dead simple. When variable definitions and redefinitions require deep thought to understand, something is wrong.
Because dynamic variable generation pollutes the namespace. If you have so many variables that you have to automatically generate them, then they should live in their own namespace, not in the locals of a function, and definitely not in the global namespace. In his style guide for the linux kernel, Linus Torvalds advises that if a function has more than 5-10 local variables, you're doing something wrong.
Because dynamic variable generation contributes to high coupling, which is a bad thing. If you assign to values to a dictionary, you can pass that dictionary back and forth until the cows come home, and all anyone has to know about is that dictionary. If you dynamically create variable names in the global namespace of a module, then if another module wants to access those variable names, it has to know all about the way they were generated, what other variables in that module are defined, and so on. Also, passing the variables around becomes much more complex -- you have to pass around a reference to the module itself, probably using sys.modules or other questionable constructs.
Because dynamic variable generation is ugly. eval looks neat and clean, but it really isn't. It can do anything. Functions that can do anything are bad, because you can't tell at first glance what they're doing here. A well-defined function does one thing, and does it well; that way, whenever you see that function, you know exactly what's happening. When you see eval, literally anything could be happening. In this sense, eval is like goto. The problem with goto is not that you can't use it correctly; it's that for every possible correct use of goto, there are 500,000,000 terrifyingly wrong ways to use it. I won't even discuss the security problems here, because in the end, that's not the real problem with eval.
I agree with the other comments that your approach is probably not the best. But the following should work:
bones = eval('boneList_' + itemType)
This will run the python interpreter on "boneList_head", and return the list.
NOTE: As Adam Mihalcin mentioned in the comments, you should be very careful about only running eval on data that you trust or have validated. A malicious user could inject arbitrary code into the itemType variable to access the os, etc.
This is an ugly hack, but it works...(of course, you need to get the correct module)
import sys
boneList_head =['def_neck', 'def_armbase']
itemType='head'
...
def selectBones():
global itemType
bones=vars(sys.modules["__main__"])['boneList_'+itemType]
for bone in bones:
cmds.select(bone, tgl=True)
This really isn't different than what other people are saying however-- We're using vars to construct a dictionary to get the list you want -- why not just pass a dictionary (or the correct list) to the function selectBones in the first place?
I'm trying to create a function to delete another function.
def delete_function(func):
del func
is what I have so far, but for some reason it doesn't work.
def foo():
print("foo")
delete_function(foo)
doesn't seem to do the trick. I know one can do it easily, just
del(foo)
but I'm trying to do it a different way. How?
Deleting a function isn't really something you do to the function itself; it's something you do to the namespace it lives in. (Just as removing the number 3 from a list isn't something you do to the number 3, it's something you do to the list.)
Suppose you say
def foo(x): return 1
bar = foo
Then (more or less) you have two names, foo and bar, for the exact same function. Now suppose you call delete_function(foo) or delete_function(bar). The exact same thing, namely a function object, is being passed to delete_function. But what you actually want to remove is the association between the name foo or bar and that object -- and there's no possible way delete_function (however you define it) can know whether it's foo or bar or something else you're wanting to get rid of.
(Well ... Actually, there is. There are nasty hacky things you can do that would let the code in delete_function know more about how it was called. But don't even think about thinking about them.)
So. Your options are as follows. (1) Nasty hacky things, as just mentioned. Don't. (2) Pass delete_function not the function object but information about the name of the function and the thing you're trying to delete it from. This is ugly and ungainly. (3) Don't bother.
I strongly recommend #3, unless the only reason you're doing this is to learn more about how Python works. In the latter case, a good place to begin might be http://docs.python.org/reference/executionmodel.html.
Since foo is a global, you can delete it from the global definitions:
def delete_func(func):
del globals()[func.func_name]
It just won't work.
What you are trying to do is, essentially, the name space of the caller.
Try this:
print "0", locals()
def foo(): pass
print "1", locals()
del foo
print "2", locals()
Note that
the locals dict at 0 and 2 are identical, and at 1 nearly - except it has the additional assignment of foo.
del is a statement and not a function
If you do the del in a function delete_function(), essentially the assignment within your function gets removed (which is effectless because the function is terminated immediately), while the caller keeps the assignment.
Strictly spoken, del does not delete objects, but merely assignments from names to objects. Objects get deleted "automatically" (garbage collected) as soon as they are not referenced any longer.
It COULD work what you try to do by inspection of the stack frame and passing of the name to be deleted as a string, but it would be a PITA.
Maybe you try
del locals()['foo']
or
locals()['foo'] = 42
? But I think it is not guarantteed that it really modifies the real locals dictionary, it might as well operate on a copy and thus stay effectless...
If you're using python 3, this should work:
def foo():
return 'foo'
del foo