What is the best way to define a class method __init__ with optional keyword arguments?
I want the class to do the following:
class Player:
def __init__(self, **kwargs):
try:
self.last_name = kwargs['last_name']
except:
pass
try:
self.first_name = kwargs['first_name']
except:
pass
try:
self.score = kwargs['score']
except:
pass
But it looks sloppy to me. Is there a better way to define this __ init __ method ? I would like all keyword arguments to remain optional.
source to share
If you only have 3 arguments then Bhargav Rao's solution is more appropriate, but if you have a lot of potential arguments try:
class Player:
def __init__(self, **kwargs):
self.last_name = kwargs.get('last_name')
# .. etc.
kwargs.get('xxx')
will return the key xxx
if it exists and return None if it doesn't. .get
takes an optional second argument which is returned if xxx
not in kwargs
(instead of None
), eg. to set an attribute to an empty string use kwargs.get('xxx', "")
.
If you really want the attribute to be undefined, if it is not in kwargs
, then it will do this:
class Player:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
would be awesome behavior, so I suggest not doing it this way.
source to share
You can use keyword arguments :
class Player:
def __init__(self, last_name=None, first_name=None, score=None):
self.last_name = last_name
self.first_name = first_name
self.score = score
obj = Player('Max', 'Jhon')
print obj.first_name, obj.last_name
Jhon Max
With arguments ** kwargs
class Player:
def __init__(self, **args):
self.last_name = args.get('last_name')
self.first_name = args.get('first_name')
self.score = args.get('score', 0) # 0 is the default score.
obj = Player(first_name='Max', last_name='Jhon')
print obj.first_name, obj.last_name, obj.score
Max Jhon 0
source to share
Here's one way to do it, so it's easy to change:
class Player:
_VALID_KEYWORDS = {'last_name', 'first_name', 'score'}
def __init__(self, **kwargs):
for keyword, value in kwargs.items():
if keyword in self._VALID_KEYWORDS:
setattr(self, keyword, value)
else:
raise ValueError(
"Unknown keyword argument: {!r}".format(keyword))
Sample usage:
Player(last_name="George", attitude="snarky")
Results:
Traceback (most recent call last): File "keyword_checking.py", line 13, in <module> Player(last_name="George", attitude="snarky") File "keyword_checking.py", line 11, in __init__ raise ValueError("Unknown keyword argument: {!r}".format(keyword)) ValueError: Unknown keyword argument: 'attitude'
source to share
May I try this way:
#!/usr/bin/python
class Player(object):
def __init__(self, **kwargs):
for key, val in kwargs.items():
self.__dict__[key] = val
obj = Player(first_name='First', last_name='Last')
print obj.first_name
print obj.last_name
newobj = Player(first_name='First')
print newobj.first_name
Output:
First
Last
First
source to share
It depends on the end result you want. If you want to create a class where attributes are defined in a dictionary, you can use setattr.
class Player:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
In [1]: player = Player(first_name='john', last_name='wayne', score=100)
In [2]: player.first_name
Out[2]: 'john'
In [3]: player.last_name
Out[3]: 'wayne'
In [4]: player.score
Out[4]: 100
In [5]: player.address
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-6-0f7ee474d904> in <module>()
----> 1 player.address
AttributeError: 'Player' object has no attribute 'address'
source to share