I am able to understand what constructors are. But why can't python take initializer lists like c++?
class test:
def __init__(self, arg1, arg2, arg3):
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
how will those arguments ever be set without being so manual?
Thanks.
test1 = test(1, 2, 3)
A constructor is just like any old function, and you pass arguments to it.
Constructor is called once the object is created, not once it is called:
t = test (arg1, arg2, arg3)
Simple - when you instantiate the class later on:
a = test(arg1, arg2, arg3)
a is now a test class, with the 3 arguments set when you initialised it.
The intention behind this is to directly initialize some variables passed to the constructor. The constructor is, as written several times before, called:
t = test(arg1, arg2, arg3)
You have then for the passed parameters defined values in your class.
Related
I am trying to get auto completion of method parameter names for class instances but can't quite figure it out. Take this example class:
class Abc:
def meth(param):
pass
If I type Abc.meth(p and press Tab I see the expected completion of param=:
However, if I try to do the same with an instance of the class Abc().meth(p, I don't see param in the completion results:
I see the same behavior in both JupyterLab and VS Code, and the fact that this works for instances of other packages such as scikit learn, I think there is something I am missing.
How can I get method parameter completion for an instance of my Abc() class similar to the LinearRegression class above?
Based on experimentation on JupyterLab Version 3.2.9, this seems to be because the autocomplete tries to account for implicit parameters like self and cls. Including a self parameter should mostly fix your issues.
class Abc:
def meth(arg1, arg2, arg3):
pass
These are the completion options I was presented for the class above:
Decorator
Abc.meth
Abc().meth
None
arg1, arg2, arg3
arg2, arg3
#staticmethod
arg1, arg2, arg3
arg2, arg3
#classmethod
arg2, arg3
arg3
The standard behavior is fine, but the results for Abc().meth are wrong with both decorators. As mentioned in the docs for staticmethod and classmethod:
method can be called either on the class (such as C.f()) or on an instance (such as C().f())
So both columns should have been the same when decorators are used, but it always omits one parameter from Abc().meth, presumably for self. And even though cls is correctly handled for Abc.meth when using #classmethod, it ends up omitting two parameters in Abc().meth instead.
Testing with Visual Studio Code 1.67.1 gave the correct autocomplete options for all cases. So the missing suggestion you experienced there is expected behavior since param takes the place of self and there are no other parameters.
Suppose I have a python function that takes two arguments, but I want the second arg to be optional, with the default being whatever was passed as the first argument. So, I want to do something like this:
def myfunc(arg1, arg2=arg1):
print (arg1, arg2)
Except that doesn't work. The only workaround I can think of is this:
def myfunc(arg1, arg2=None):
if arg2 is None:
arg2 = arg1
print (arg1, arg2)
Is there a better way to do this?
As #Ignacio says, you can't do this. In your latter example, you might have a situation where None is a valid value for arg2. If this is the case, you can use a sentinel value:
sentinel = object()
def myfunc(arg1, arg2=sentinel):
if arg2 is sentinel:
arg2 = arg1
print (arg1, arg2)
myfunc("foo") # Prints 'foo foo'
myfunc("foo", None) # Prints 'foo None'
Not really. The other argument names don't exist until the function is actually entered.
The second way is fine in my opinion: it is exactly clear what you do, and for all those who will come after you and read the code.
While there is a slight overhead in documenting the default behavior, the use of 'None' or any other to make your function generate a default value is very common. Putting logic inside the function calls would certainly not be commendable in my opinion, it could become very complex very soon. So just leave it in the function body, where all the code is.
Suppose I have a python function that takes two arguments, but I want the second arg to be optional, with the default being whatever was passed as the first argument. So, I want to do something like this:
def myfunc(arg1, arg2=arg1):
print (arg1, arg2)
Except that doesn't work. The only workaround I can think of is this:
def myfunc(arg1, arg2=None):
if arg2 is None:
arg2 = arg1
print (arg1, arg2)
Is there a better way to do this?
As #Ignacio says, you can't do this. In your latter example, you might have a situation where None is a valid value for arg2. If this is the case, you can use a sentinel value:
sentinel = object()
def myfunc(arg1, arg2=sentinel):
if arg2 is sentinel:
arg2 = arg1
print (arg1, arg2)
myfunc("foo") # Prints 'foo foo'
myfunc("foo", None) # Prints 'foo None'
Not really. The other argument names don't exist until the function is actually entered.
The second way is fine in my opinion: it is exactly clear what you do, and for all those who will come after you and read the code.
While there is a slight overhead in documenting the default behavior, the use of 'None' or any other to make your function generate a default value is very common. Putting logic inside the function calls would certainly not be commendable in my opinion, it could become very complex very soon. So just leave it in the function body, where all the code is.
Suppose I have a function get_data which takes some number of keyword arguments. Is there some way I can do this
def get_data(arg1, **kwargs):
print arg1, arg2, arg3, arg4
arg1 = 1
data['arg2'] = 2
data['arg3'] = 3
data['arg4'] = 4
get_data(arg1, **data)
So the idea is to avoid typing the argument names in both function calling and function definition. I call the function with a dictionary as argument and the keys of the dictionary become local variables of function and their values are the dictionary values
I tried the above and got error saying global name 'arg2' is not defined. I understand I can change the locals() in the definition of get_data to get the desired behavior.
So my code would look like this
def get_data(arg1, kwargs):
locals().update(kwargs)
print arg1, arg2, arg3, arg4
arg1 = 1
data['arg2'] = 2
data['arg3'] = 3
data['arg4'] = 4
get_data(arg1, data)
and it wouldn't work too. Also cant I achieve the behavior without using locals()?
**kwargs is a plain dictionary. Try this:
def get_data(arg1, **kwargs):
print arg1, kwargs['arg2'], kwargs['arg3'], kwargs['arg4']
Also, check documentation on keyword arguments.
If we examine your example:
def get_data(arg1, **kwargs):
print arg1, arg2, arg3, arg4
In your get_data functions's namespace, there is a variable named arg1, but there is no variable named arg2. so you can not reach a function or a variable that is not in your namespace.
In fact, in your namespace; there is a variable arg1 and a dictionary object called kwargs. using ** notation before the kwargs (name kwargs is not important in here, it can be something else too.) tells your python compiler that kwargs is a dictionary and all values in that dictionary will be evaluated as named parameters in your function definition.
Lets take a look at this example:
def myFunc(**kwargs):
do something
myFunc(key1='mykey', key2=2)
when you call myFunc with named parameters key1 and key2, your function definition acts like
def myFunc(key1=None, key2=None):
but with an exception! since myFunc have no named parameters, compiler do not know how to handle them directly since you can pass any named parameter to your function.
So your function accept those named parameters within a dictionary like you call your function:
myFunc({key1:'mykey', key2:2})
so, your function definition get those parameters within a dictionary. **kwargs defines your dictionary in that point, which also tell compiler that any named parameters will be accepted (by the help of ** signs before the kwargs)
def myFunc(**kwargs):
print kwargs
will print
{key1:'mykey', key2:2}
So in your example, you can use kwargs like a dictionary;
def myFunc(**kwargs):
kwargs['arg2']
kwargs.get('arg3')
I hope it is not complicated (:
Suppose I have a python function that takes two arguments, but I want the second arg to be optional, with the default being whatever was passed as the first argument. So, I want to do something like this:
def myfunc(arg1, arg2=arg1):
print (arg1, arg2)
Except that doesn't work. The only workaround I can think of is this:
def myfunc(arg1, arg2=None):
if arg2 is None:
arg2 = arg1
print (arg1, arg2)
Is there a better way to do this?
As #Ignacio says, you can't do this. In your latter example, you might have a situation where None is a valid value for arg2. If this is the case, you can use a sentinel value:
sentinel = object()
def myfunc(arg1, arg2=sentinel):
if arg2 is sentinel:
arg2 = arg1
print (arg1, arg2)
myfunc("foo") # Prints 'foo foo'
myfunc("foo", None) # Prints 'foo None'
Not really. The other argument names don't exist until the function is actually entered.
The second way is fine in my opinion: it is exactly clear what you do, and for all those who will come after you and read the code.
While there is a slight overhead in documenting the default behavior, the use of 'None' or any other to make your function generate a default value is very common. Putting logic inside the function calls would certainly not be commendable in my opinion, it could become very complex very soon. So just leave it in the function body, where all the code is.