2

i thought i understood the global vs local scope for variable but i am struggling on a case.

Here the function i want to implement:

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place.
              It should not return anything.
     Goal : in id_name_verified, 'Verified' column should be removed and password should be added from id_password with corresponding id and the column be named password
    """


Test:
import pandas as pd
import numpy as np


def login_table(id_name_verified, id_password):
    id_name_verified.drop(columns="Verified",inplace=True)
    password = pd.DataFrame(id_password)
    password.columns = ["Id", "Password"]
    id_name_verified =id_name_verified.merge(password, on=['Id'])




id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)


Expected Output:

   Id        Login   Password
0   1      JohnDoe  987340123
1   2  AnnFranklin  187031122

Output i got:

   Id        Login
0   1      JohnDoe
1   2  AnnFranklin

When I run this on pycharm, i see the problem is in the last line of my function where id_name_verified is identified as being from outer scope. This inspection detects shadowing names defined in outer scopes.

If i don't define a function it will work so I guess there is something I miss in the understanding of parameters pass to a function; any suggestions ?

2
  • This is not a global vs local variables problem (apart from pycharm warning about shadowing). login_table() should return id_name_verified and the call site should be: id_name_verified = login_table(id_name_verified, id_password) Commented Nov 12, 2019 at 15:54
  • i get what you mean but if i want to satisfy the specs of the function, i don't want the function to return something, so modify it in place as i said, and neither change the number of parameter Commented Nov 12, 2019 at 16:21

5 Answers 5

1

Here is the code that will solve your problem:

import pandas as pd
import numpy as np

def login_table( id_password):
    global id_name_verified
    id_name_verified.drop(columns="Verified",inplace=True)
    password = pd.DataFrame(id_password)
    password.columns = ["Id", "Password"]
    id_name_verified =id_name_verified.merge(password, on=['Id'])

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table( id_password)
print(id_name_verified)

The changes I made are, I declared the "id_name_verified" as global inside the function "login_table". Once this is done you don't have to pass "id_name_verified" again to the function because by using the keyword "global" we have already given access of "id_name_verified" to the function "login_table". So removed the "id_name_verified" as one of the arguments to the function.

Sign up to request clarification or add additional context in comments.

1 Comment

As a programmer you should try very, very, very hard not to use global variables!
1
import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    id_name_verified.drop(inplace=True, columns="Verified") # drop verified column inplace
    id_name_verified.insert(loc=2,column="Password",value=np.nan) # insert password column inplace
    for row in range(len(id_password)): 
        # apply the password on the rows that match using at
        id = id_password[row][0]
        pw = id_password[row][1]
        id_name_verified.at[row, "Password"] = pw

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

Comments

1

For faster version use mapping. Creating new DataFrame is slow and costly way.

import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.   
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place. 
              It should not return anything.
    """   
    id_name_verified.drop(columns='Verified', inplace=True)
    mapping = {li[0]: li[1] for li in id_password}
    id_name_verified['Password'] = id_name_verified['Id'].map(mapping)

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

Comments

0

Here's the code that passes all 4 tests on TestDome:

import pandas as pd
import numpy as np

def login_table(id_name_verified, id_password):
    """
    :param id_name_verified: (DataFrame) DataFrame with columns: Id, Login, Verified.   
    :param id_password: (numpy.array) Two-dimensional NumPy array where each element
                        is an array that contains: Id and Password
    :returns: (None) The function should modify id_name_verified DataFrame in-place. 
              It should not return anything.
    """   
    id_name_verified.drop(columns = 'Verified', inplace = True)
    password_df = pd.DataFrame(id_password)
    pass_col = password_df[1]
    id_name_verified['Password'] = pass_col

id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)

You drop the 'Verified' column, then create a new data frame just out of id_password, take the column that contains passwords and add it to the id_name_verified data frame.

Comments

0
import pandas as pd
import numpy as np 

def login_table(id_name_verified, id_password):
    # in place makes sure that changes are made in a current dataframe 
    id_name_verified.drop('Verified', 1, inplace= True) 
    # id_password[:,1] -> : selects all rows and 1 selects only second column
    id_name_verified['Password'] = id_password[:,1]
    pass


id_name_verified = pd.DataFrame([[1, "JohnDoe", True], [2, "AnnFranklin", False]], columns=["Id", "Login", "Verified"])
id_password = np.array([[1, 987340123], [2, 187031122]], np.int32)
login_table(id_name_verified, id_password)
print(id_name_verified)


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.