Why I cannot pass my parameter python - python

I wrote a simple function to calculate mode, but it seems one parameter does not pass successfully.
I initial countdict= dict() in the main function, then I pass it mod = mode(magList, countdict).
In mode(alist, countdict), countdict= dict(zip(alist,[0]*len(alist))). and countdict can print in mode.
but when I try to print(countdict) in main function, the output says it is empty. I check my code, it says in function mode, I unused countdict. How could that be possible.
The whole code is as following:
def mode(alist, countdict):
countdict= dict(zip(alist,[0]*len(alist)))
for x in alist:
countdict[x]+=1
maxcount =max(countdict.values())
modelist = [ ]
for item in countdict:
if countdict[item] == maxcount:
modelist.append(item)
return modelist
def makeMagnitudeList():
quakefile = open("earthquakes.txt","r")
headers = quakefile.readline()
maglist = [ ]
for aline in quakefile:
vlist = aline.split()
maglist.append(float(vlist[1]))
return maglist
def mymain():
magList = makeMagnitudeList()
print(magList)
countdict= dict()
mod = mode(magList, countdict)
print("mode: ", mod)
print(countdict)
if __name__=='__main__':
mymain()

As I said earlier, the line:
countdict= dict(zip(alist,[0]*len(alist)))
will wipe out the reference to countdict that you passed in. Because of this, the countdict variable you are printing is the original, empty dictionary. The question Liarez linked to: How do I pass a variable by reference? will help explain why this is happening.
To get around this, you could change the return statement in the mode function to:
return (modelist, countdict)
which will return a tuple containing both modelist and countdict. When calling this function, you would write:
(mod, countdict) = mode(magList, countdict)
ensuring that the modified countdict is returned, meaning that your print function call should not output an empty dictionary.
The other thing to note is that the countdict you are passing into mode is empty anyway, so you may find it better to simply not pass this argument in and have mode take only one parameter.

This line of code is your problem.
countdict= dict(zip(alist,[0]*len(alist)))
Python dictionaries are mutable objects and can be changed in a function, however, dictionary itself is not passed to the function. Only reference is passed and is passed by value. It means that when you assign a new dictionary to your countdict parameter, you lose the original reference pointing at countdict created in your mymain function.

Related

Understanding the in operator in Python

index = []
def add_to_index(index,keyword,url):
if len(index) == 0:
index.append([keyword, [url]])
elif keyword in index:
find_key_pos = index.find(keyword)
index.insert(find_key_pos + len(keyword), url)
add_to_index(index,'udacity','http://udacity.com')
add_to_index(index,'udacity','http://npr.org')
print(index)
My output is:
[['udacity', ['http://udacity.com']]]
Actually the output has to be
[['udacity', ['http://udacity.com', 'http://npr.org']]
Whenever the keyword already exists in the index list, I just have to insert the url to the list that is next to the keyword.
In,
add_to_index(index,'udacity','http://udacity.com')
add_to_index(index,'udacity','http://npr.org')
The keyword 'udacity' is the same that is why I should add the different url's after that keyword.
Your bugs:
index.insert(find_key_pos + len(keyword), url)
The first parameter to list.insert() is the index for the new element. You actually only want to get the list for your keyword though and append a new URL to the nested list.
What you want instead is:
index[find_key_pos].append(url)
Second bug lies in the re-use of the index variable. Your function parameter is shadowing the list from the parent scope. Use different names. Your code will work, because lists are mutable and you are passing around references to the same list, but it will create a hella lot of confusion down the road.
But what you should really do is you should look up Python dictionaries. They offer the keyword functionality out of the box.
Here's a small dict wrapper that will make your life easier:
class ListDict():
def __init__(self):
self.index = ()
def addEntry(self, key, entry):
if key in self.index:
self.index[key].append(entry)
else:
self.index[key] = [entry]
def getEntries(self, key):
if key in self.index:
return self.index[key]
else:
return []
Usage:
websiteUrls = ListDict()
websiteUrls.addEntry("udemy", "foo")
websiteUrls.addEntry("udemy", "bar")
websiteUrls.getEntries("udemy")
# ["foo", "bar"]
websiteUrls.getEntries("nope")
# []

var passed to a function by kwargs is not updated [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 8 months ago.
In some languages you can pass a parameter by reference or value by using a special reserved word like ref or val. When you pass a parameter to a Python function it never alters the value of the parameter on leaving the function.The only way to do this is by using the global reserved word (or as i understand it currently).
Example 1:
k = 2
def foo (n):
n = n * n #clarity regarding comment below
square = n
return square
j = foo(k)
print j
print k
would show
>>4
>>2
showing k to be unchanged.
In this example the variable n is never changed
Example 2:
n = 0
def foo():
global n
n = n * n
return n
In this example the variable n is changed.
Is there any way in Python to call a function and tell Python that the parameter is either a value or reference parameter instead of using global?
There are essentially three kinds of 'function calls':
Pass by value
Pass by reference
Pass by object reference
Python is a PASS-BY-OBJECT-REFERENCE programming language.
Firstly, it is important to understand that a variable, and the value of the variable (the object) are two seperate things. The variable 'points to' the object. The variable is not the object. Again:
THE VARIABLE IS NOT THE OBJECT
Example: in the following line of code:
>>> x = []
[] is the empty list, x is a variable that points to the empty list, but x itself is not the empty list.
Consider the variable (x, in the above case) as a box, and 'the value' of the variable ([]) as the object inside the box.
PASS BY OBJECT REFERENCE (Case in python):
Here, "Object references are passed by value."
def append_one(li):
li.append(1)
x = [0]
append_one(x)
print x
Here, the statement x = [0] makes a variable x (box) that points towards the object [0].
On the function being called, a new box li is created. The contents of li are the SAME as the contents of the box x. Both the boxes contain the same object. That is, both the variables point to the same object in memory. Hence, any change to the object pointed at by li will also be reflected by the object pointed at by x.
In conclusion, the output of the above program will be:
[0, 1]
Note:
If the variable li is reassigned in the function, then li will point to a separate object in memory. x however, will continue pointing to the same object in memory it was pointing to earlier.
Example:
def append_one(li):
li = [0, 1]
x = [0]
append_one(x)
print x
The output of the program will be:
[0]
PASS BY REFERENCE:
The box from the calling function is passed on to the called function. Implicitly, the contents of the box (the value of the variable) is passed on to the called function. Hence, any change to the contents of the box in the called function will be reflected in the calling function.
PASS BY VALUE:
A new box is created in the called function, and copies of contents of the box from the calling function is stored into the new boxes.
You can not change an immutable object, like str or tuple, inside a function in Python, but you can do things like:
def foo(y):
y[0] = y[0]**2
x = [5]
foo(x)
print x[0] # prints 25
That is a weird way to go about it, however, unless you need to always square certain elements in an array.
Note that in Python, you can also return more than one value, making some of the use cases for pass by reference less important:
def foo(x, y):
return x**2, y**2
a = 2
b = 3
a, b = foo(a, b) # a == 4; b == 9
When you return values like that, they are being returned as a Tuple which is in turn unpacked.
edit:
Another way to think about this is that, while you can't explicitly pass variables by reference in Python, you can modify the properties of objects that were passed in. In my example (and others) you can modify members of the list that was passed in. You would not, however, be able to reassign the passed in variable entirely. For instance, see the following two pieces of code look like they might do something similar, but end up with different results:
def clear_a(x):
x = []
def clear_b(x):
while x: x.pop()
z = [1,2,3]
clear_a(z) # z will not be changed
clear_b(z) # z will be emptied
OK, I'll take a stab at this. Python passes by object reference, which is different from what you'd normally think of as "by reference" or "by value". Take this example:
def foo(x):
print x
bar = 'some value'
foo(bar)
So you're creating a string object with value 'some value' and "binding" it to a variable named bar. In C, that would be similar to bar being a pointer to 'some value'.
When you call foo(bar), you're not passing in bar itself. You're passing in bar's value: a pointer to 'some value'. At that point, there are two "pointers" to the same string object.
Now compare that to:
def foo(x):
x = 'another value'
print x
bar = 'some value'
foo(bar)
Here's where the difference lies. In the line:
x = 'another value'
you're not actually altering the contents of x. In fact, that's not even possible. Instead, you're creating a new string object with value 'another value'. That assignment operator? It isn't saying "overwrite the thing x is pointing at with the new value". It's saying "update x to point at the new object instead". After that line, there are two string objects: 'some value' (with bar pointing at it) and 'another value' (with x pointing at it).
This isn't clumsy. When you understand how it works, it's a beautifully elegant, efficient system.
Hope the following description sums it up well:
There are two things to consider here - variables and objects.
If you are passing a variable, then it's pass by value, which means the changes made to the variable within the function are local to that function and hence won't be reflected globally. This is more of a 'C' like behavior.
Example:
def changeval( myvar ):
myvar = 20;
print "values inside the function: ", myvar
return
myvar = 10;
changeval( myvar );
print "values outside the function: ", myvar
O/P:
values inside the function: 20
values outside the function: 10
If you are passing the variables packed inside a mutable object, like a list, then the changes made to the object are reflected globally as long as the object is not re-assigned.
Example:
def changelist( mylist ):
mylist2=['a'];
mylist.append(mylist2);
print "values inside the function: ", mylist
return
mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist
O/P:
values inside the function: [1, 2, 3, ['a']]
values outside the function: [1, 2, 3, ['a']]
Now consider the case where the object is re-assigned. In this case, the object refers to a new memory location which is local to the function in which this happens and hence not reflected globally.
Example:
def changelist( mylist ):
mylist=['a'];
print "values inside the function: ", mylist
return
mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist
O/P:
values inside the function: ['a']
values outside the function: [1, 2, 3]
Python is neither pass-by-value nor pass-by-reference. It's more of "object references are passed by value" as described here:
Here's why it's not pass-by-value. Because
def append(list):
list.append(1)
list = [0]
reassign(list)
append(list)
returns [0,1] showing that some kind of reference was clearly passed as pass-by-value does not allow a function to alter the parent scope at all.
Looks like pass-by-reference then, hu? Nope.
Here's why it's not pass-by-reference. Because
def reassign(list):
list = [0, 1]
list = [0]
reassign(list)
print list
returns [0] showing that the original reference was destroyed when list was reassigned. pass-by-reference would have returned [0,1].
For more information look here:
If you want your function to not manipulate outside scope, you need to make a copy of the input parameters that creates a new object.
from copy import copy
def append(list):
list2 = copy(list)
list2.append(1)
print list2
list = [0]
append(list)
print list
Technically python do not pass arguments by value: all by reference. But ... since python has two types of objects: immutable and mutable, here is what happens:
Immutable arguments are effectively passed by value: string, integer, tuple are all immutable object types. While they are technically "passed by reference" (like all parameters), since you can't change them in-place inside the function it looks/behaves as if it is passed by value.
Mutable arguments are effectively passed by reference: lists or dictionaries are passed by its pointers. Any in-place change inside the function like (append or del) will affect the original object.
This is how Python is designed: no copies and all are passed by reference. You can explicitly pass a copy.
def sort(array):
# do sort
return array
data = [1, 2, 3]
sort(data[:]) # here you passed a copy
Last point I would like to mention which is a function has its own scope.
def do_any_stuff_to_these_objects(a, b):
a = a * 2
del b['last_name']
number = 1 # immutable
hashmap = {'first_name' : 'john', 'last_name': 'legend'} # mutable
do_any_stuff_to_these_objects(number, hashmap)
print(number) # 1 , oh it should be 2 ! no a is changed inisde the function scope
print(hashmap) # {'first_name': 'john'}
So this is a little bit of a subtle point, because while Python only passes variables by value, every variable in Python is a reference. If you want to be able to change your values with a function call, what you need is a mutable object. For example:
l = [0]
def set_3(x):
x[0] = 3
set_3(l)
print(l[0])
In the above code, the function modifies the contents of a List object (which is mutable), and so the output is 3 instead of 0.
I write this answer only to illustrate what 'by value' means in Python. The above code is bad style, and if you really want to mutate your values you should write a class and call methods within that class, as MPX suggests.
Consider that the variable is a box and the value it points to is the "thing" inside the box:
1. Pass by reference : function shares the same box and thereby the thing inside also.
2. Pass by value : function creates a new box, a replica of the old one, including a copy of whatever thing is inside it. Eg. Java - functions create a copy of the box and the thing inside it which can be: a primitive / a reference to an object. (note that the copied reference in the new box and the original both still point to the same object, here the reference IS the thing inside the box, not the object it is pointing to)
3. Pass by object-reference: the function creates a box, but it encloses the same thing the initial box was enclosing. So in Python:
a) if the thing inside said box is mutable, changes made will reflect back in the original box (eg. lists)
b) if the thing is immutable (like python strings and numeric types), then the box inside the function will hold the same thing UNTIL you try to change its value. Once changed, the thing in the function's box is a totally new thing compared to the original one. Hence id() for that box will now give the identity of the new thing it encloses.
The answer given is
def set_4(x):
y = []
for i in x:
y.append(i)
y[0] = 4
return y
and
l = [0]
def set_3(x):
x[0] = 3
set_3(l)
print(l[0])
which is the best answer so far as it does what it says in the question. However,it does seem a very clumsy way compared to VB or Pascal.Is it the best method we have?
Not only is it clumsy, it involves mutating the original parameter in some way manually eg by changing the original parameter to a list: or copying it to another list rather than just saying: "use this parameter as a value " or "use this one as a reference". Could the simple answer be there is no reserved word for this but these are great work arounds?
class demoClass:
x = 4
y = 3
foo1 = demoClass()
foo1.x = 2
foo2 = demoClass()
foo2.y = 5
def mySquare(myObj):
myObj.x = myObj.x**2
myObj.y = myObj.y**2
print('foo1.x =', foo1.x)
print('foo1.y =', foo1.y)
print('foo2.x =', foo2.x)
print('foo2.y =', foo2.y)
mySquare(foo1)
mySquare(foo2)
print('After square:')
print('foo1.x =', foo1.x)
print('foo1.y =', foo1.y)
print('foo2.x =', foo2.x)
print('foo2.y =', foo2.y)
In Python the passing by reference or by value has to do with what are the actual objects you are passing.So,if you are passing a list for example,then you actually make this pass by reference,since the list is a mutable object.Thus,you are passing a pointer to the function and you can modify the object (list) in the function body.
When you are passing a string,this passing is done by value,so a new string object is being created and when the function terminates it is destroyed.
So it all has to do with mutable and immutable objects.
Python already call by ref..
let's take example:
def foo(var):
print(hex(id(var)))
x = 1 # any value
print(hex(id(x))) # I think the id() give the ref...
foo(x)
OutPut
0x50d43700 #with you might give another hex number deppend on your memory
0x50d43700

'return outside of function' error with correct indentation?

in python, it comes out with 'return outside of function', I check the indentation is nothing wrong. any clue on that?
dict={1:10,2:20,3:30}
for a,b in dict.items():
if b==30:
return a
There's no function, so you cannot use return. You may wrap the code in def:
d={1:10,2:20,3:30}
def return_30(d):
for a,b in d.items():
if b==30:
return a
Also I renamed dict to d, because dict is a name of the type, and when you redefine it you lose access to original dict.
The for loop, isn't a function.
A function in python is DEFined using the def keyword as in:
def function():
print(1+2) # Im inside the function, return keyword here is valid
# I'm outside the function.
for x in range(10):
print(x)
#This is not a function, return keyword here is invalid.

Python DFS, can't figure out why return list is empty if using append/pop() but works for []+[] in recursive call

can someone plz tell me why this code generate empty "res" variable? If uncomment the commented line and remove below will be working fine.
Codes not work:
class Solution(object):
def dfs(self, nums, res, line):
if not nums:
print(line)
res.append(line)
return
for i, num in enumerate(nums):
line.append(num)
# self.dfs(nums[:i]+nums[i+1:], res, line+[num])
self.dfs(nums[:i]+nums[i+1:], res, line)
line.pop()
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
self.dfs(nums, res, [])
print(res)
return res
if __name__ == "__main__":
Solution().permute([1,2])
Works fine if changing to:
for i, num in enumerate(nums):
self.dfs(nums[:i]+nums[i+1:], res, line+[num])
except using append/pop for passing the DFS. Even the "line" variable before appending to "res" is correct.
Does it have something to do with referencing? The only thing I could think of is whatever passed to res got cleaned up. I would really appreciate if someone could show me the link to reference.
Your guessing is correct. Just like Java, list in python is copy-by-reference. Consider the following example:
a = [1, 2, 3]
b = a
a.append(4)
print(b)
You will get
[1, 2, 3, 4]
Thus, one easy way to fix the code is that replacing the res.append(line) in dfs() right before return into:
res.append(line[:])
Basically, line[:] will create a separate list object. You can see more information in this thread.
Python function call semantics:
Are not pass-by-reference. The receiving end does not need to de-reference it.
Are not pass-by-value. There is no copy made of the value.
May best be described as pass by object. The object itself is passed to the function; not a reference, not a copy, the very object itself.
See Frederik Lundh's article about call by object semantics. The Wikipedia article for this names it “call by sharing” and attributes Barbara Liskov with coining that term.
This means that any container object you pass as a parameter will be present in the function as the same object, and modifications there will persist in the container object. The same is true of any mutable object.
So, if you want to modify a container passed in, don't modify it directly. Create a copy (usually by calling the type, e.g. list, to get a new instance), and modify that.
If the function's purpose is to generate a new container, it should create its own instance and return that copy.
So I think the dfs function is poorly designed. It should instead do something like:
def dfs(nums, line):
result = []
for i, num in enumerate(nums):
line.append(num)
result.extend(dfs(nums[:i]+nums[i+1:], line))
line.pop()
else:
print(line)
result.append(line)
return result

Adding items to a list if it's not a function

I'm trying to write a function right now, and its purpose is to go through an object's __dict__ and add an item to a dictionary if the item is not a function.
Here is my code:
def dict_into_list(self):
result = {}
for each_key,each_item in self.__dict__.items():
if inspect.isfunction(each_key):
continue
else:
result[each_key] = each_item
return result
If I'm not mistaken, inspect.isfunction is supposed to recognize lambdas as functions as well, correct? However, if I write
c = some_object(3)
c.whatever = lambda x : x*3
then my function still includes the lambda. Can somebody explain why this is?
For example, if I have a class like this:
class WhateverObject:
def __init__(self,value):
self._value = value
def blahblah(self):
print('hello')
a = WhateverObject(5)
So if I say print(a.__dict__), it should give back {_value:5}
You are actually checking if each_key is a function, which most likely is not. You actually have to check the value, like this
if inspect.isfunction(each_item):
You can confirm this, by including a print, like this
def dict_into_list(self):
result = {}
for each_key, each_item in self.__dict__.items():
print(type(each_key), type(each_item))
if inspect.isfunction(each_item) == False:
result[each_key] = each_item
return result
Also, you can write your code with dictionary comprehension, like this
def dict_into_list(self):
return {key: value for key, value in self.__dict__.items()
if not inspect.isfunction(value)}
I can think of an easy way to find the variables of an object through the dir and callable methods of python instead of inspect module.
{var:self.var for var in dir(self) if not callable(getattr(self, var))}
Please note that this indeed assumes that you have not overrided __getattr__ method of the class to do something other than getting the attributes.

Categories

Resources