New to python programming here. I need some help understand why this does not work:
import x.y # x is a package with __init__.py
def func1(x.y.z): # I get a syntax error here
It works when I do this:
import x.y
a = x.y.z
def func1(a):
I've search the web and can't find anything that would answer this somewhat directly.
Thanks.
With def you define new functions which accept some possibly unknown(!) arguments.
So, def sin(x): means "define a function called sin that accepts one argument". Note that this code means that x can be absolutely anything, the function definition doesn't (and cannot) apply any restrictions on its type, value, size, etc.
When you do
a = "hello"
def test(a):
pass
The a in the function definition is merely an argument that doesn't have any relation to any other a you use in your code! You could've called it x, pi, z or whatever as the name doesn't really matter (code readability aside).
When you try to write
def test(x.y.z):
pass
You get a syntax error as there exist restrictions on the variables' and arguments' names that don't allow you to call a variable any name you want. Why? Simply because otherwise you'll get a lot of uncertainty. For example, how to parse this:
# a poorly formatted number literal or a variable definition??
1234hello = "test"
# attempt to access a member of a class (or module) or a variable definition??
x.y.z = 5
# is "yay a variable's name or a poorly formatted string literal??
x = "yay - 5
# the same question as above
f' = df/dx
A function argument is a variable, so the very same restrictions are imposed on it as well.
BTW, take a look at the SO code highlighter going nuts trying to highlight the code above.
Related
Is there a way to limit function so that it would only have access to local variable and passed arguments?
For example, consider this code
a = 1
def my_fun(x):
print(x)
print(a)
my_fun(2)
Normally the output will be
2
1
However, I want to limit my_fun to local scope so that print(x) would work but throw an error on print(a). Is that possible?
I feel like I should preface this with: Do not actually do this.
You (sort of) can with functions, but you will also disable calls to all other global methods and variables, which I do not imagine you would like to do.
You can use the following decorator to have the function act like there are no variables in the global namespace:
import types
noglobal = lambda f: types.FunctionType(f.__code__, {})
And then call your function:
a = 1
#noglobal
def my_fun(x):
print(x)
print(a)
my_fun(2)
However this actually results in a different error than you want, it results in:
NameError: name 'print' is not defined
By not allowing globals to be used, you cannot use print() either.
Now, you could pass in the functions that you want to use as parameters, which would allow you to use them inside the function, but this is not a good approach and it is much better to just keep your globals clean.
a = 1
#noglobal
def my_fun(x, p):
p(x)
p(a)
my_fun(2, print)
Output:
2
NameError: name 'a' is not defined
Nope. The scoping rules are part of a language's basic definition. To change this, you'd have to alter the compiler to exclude items higher on the context stack, but still within the user space. You obviously don't want to limit all symbols outside the function's context, as you've used one in your example: the external function print. :-)
For example, I'd like to do something like: greet(,'hola'), where greet is:
def greet(person='stranger', greeting='hello')
This would help greatly for testing while writing code
Upon calling a function you can use the variable names to make it even more clear what variable will assume which value. At the same time, if defaults are provided in the function definition, skipping variables when calling the function does not raise any errors. So, in short you can just do this:
def greet(person='stranger', greeting='hello')
print('{} {}'.format(greeting, person))
return
greet(greeting='hola') # same as greet(person='stranger', greeting='hola')
# returns 'hola stranger'
Note that, as I said above this would not work if for example your function definition was like this:
def greet(person, greeting)
print('{} {}'.format(greeting, person))
return
Since in this case, Python would complain saying that it does not know what to do with person; no default is supplied..
And by the way, the problem you are describing is most likely the very reason defaults are used in the first place
Without knowing the other parameters, and only knowing that the parameter you want to change is in second position you could use the inspect module to get function signature & associated default values.
Then make a copy of the default values list and change the one at the index you want:
import inspect
def greet(person='stranger', greeting='hello'):
print(person,greeting)
argspec = inspect.getargspec(greet)
defaults = list(argspec.defaults)
defaults[1] = "hola" # change second default parameter
greet(**dict(zip(argspec.args,defaults)))
Assuming that all parameters have default values (else it shifts the lists an that fails) that prints:
stranger hola
I'm not an expert at python, so bear with me while I try to understand the nuances of variable scopes.
As a simple example that describes the problem I'm facing, say I have the following three files.
The first file is outside_code.py. Due to certain restrictions I cannot modify this file. It must be taken as is. It contains some code that runs an eval at some point (yes, I know that eval is the spawn of satan but that's a discussion for a later day). For example, let's say that it contains the following lines of code:
def eval_string(x):
return eval(x)
The second file is a set of user defined functions. Let's call it functions.py. It contains some unknown number of function definitions, for example, let's say that functions.py contains one function, defined below:
def foo(x):
print("Your number is {}!".format(x))
Now I write a third file, let's call it main.py. Which contains the following code:
import outside_code
from functions import *
outside_code.eval_string("foo(4)")
I import all of the function definitions from functions.py with a *, so they should be accessible by main.py without needing to do something like functions.foo(). I also import outside_code.py so I can access its core functionality, the code that contains an eval. Finally I call the function in outside_code.py, passing a string that is related to a function defined in functions.py.
In the simplified example, I want the code to print out "Your number is 4!". However, I get an error stating that 'foo' is not defined. This obviously means that the code in outside_code.py cannot access the same foo function that exists in main.py. So somehow I need to make foo accessible to it. Could anyone tell me exactly what the scope of foo currently is, and how I could extend it to cover the space that I actually want to use it in? What is the best way to solve my problem?
You'd have to add those names to the scope of outside_code. If outside_code is a regular Python module, you can do so directly:
import outside_code
import functions
for name in getattr(functions, '__all__', (n for n in vars(functions) if not n[0] == '_')):
setattr(outside_code, name, getattr(functions, name))
This takes all names functions exports (which you'd import with from functions import *) and adds a reference to the corresponding object to outside_code so that eval() inside outside_code.eval_string() can find them.
You could use the ast.parse() function to produce a parse tree from the expression before passing it to eval_function() and then extract all global names from the expression and only add those names to outside_code to limit the damage, so to speak, but you'd still be clobbering the other module namespace to make this work.
Mind you, this is almost as evil as using eval() in the first place, but it's your only choice if you can't tell eval() in that other module to take a namespace parameter. That's because by default, eval() uses the global namespace of the module it is run in as the namespace.
If, however, your eval_string() function actually accepts more parameters, look for a namespace or globals option. If that exists, the function probably looks more like this:
def eval_string(x, namespace=None):
return eval(x, globals=namespace)
after which you could just do:
outside_code.eval_string('foo(4)', vars(functions))
where vars(functions) gives you the namespace of the functions module.
foo has been imported into main.py; its scope is restricted to that file (and to the file where it was originally defined, of course). It does not exist within outside_code.py.
The real eval function accepts locals and globals dicts to allow you to add elements to the namespace of the evaluted code. But you can't do anything if your eval_string doesn't already pass those on.
The relevant documentation: https://docs.python.org/3.5/library/functions.html#eval
eval takes an optional dictionary mapping global names to values
eval('foo(4)', {'foo': foo})
Will do what you need. It is mapping the string 'foo' to the function object foo.
EDIT
Rereading your question, it looks like this won't work for you. My only other thought is to try
eval_str('eval("foo(4)", {"foo": lambda x: print("Your number is {}!".format(x))})')
But that's a very hackish solution and doesn't scale well to functions that don't fit in lambdas.
I am making a program to do some calculations for my Microeconomics class. Since there are some ways of working depending on the problem I am given, I have created a class. The class parses an Utility function and a 'mode' from the command line and calls a function or another depending on the mode.
Since every function uses the same variables I initiate them in __init__():
self.x = x = Symbol('x') # Variables are initiated
self.y = y = Symbol('y')
self.Px, self.Py, self.m = Px, Py, m = Symbol('Px'), Symbol('Py'), Symbol('m')
I need a local definition to successfully process the function. Once the function is initiated through sympify() I save it as an instance variable:
self.function = sympify(args.U)
Now I need to pass the variables x,yPx,Py,m to the different functions. This is where I have the problem. As I want a local definition I could simply x=self.x with all the variables. I would need to repeat this in every piece of code which isn't really sustainable. Another option is to pass all the variables as arguments.
But since I'm using a dictionary to choose which function to call depending on the mode this would mean I have to pass the same arguments for every function, whether I use them or not.
So I have decided to create a dictionary such as:
variables = { #A dictionary of variables is initiated
'x':self.x,
'y':self.y,
'Px':self.Px,
'Py':self.Py,
'm':self.m
}
This dictionary is initiated after I declare the variables as sympy Symbols. What I would like is to pass this dictionary in an unpacked form to every function. This way i would only need **kwargs as an argument and I could use the variables I want.
What I want is something like this:
a = 3
arggs = {'a' = a}
def f(**kwargs):return a+1
f(**args)
This returns 4. However when I pass my dictionary as an argument I get a non-defined 'x' or 'y' variables error. It can't be an scope issue because all the variables have been initiated for all the instance.
Here is my code calling the function:
self.approaches[self.identification][0](**self.variables)
def default(self, **kwargs):
solutions = dict()
self.MRS = S(self.function.diff(x) / self.function.diff(y)) # This line provokes the exception
What's my error?
PS: Some information may be unclear. English is not my main language. Apologies in advance.
Unfortunately, Python doesn't quite work like that. When you use **kwargs, the only variable this assigns is the variable kwargs, which is a dictionary of the keyword arguments. In general, there's no easy way to inject names into a function's local namespace, because of the way locals namespaces work. There are ways to do it, but they are fairly hacky.
The easiest way to make the variables available without having to define them each time is to define them at the module level. Generally speaking, this is somewhat bad practice (it really does belong on the class), but since SymPy Symbols are immutable and defined entirely by their name (and assumptions if you set any), it's just fine to set
Px, Py, m = symbols("Px Py m")
at the module level (i.e., above your class definition), because even if some other function defines its own Symbol("Px"), SymPy will consider it equal to the Px you defined from before.
In general, you can play somewhat fast and loose with immutable objects in this way (and all SymPy objects are immutable) because it doesn't really matter if an immutable object gets replaced with a second, equal object. It would matter, if, say, you had a list (a mutable container) because it would make a big difference if it were defined on the module level vs. the class level vs. the instance level.
I need help with parameteres. Do both of these function definitions do the exact same thing for print_twice?
def print_twice(lol):
print lol
print lol
def print_twice(michael):
print michael
print michael
If yes, then I'm guessing the word used for the parameter doesn't matter, correct?
The word we use for the parameter does matter. It is important that the word you use:
is meaningful and clearly explains what the argument is for,
does not override some variable name from the external scope.
Importance of meaningful arguments' names
The name you use for argument is important, because the names of the arguments, their default values and the function name are the things developers using your function first see, even without the need to look into function documentation (eg. by using help(your_function)). Just use IDLE to define your function and then try to use it - when writing it, the IDLE will show you possible arguments.
So please, give them meaningful names that will make using your function easier and will not require looking into the documentation.
Overriding variables from outer scopes
When it comes to the second point, just look at this example:
def show_elements(elements):
"""Shows elements of the passed argument
"""
for element in elements:
print element
which works ok, but if you replace elements with eg. list, you will override list within this specific scope:
def show_elements(list):
"""Shows elements of the passed argument
"""
for element in list:
print element
and then if you would like to use list eg. for building a list, or converting from other type into list, then you will have problems. list is a builtin and you should not override it. Similar is true also about the other variables from the scopes surrounding the function.
Historically, when Python was resolving variable names by first looking into local scope, then global and builtin scopes, skipping all nonlocal ones (eg. scope from the function in which our function was defined), enclosing scope's variables were passed that way:
def funca():
local_val1 = 'some value1'
local_val2 = 'some value2'
def funcb(local_val1=local_val1):
# local_val1 is accessible here, even though local_val2 is not
...
...
But since the above is no longer true, you will need to take surrounding scopes into account, thus using non-conflicting name is important.
Yes they do. The name of a parameter is irrelevant, although good programming practices mandate that the name should be clear and self-explanatory
That's correct, the name of the parameter doesn't matter.
yes that is correct its just a variable name ...
That is correct. The word used for the parameter in the function definition is only a name, and does not refer to anything external.
Programming is supposed to be logical. So, let's think logically. If you write "a" on a paper twice, you get "a" two times. Same with "b." So you're doing the same function with letters. But what if you reassigned a value to a, each time a went through the function. I mean, what if a was a number, then IMO the closest you could get is something like this:
def func1(a, b):
a = input("Enter a number: ")
b = input("Enter another number: ")
b *= b
a *= a
print func1(a)
print func1(a)
print func1(b)
print func1(b)
Now, when I try to compile this specific code online, I get an error but I think something like this will work for the sake of trying to do what you're doing if done correctly? It's a good experiment, and I would imagine some usage in it.