Concept of func, *args and **kwargs in decorator

sir, i did not understand the concept of these three functions in this coding. Please explain.
def login_required(func):
def wrapper(username, password, *args, **kwargs):
if username in users and users[username]==password:
func(*args,*kwargs)
else:
print(“error”)
return wrapper

Hello @vanshikasetia, okay see there might be some functions or the application where we want different functionality on the basis of different conditions like if you want your webpage looks different for the logged in user and different for the user who hasn’t logged in.
In that case, we can use the decorators and pass on the condition easily for the logged in and logged out users.
So here, we have declared the function login_required

def login_required(func):

Now if you see we are passing a function inside this function. This means if you want to impose certain conditions on your function by passing it into the login_required function. Now as the function is passed now we are declaring one more func named wrapper inside the login_required function and this function takes the parameters necessary for the login. So we can see we have username and password for that and here *arg and **kwargs are also passed and it is good to always pass *args and **kwargs because they just signify in case there are extra optional variables they just pass on without any issue.

def wrapper(username, password, *args, **kwargs):
    if username in users and users[username]==password:
        func(*args,*kwargs)

And then we are checking if the username and the password is correct or not and if it is correct then we can pass on the extra variables to the original func function that we want to have the accessibility if the user is logged in. And if this is true we are passing the func else we are returning the error.
And at last, you can see we are just returning the wrapper function.

if username in users and users[username]==password:
    func(*args,*kwargs)
else:
    print(“error”)
return wrapper

I hope this is clear to you. In case if there is any issue pls let me know, I will try my best to help you out. And if it is clear then pls mark it as resolve and feel free to provide the rating as well as feedback.
Thanks :slight_smile:

Okay sir, but can you also just explain the difference between:
print(args)
print(kwargs)
AND
print(*args)
print(**kwargs)

what does the symbol * does when we put it inside the parenthesis after the print function?

Okay see the example for more clarity:

def func(*args,**kwargs):
    print(args)
    print(kwargs)
    print(*args)
    print(*kwargs)

And suppose now I give input to the function func(1,2,3,4,“Steve”,4.3,“Gate”,a=“Hello”,b=“World”,fruit=“mango”,vegetable=“spinach”)
Now the output will be

(1, 2, 3, 4, 'Steve', 4.3, 'Gate')
{'a': 'Hello', 'b': 'World', 'fruit': 'mango', 'vegetable': 'spinach'}
1 2 3 4 Steve 4.3 Gate
a b fruit vegetable
# So if you see the output corresponding to the statements.
print(args) returns the tuple of the arguments
print(kwargs) returns the dictionary of the keyworded arguments (key value pair)
print(*args) returns the arguments that are there in the tuple
print(*kwargs) returns the keys that are there in the dictionary like a,b,fruit etc.

I hope this is clear to you. In case if there is any issue pls let me know, I will try my best to help you out. And if it is clear then pls mark it as resolve and feel free to provide the rating as well as feedback.
Thanks :slight_smile:

okay sir. thank you so much for clearing my doubts