for i in rates:
if input_currency == currency:
if output_currency in rates[currency]:
pass
else:
for i in rates:
Is it generally a bad thing to use the same variable i again within a for loop? Even if I loop through the same data structure again? PyCharm just tells me it's been used already, but it still works.
It's not wrong. But it's dangerous if you don't know what you are doing. For example, you might have problems if you want to use i inside the outer loop:
rates = [1,2,3,4,5]
for i in rates:
for i in rates:
pass
print(i) # This always prints 5
This may confuse you if you're not familiar with Python. In C, for example, a variable defined inside the inner loop is different from the one that is defined in the outer loop (i.e., you can reuse the same name for different variables).
Related
Let's say that I have a variable in which I will use for a loop 1000 times such that:
A = [3,4,5,6]
for i in range(1000):
# if something
# c = <a list which length depends on runtime>
A = c
del c
Would deleting c after single loop makes memory consumption more efficient?
In general, no. It doesn't.
del deletes names from namespaces, not objects.
Of course, if you remove a reference, and the reference count reaches 0, the object will be reclaimed (immediately in CPython).
But note, in your loop above, you create another reference anyway, A = c, so it definitely doesn't help at all.
There is one scenario where this may be beneficial, suppose you do this in a global scope, e.g. at a module level, so not in a function. Because python for-loops don't create their own scopes, c has now remained in the global namespace, and potentially, it keeps a giant list alive until the end of the program.
This is usually better solved by organizing your program better into modular functions, and only creating references to objects in the global scope that you want to survive until the end of the program. However, sometimes, you do end up doing a loop like that, and in that case, explicitly removing that last reference does help (but again, since you did A = c, then it wouldn't help anyway).
I feel that you have a fundamental misunderstanding of how Python variables work. I second the suggestion from the comments to read:
https://nedbatchelder.com/text/names.html
I have a simple function containing a loop that calculates how money grows per year with interest, which got me thinking about scope and variables in Python.
def invest(amount, rate, years):
for i in range(years):
amount = amount + amount*rate
print(f"year {i+1}: ${amount:.2f}")
invest(100, 0.05, 4)
The output:
year 1: $105.00
year 2: $110.25
year 3: $115.76
year 4: $121.55
I know it works, but usually I would create the 'amount' variable above the for loop to ensure that after each iteration, that variable will get updated. Since I didn't do that this time, I assume that this variable gets created globally so that happens automatically.
Are my assumptions correct? Thank you
If it was global then you would be able to access it outside the function. The scope of the variable is limited to that specific function.
You can also create another intermediate variable above the loop but it wouldn't change much about the function- you don't need the original value of amount in your function so for your purposes- using that variable and updating it directly in your loop is fine.
The answer above already satisfy what you asked, but I think the following link might be good for your learning, as it was good for mine. In Python Tutor you can put your code and visualize what happens inside the global scope, functions' scopes, etc. Hope this can help you!
In python you can create rather hard to find bugs by giving a loop variable a name that already exists in the rest of your code.
The pattern looks like this:
idx = 0 # the result of some calculations
for idx in range(10):
# do something
# use idx and expect it to be 0
# surprise, idx is actually 9
Of course, the obvious solution is to have better variable names. But even if you use very descriptive names, there is still a chance that the same name seems like a good choice somewhere else in your code.
Especially in numerical code, there are just so many indices that it gets really hard to keep track. And variables pretty much never run out of scope:
for idx in range(10):
# do something
# idx is now in scope
# autocomplete will suggest idx, but it is still fine as a loop variable
for idx in range(10):
# do something
Is it possible to set up a linter for this problem ?
I want to be warned whenever I use a variable as a loop variable that has been defined in an enclosing scope. The rule would need a notion of scopes and their child-scopes. The first code sample above should create a warning. In the second example, the loop variable already exists in the outer scope, but it has been defined in a child of the enclosing scope. That should be fine.
I have a Python module which consists of a number of different functions.
Say my first function returns a variable which I want to use twice in the second and the second returns a variable which I want to use four times in the third function ( . . . and so on).
Is it better to declare the variables that I will want to use throughout the entire module as global and then call the function that returns said variable once to define it globally rather than to call functions more than once in order to use the variables they return?
Am I correct in saying that this is a trade-off between safety (not using global variables) and efficiency (not executing each function more than once if possible)?
def fn_for_reading_file():
# (Insert code for prompting user for filename, opening and reading file)
global file_as_string
# (Insert code for assigning user's file to file_as_string)
return file_as_string
fn_for_reading_file()
def extract_data_from_string():
global my_list = []
# (Insert code for going through return_file_as_string and appending data to my_list)
return my_list
extract_data_from_string()
def another_fn():
# (Insert code which uses file_as_string and my_list)
return fn_output
another_fn()
I would try to reframe the problem you're thinking about. If you're only thinking in terms of functional programming then yes, you're correct in that safety vs. more code is the basic trade off you're looking at.
However, there are a number of ways to get around your dilemma by reframing the problem. I obviously don't know what your code looks like, but it might be meaningful to think about building this functionality into a class. Rather than using global variables, set those values as class attributes with appropriate getters/setters, and then structure the module such that your functions become methods.
I'm currently developing some things in Python and I have a question about variables scope.
This is the code:
a = None
anything = False
if anything:
a = 1
else:
a = 2
print a # prints 2
If I remove the first line (a = None) the code still works as before. However in this case I'd be declaring the variable inside an "if" block, and regarding other languages like Java, that variable would only be visible inside the "if".
How exactly variable scoping works in Python and what's the good way to program in cases like this?
Thanks!
As a rule of thumb, scopes are created in three places:
File-scope - otherwise known as module scope
Class-scope - created inside class blocks
Function-scope - created inside def blocks
(There are a few exceptions to these.)
Assigning to a name reserves it in the scope namespace, marked as unbound until reaching the first assignment. So for a mental model, you are assigning values to names in a scope.
I believe that Python uses function scope for local variables. That is, in any given function, if you assign a value to a local variable, it will be available from that moment onwards within that function until it returns. Therefore, since both branches of your code are guaranteed to assign to a, there is no need to assign None to a initially.
Note that when you can also access variables declared in outer functions -- in other words, Python has closures.
def adder(first):
def add(second):
return first + second
return add
This defines a function called adder. When called with an argument first, it will return a function that adds whatever argument it receives to first and return that value. For instance:
add_two = adder(2)
add_three = adder(3)
add_two(4) # = 6
add_three(4) # = 7
However, although you can read the value from the outer function, you can't change it (unlike in many other languages). For instance, imagine trying to implement an accumulator. You might write code like so:
def accumulator():
total = 0
def add(number):
total += number
return total
return add
Unfortunately, trying to use this code results in an error message:
UnboundLocalError: local variable 'total' referenced before assignment
This is because the line total += number tries to change the value of total, which cannot be done in this way in Python.
There is no problem assigning the variable in the if block.
In this case it is being assigned on both branches, so you can see it will definitely be defined when you come to print it.
If one of the branches did not assign to a then a NameError exception would be raise when you try to print it after that branch
Python doesn't need variables to be declared initially, so you can declare and define at arbitrary points. And yes, the scope is function scope, so it will be visible outside the if.
i'm quite a beginner programmer, but for what i know, in python private variables don't exist. see private variables in the python documentation for a detailed discussion.
useful informations can also be found in the section "scopes and namespaces" on the same page.
personally, i write code like the one you posted pretty much every day, especially when the condition relies in getting input from the user, for example
if len(sys.argv)==2:
f = open(sys.argv[1], 'r')
else:
print ('provide input file')
i do declare variables before using them for structured types, for example i declare an empty list before appending its items within a loop.
hope it helps.