简体   繁体   中英

modifying global variable pass in parameter function in place on python

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?

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.

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)

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.

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)


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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM