how can I express this idea in Pythonic way? The problem is that I want to create class with many attributes, but don't want to initialize all in __init__(self, arg1, arg2, ..., argN). Instead of this I want use some like this:
class DummyUpdater(object):
def from_dict(self, d):
self.__dict__.update(d)
return self
def __repr__(self):
attributes = inspect.getmembers(self.__class__, lambda a: not(inspect.isroutine(a)))
return '{}'.format({a[0]: getattr(self, a[0]) for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))})
class Passenger(DummyUpdater):
"""docstring for Passenger"""
first_name = ''
last_name = ''
middle_name = ''
title = ''
maturity = ''
document_number = ''
document_type = ''
What is used now (with dummy updater):
passenger = Passenger().from_dict({'first_name' : 'Name', ...})
What I want to achive:
passenger = Passenger({'first_name' : 'Name', ...})
# and when I print passenger object I want see
print(passenger) # {'first_name' : 'Name', ...}
1 Answer 1
Python and the power of unpacking may help you in this one,
As it is unclear how your Class is used, I will give an example of how to initialize the dictionary with unpacking. This will work on any iterable.
True to it's name, what this does is pack all the arguments that this method call receives into one single variable, a tuple called *args. The same principle applies to **kwargs too, except that in this case it applies to keyword arguments. This most of the time corresponds to dictionaries
An example on how to use **kwargs
to initialise your dictionary class
class DummyUpdater(object):
def __init__(self, iterable=(), **kwargs):
self.__dict__.update(iterable, **kwargs)
class Passenger(DummyUpdater):
def __init__(self, iterable=(), **kwargs):
super().__init__(iterable, **kwargs)
# See the power of unpacking!
# We can create a class like this just with variables
d = DummyUpdater(first_name="abc", last_name='sgkf', middle_name='something else', title='ook iets', maturity='', doc_num='4', doc_type='1900')
# Or with a dictionary
d2 = Passenger({'first_name' : 'abc', 'last_name' : 'def'}) # etc..
EDIT
I am unsure if this is in scope or not, since this question doesn't address this at all, but since @Peilonrayz attended me to the usage of __slots__
I learned something myself and am willing to share this with everyone who is interested.
Secondly setting up a class this way, will imrprove memory usage a lot!
class DummyUpdater(object):
__slots__ = ['first_name', 'last_name']
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
class Passenger(DummyUpdater):
__slots__ = ['first_name', 'last_name']
def __init__(self, **kwargs):
super().__init__(**kwargs)
# SLOTS MAGIC
# HOWTO init from variables
p = Passenger(first_name='abc', last_name='def')
print(p.first_name) # prints abs
print(p.last_name) # prints def
# HOWTO init from a dict, notice how I unpack the dictionary to pass all the variables
p2 = Passenger(**{'first_name':'abc', 'last_name':'def'})
print(p2.first_name) # prints abc
print(p2.last_name) # prints def
-
\$\begingroup\$ If you add
__slots__
to this, then the code stops working as expected. Say you add__slots__ = ['a']
toPassenger
, then usePassenger(a='A').a
you'll get anAttributeError
on trying to reada
. \$\endgroup\$2017年07月26日 09:14:39 +00:00Commented Jul 26, 2017 at 9:14 -
\$\begingroup\$ You are correct, I'm still a beginner myself and to be honest never even heard of
__slots__
. You made me learn something new :), but I would not know how to solve this. \$\endgroup\$Ludisposed– Ludisposed2017年07月26日 09:31:39 +00:00Commented Jul 26, 2017 at 9:31 -
\$\begingroup\$ No problem Ludisposed, :) I found it only half a year or so ago. You can use
setattr
to fix this :) \$\endgroup\$2017年07月26日 09:33:31 +00:00Commented Jul 26, 2017 at 9:33
Explore related questions
See similar questions with these tags.
Passenger
. Also, can you fix your docstring. \$\endgroup\$