I have written one method in python as follows :
def report(self,year,month):
print year,month
emptylist=[]
parameter month is optional. Sometimes it's NOT passed from the caller function but sometimes it is passed.How is this different from the following code ?
def func(self,*args,**kwargs):print args,kwargs I know this has simple answer but I'm new to python and programming stuff. Please help me out.
If month has a default value, you can try
def report(self, year, month='default_value'):
print year, month
emptylist = []
The value of month gets overwritten if passed
In addition to Ashoka's answer, it's normally a good idea to use None as the default value in the method's signature and assign the true default value with in function body. This makes it easier to wrap the function, pass arguments, and it also avoids problems with mutable default values.
def func(kwarg=None):
if kwarg is None:
kwarg = 'default'
print(kwarg)
func()
func(kwarg='Hello')
Related
I am trying to use the function below. Mostly when i call this function I just pass in the report_type but a few of the report calls wants a start_date. Questions
Does the None in the definition of function mean that the field is optional
def request_report(self, report_type, start_date=None, end_date=None, marketplaceids=()):
data = dict(Action='RequestReport',
ReportType=report_type,
StartDate=start_date,
EndDate=end_date)
data.update(utils.enumerate_param('MarketplaceIdList.Id.', marketplaceids))
return self.make_request(data)
I normally call the function with one of the lines below depending on if I am passing a start_date. Other then having a series of 'if' statements for each request type is there a good way to call this function and only pass a specific variable if it is populated? Over time I will be adding more optional parameters and done want a giant 'if' statement
requested_report=report_api.request_report(report_type=report_name, start_date=starting_date)
requested_report=report_api.request_report(report_type=report_name)
The =... part gives a parameter a default value. Here that's None, and that does mean the parameter is optional when calling the function. If you don't specify it, the default is used. See Default Argument Values in the Python tutorial, as well as the reference documentation for function definitions:
When one or more parameters have the form parameter = expression, the function is said to have “default parameter values.” For a parameter with a default value, the corresponding argument may be omitted from a call, in which case the parameter’s default value is substituted.
When calling such a function, you could pass in the same value as the default, to this specific function that makes no difference; so when there is no starting_date, you can pass in None:
start_date = starting_date or None # when determining the starting date, default to None
requested_report=report_api.request_report(
report_type=report_name,
start_date=starting_date
)
Another option is to set any optional keyword arguments in a dictionary, then pass those in with the ** call syntax to unpack the dictionary as keyword arguments:
kwargs = {}
if ...: # test that decides if start_date is needed
kwargs['start_date'] = starting_date # expression to set the start date
requested_report=report_api.request_report(
report_type=report_name, **kwargs)
It is fine for the kwargs dictionary to be empty.
It is called a default parameter.
Default parameter values are evaluated when the function definition is
executed
Here is the doc on method definition.
Here is additional information
I would personally like to know the semantic difference between using Pass and None. I could not able to find any difference in execution.
PS: I could not able to find any similar questions in SO. If you find one, please point it out.
Thanks!
pass is a statement. As such it can be used everywhere a statement can be used to do nothing.
None is an atom and as such an expression in its simplest form. It is also a keyword and a constant value for “nothing” (the only instance of the NoneType). Since it is an expression, it is valid in every place an expression is expected.
Usually, pass is used to signify an empty function body as in the following example:
def foo():
pass
This function does nothing since its only statement is the no-operation statement pass.
Since an expression is also a valid function body, you could also write this using None:
def foo():
None
While the function will behave identically, it is a bit different since the expression (while constant) will still be evaluated (although immediately discarded).
In simple terms, None is a value that you can assign to a variable that signifies emptiness. It can be useful as a default state:
a = None
def f():
a = 5
f()
pass is a statement that is like a nop. It can be useful when you are defining function stubs, for instance:
def f():
pass
In C-like languages, you would be able to define empty functions by simply putting nothing between the braces void f() { }, but since Python uses indentation instead of braces to define blocks, you must put something in the body, and pass is the idiomatic thing to put there.
That's absolute difference between pass and None
The pass (without upper case P):
Because python be the indent base language, so if you define a new method, you should have some code after that.
def method_a():
some_thing = 1 # Have to do some thing
If not, an exception should be raised so you could use the pass keyword for hacks this problem.
def method_a():
pass # Do nothing
The None:
So very different, the None keyword has a little bit same to the null keywords from another language like Java or C. That may be the empty data or not assign data like that.
[] == None
null == None
() == None
...
For example, I'd like to do something like: greet(,'hola'), where greet is:
def greet(person='stranger', greeting='hello')
This would help greatly for testing while writing code
Upon calling a function you can use the variable names to make it even more clear what variable will assume which value. At the same time, if defaults are provided in the function definition, skipping variables when calling the function does not raise any errors. So, in short you can just do this:
def greet(person='stranger', greeting='hello')
print('{} {}'.format(greeting, person))
return
greet(greeting='hola') # same as greet(person='stranger', greeting='hola')
# returns 'hola stranger'
Note that, as I said above this would not work if for example your function definition was like this:
def greet(person, greeting)
print('{} {}'.format(greeting, person))
return
Since in this case, Python would complain saying that it does not know what to do with person; no default is supplied..
And by the way, the problem you are describing is most likely the very reason defaults are used in the first place
Without knowing the other parameters, and only knowing that the parameter you want to change is in second position you could use the inspect module to get function signature & associated default values.
Then make a copy of the default values list and change the one at the index you want:
import inspect
def greet(person='stranger', greeting='hello'):
print(person,greeting)
argspec = inspect.getargspec(greet)
defaults = list(argspec.defaults)
defaults[1] = "hola" # change second default parameter
greet(**dict(zip(argspec.args,defaults)))
Assuming that all parameters have default values (else it shifts the lists an that fails) that prints:
stranger hola
Not being able to overload functions in Python brought me to look into *args and **kwargs to pass undefined amounts of arguments and variable definitions to a called function. I tried to apply that concept to a simple function that prints arguments to the screen using a seperator (and without the nasty "" around everything by the while). You can find the code snippet at the end of that post.
My problem is that I don't know the correct way to actually assign values of kwargs to their respective parameters OUTSIDE CLASSES. If I want use setattr which takes in 3 arguments (setatt(self, key, value)) it will, of course, always give me an error when I try to pass only a key and a value. Is there a proper way to assign values to parameters for global functions outside classes?
I hope you can clear the skies for me.
Here the not working code example which I wanna get to work by finding an alternative to setattr(self, key, value):
import sys
def printAll(*args, **kwargs):
sep = ""
for key, value in kwargs.items():
setattr(key, value)
for arg in args:
sys.stdout.write(str(arg))
sys.stdout.write(sep)
nr = 9876543210
printAll("How many", "arguments", " I want", nr, sep='-')
EDIT:
Ok, here is the updated and working example function after reading the answers of #Martijn Pieters and #Fabian:
def printAll(*args, **kwargs):
# use sep = 'value' to define a seperator or use the default one
sep = kwargs.get('sep')
if sep is None:
sep = ""
for arg in args:
sys.stdout.write(str(arg))
sys.stdout.write(sep)
Python 2:
def foo(*args, **kwargs):
for key, value in kwargs.iteritems():
locals()[key] = value
return foobar
exec ''
print foo(foobar=12)
This is not a good idea though. You should specifically access kwargs, as Martijn said. Generally you cannot modify locals() in a function, unless you put an exec statement in it. That forces the interpreter to access locals() again, because it's possible that the namespace has changed (and did, in this case). It's sufficient to put the exec statement right after the return so it will never be executed, as long as it's there.
Please don't do this.
You generally don't set kwargs values as local variables. It's a dictionary, just refer to the values contained:
sys.stdout.write(kwargs.get('sep', ''))
I'm attempting to write a class method that takes 3 keyword arguments. I've used keyword arguments before but can't seem to get it to work inside of my class. The following code:
def gamesplayed(self, team = None, startyear = self._firstseason,
endyear = self._lastseason):
totalGames = 0
for i in self._seasons:
if((i.getTeam() == team or team == "null") and
i.getYear() >= startyear and i.getYear() <= endyear):
totalGames += i .getGames()
return totalGames
produces the error:
NameError: name 'self' is not defined
If I take out the keyword arguments and make them simple positional ones, it works fine. Therefore I am not sure where my problems lies. Thanks in advance for any help.
def gamesplayed(self, team = None, startyear = self._firstseason, endyear = self._lastseason):
In the function declaration you are trying to reference instance variables using self. This however does not work as self is just a variable name for the first argument of the function which gets a reference to the current instance passed in. As such, self is especially not a keyword that always points to the current instance (unlike this in other languages). This also means that the variable is not yet defined during the declaration of the function.
What you should do is to simply preset those parameters with None, and preset them to those values in that case inside the function body. This also allows users to actually parse a value to the method that results in the default values without having to actually access the values from somewhere inside your class.
Default values for keyword arguments are bound at module construction time, not at class instance construction time. This is why self is not defined in this context.
The same fact about default values can create all sorts of problems any time you want a keyword argument where the default value updates every time the function is called. When you run the program, you'll find that the default value you expect to be updating is always set to the value constructed when the module was first initialized.
I would advise using None as a default keyword parameter in both instances, as poke and others have suggested. Your code could look something like:
def gamesplayed(self, team=None, startyear=None, endyear=None):
if not startyear:
startyear = self._firstseason
if not endyear:
endyear = self._lastseason