Why a variable can be accessible outside the loop in Python? [duplicate] - python

This question already has answers here:
Scoping in Python 'for' loops
(8 answers)
Closed 7 years ago.
Consider this example:
for iter in xrange(10):
myvar = iter
print myvar
# 9
Here myvar is clearly outside the loop? But it is still accessible.
If this is Perl, it will throw an error.
What's the reason behind such feature in Python?
Is it harmful? What's the best practice then, to declare a variable before looping?

There is no new scope created by the for loop (Ruby also behaves the same way). This may be surprising if you are coming from a language that creates new scopes for blocks.
I don't believe it's harmful as long as you know the rules.
If your functions and methods are so large that you have trouble keeping track, then your functions and methods are too large.

Think of it as if you're doing this:
my_var = 0
my_var = 1
my_var = 2
...
my_var = 9
print my_var
This is basically what the iteration will look like, there is no reason why my_var would not be accessible from within your current method / scope.

Related

Defining a variable after inner function is a bad practice? [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 years ago.
I was thinking that variable can be only accessed after its declaration.
But apparently, Python's name resolution starts to look for from inside to outer.
My question is that this is bad practice in terms of readability? I was wondering that this might be a common knowledge for Pythonista so that I can write this kind of code from now on.
def outer():
def inner():
print x
x = ‘foo’
inner()
>>> outer()
>>> ‘foo’
When you invoke inner(), it starts executing. On line print x it sees variable name x. Then it looks to inner scope of function inner, doesn't find variable x there. Then it looks to the outer scope, namely, scope of outer. At this moment there is already variable x defined (as it is done before inner() invokation) and this variable is used.

How to generate multiple function names? [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 5 years ago.
I have a number of functions called func_1, func_2, ... I'd like to call each of them in a for loop.
I could do:
for f in [func_1, func_2, func_3]:
print f('foo', 'bar')
but I'd like less typing. Is there any way to generate the names, something like:
for f in ['func_%s' % range(1,5)]:
print f('foo', 'bar')
This fails with 'str' object is not callable, but is there anything like this that works?
EDIT: I'm testing a number of alternative versions of func. They are all supposed to give the same result, but with different implementations. I control the inputs and this is not in production.
However, this is bad and possibly dangerous practice in other contexts. See the comments and answers.
You could look them up in the local scope:
for f in ['func_%s' % range(1,5)]:
print locals()[f]('foo', 'bar')
The locals() function returns a dictionary of names to values in the local scope. If they are global functions, use globals().
You can use eval. However it is very dangerous to use eval. Be careful while playing with it.
for f in ['func_%s' % range(1,5)]:
print eval(f)('foo', 'bar')

Why does Python pointing change with small changes to this function? [duplicate]

This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 8 years ago.
when working with python, it bothered me that while obj.method() is perfectly fine, method(obj) isn't allowed. So I figured I'd try to write some code to fix that. I came up with the next:
def globalclassfuncs(defobj):
for i in inspect.getmembers(defobj, predicate=inspect.ismethod):
def scope():
var = i[0];
setattr(sys.modules[__name__], i[0], lambda obj, *args: getattr(obj, var)(*args));
scope();
However, there's something weird with this. When I remove def scope(): and scope(), so that it'll run without a function definition in the for loop, or when I change the getattr() function to use i[0] directly instead of through var, somehow all new defined functions point to the last defined function instead of the function they should point to. Why does this behaviour change so much on such small changes in the code?
Seems like a case of late binding closure

python variable scope in function [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 8 years ago.
I have found a similar question Python variable scope error. It's related to immutable variable. But when I test mutable variable, I don't know how Python interpreter decides the scope of the variable.
Here's my sample code:
def test_immutable():
a = 1
b = 2
def _test():
print(a)
print(b)
a += 1
print(a)
_test()
def test_mutable():
_dict = {}
def _test():
print(_test.__dict__)
_dict['name'] = 'flyer'
print('in _test: {0}'.format(_dict['name']))
_test()
print(_dict['name'])
if __name__ == '__main__':
# test_immutable() # throw exception
test_mutable() # it's ok
Immutable vs mutable has nothing to do with variable scoping. Variables are just names, and always work the same way. Scoping is even decided at compile time, long before Python knows what you're going to assign to them.
The difference between your two functions is that the first one assigns directly to a with the += operator, which causes a to become a local. The second one assigns to a key inside _dict, which ultimately calls a method on the dict object, and doesn't affect the variable's scoping.

'Safe' Assignment in MATLAB [duplicate]

This question already has answers here:
How do I do multiple assignment in MATLAB?
(9 answers)
Closed 9 years ago.
I've noticed that in a python code you can do something like:
a=0
b=1
a,b=b,a
print(a,b)
which outputs (a=1,b=0) (i.e. each variable is assigned independently of the last assignment). Is there a way to do something similar in MATLAB?
Sorry if this is a really simple question, but I've been trying to find a clean answer to this for a bit of time now and haven't found anything.
There is no need for an additional temporary variable here. If you want multiple assignments in a single statement, you can use deal:
[a, b] = deal(b, a)
I believe this is what you're looking for.
It's always possible to do that with a temporary variable in any language. The unpacking method of Python is just a little syntax sugar to simplify the developer life :)
a = 0
b = 1
tmp = a
a = b
b = tmp
print(a,b)
Anyway, it's not magical, the Python byte code might implement the permutation with a temporary variable. (There's techniques to do this without temp variable, but well... for the sake of clarity use one :p)

Categories

Resources