I have the following class and method:
class Basis(object):
def __init__(self, P = {'dimension': 1, 'generation':1}):
self.P = P
self.P['angle'] = np.pi/4
where P
is a dict
that does not include the 'angle'
, hence why I am setting it within the constructor (the angle is something fixed for now, but I might have it a user-defined funciton in the future).
Now I have a method:
def make_projection(self, dimension, angle = np.pi/4):
return (angle*3)
and I would like to set the default value of angle
in this function to the self.P['angle']
defined in the constructor.
I do not want to use the self.P['angle']
within the main code of the function, as I might use the method on its own giving it a different angle.
If I just do: def make_projection(self, dimension, angle = self.P['angle']):
, it underlines both self
and I do not understand why.
--
Is this something I am allowed to do?
First of all, the defaults for keywords arguments in methods can't be mutable objects, like list
, dict
, etc. Here you can read why.
Secondly, in def make_projection(self, dimension, angle = self.P['angle'])
the self
variable is still not defined, so you can get self.P
only in method's body.
Try this:
class Basis(object):
def __init__(self, P=None):
self.P = P or {'dimension': 1, 'generation':1}
self.P['angle'] = np.pi/4
def make_projection(self, dimension, angle=None):
angle = angle if angle is not None else self.P['angle'] # we must compare to None, because angle can be 0.
return angle*3
Python default values for arguments are evaluated when the function is defined, not when the function is called.
You need to do something like:
def foo(self, x, y=None):
if y is None:
y = self.defval
This is also the reason for which having a mutable default (e.g. a dictionary) is a dangerous trap in Python; if you change the value that was given by default you're also changing what will be the default in future calls.