I would like to create new variables from a list.
For example:
mylist=[A,B,C]
From which i would like to create the following variables:
self.varA
self.varB
self.varC
How can create these new variables in a loop?
mylist=['A','B','C']
for name in mylist:
setattr(self, name, None)
but this is nearly always a bad idea and the values should be in a dict like:
self.v = {}
for name in mylist:
self.v[name] = None
Your question ignores the fact that the variables need values ... who is going to supply what values how? Here is a solution to one of the possible clarified questions:
With this approach, the caller of your constructor can use either a dict or keyword args to pass in the names and values.
>>> class X(object):
... def __init__(self, **kwargs):
... for k in kwargs:
... setattr(self, k, kwargs[k])
...
# using a dict
>>> kandv = dict([('foo', 'bar'), ('magic', 42), ('nix', None)])
>>> print X(**kandv).__dict__
{'nix': None, 'foo': 'bar', 'magic': 42}
# using keyword args
>>> print X(foo='bar', magic=42, nix=None).__dict__
{'nix': None, 'foo': 'bar', 'magic': 42}
Related
I'm trying to get a key-value item from a dictionary using a key instead of getting only the value.
I understand that I could do something like
foo = {"bar":"baz", "hello":"world"}
some_item = {"bar": foo.get("bar")}
But here I need to type out the key twice, which seems a bit redundant. Is there some direct way to get the key-value pair for the key bar? Something like
foo.get_item("bar")
>>> {"bar": "baz"}
One way or another, you'll need to bind "bar" to a variable.
>>> foo = {"bar":"baz", "hello":"world"}
>>> (lambda k="bar": {k: foo[k]})()
{'bar': 'baz'}
or:
>>> k = "bar"
>>> {k: foo[k]}
{'bar': 'baz'}
or:
>>> def item(d, k):
... return {k: d[k]}
...
>>> item(foo, "bar")
{'bar': 'baz'}
It's possible to extend dict to create your own methods. It could be useful if you're the one creating the initial dictionary in the first place.
class MyDict(dict):
def fetch(self, key):
return {key:self.get(key)}
The downside is you would need to recast regular dictionaries (assuming you didn't create the initial)
new_foo = MyDict(foo)
some_item = new_foo.fetch("bar")
But in this case it would probably be easier just to use a lambda (see Samwise's answer)
you can get the key value pair for key 'bar' by doing something like ->
foo = {"bar":"baz", "hello":"world"}
some_item = {k:v for k,v in foo.items() if k=='bar'}
I'm trying to generate a dict containing the names and the value of the non-None parameters current call. This very much feels like something that should be a built-in, but can't find anything that quite does it in the Python documentation.
For example, when
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
# code to generate dict of non-`None` named arguments (see below)
... # other things happen later
is called with the parameters foo(limit=5, lower_bound=100), I need the following dict: {limit=5, lower_bound=100}.
Is there something that conveniently does that for me?
Potential Solutions
So far, I have looked into the following, all of which seem flawed:
Manually making lists (which has a downside of having more places to things to make changes if, for example, an argument has its name changed)
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
keys = ('limit', 'offset', 'lower_bound', 'upper_bound')
values = (limit, offset, lower_bound, upper_bound)
magic_dict = {k: v for k, v in zip(keys, values) if v is not None}
locals() — link — which would need everything removed that shouldn't make it into the dictionary (i.e. the keys with the value of None). This also seems potentially error prone if variables definitions get added above the magic dictionary code, which would also need to be removed.
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
magic_dict = {k: v for k, v in locals().items() if v is not None}
inspect's — link — signature and bind, which still requires would a list of the parameters
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
sig = signature(foo)
sig_args = sig.bind(limit, offset, lower_bound, upper_bound).arguments
magic_dict = {k: v for k, v in sig_args.items() if v is not None}
Other thoughts included making a class to make getattr available
It feels like I'm missing something obvious — feedback would be appreciated!
Someone suggested
What is an elegant way to select all non-None elements from parameters and place them in a python dictionary?, whose responses are primarily "move to **kwargs". My initial reaction is that I would prefer to keep a specific list of arguments — is that bad logic by me? What is typical best practice with Python?
You can try using decorators:
def capture(func):
capture.kwds = None
def wrap(*args, **kwargs):
capture.kwds = kwargs
return func(*args, **kwargs)
return wrap
#capture
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
return None
Now you can call:
>>> foo(limit=1, offset=2, lower_bound=3, upper_bound=4)
None
>>> capture.kwds
{'limit': 1, 'offset': 2, 'lower_bound': 3, 'upper_bound': 4}
You can also use the locals method, but copy the locals at the top of your function. At the end one can use the keys of the original locals and select only those in the return statement:
def foo(a=None, b=None, c=None):
original_locals = locals().copy()
d = 'test' #Test adding new variable which should not be returned
return {k:v for k,v in locals().items() if k in original_locals.keys() and v is not None}
foo(1)
>> {'a': 1}
foo(1, 2, 3)
>> {'a': 11, 'b': 2, 'c': 3}
Note that you have to copy the locals, otherwise this method will not work.
If you also want to add kwargs:
def func(a=None, b=None, c=None, **kwargs):
org_loc = locals().copy()
def check_kwargs(d):
if 'kwargs' in d.keys():
d.update(d['kwargs'])
del d['kwargs']
check_kwargs(org_loc)
d = 'test'
new_loc = locals()
check_kwargs(new_loc)
return {k:v for k,v in new_loc.items() if k in org_loc.keys() and v is not None}
Then:
func(1)
>> {'a':1}
func(1, test='test')
>> {'a': 1, 'test': 'test'}
I have a large list like:
[A][B1][C1]=1
[A][B1][C2]=2
[A][B2]=3
[D][E][F][G]=4
I want to build a multi-level dict like:
A
--B1
-----C1=1
-----C2=1
--B2=3
D
--E
----F
------G=4
I know that if I use recursive defaultdict I can write table[A][B1][C1]=1, table[A][B2]=2, but this works only if I hardcode those insert statement.
While parsing the list, I don't how many []'s I need beforehand to call table[key1][key2][...].
You can do it without even defining a class:
from collections import defaultdict
nested_dict = lambda: defaultdict(nested_dict)
nest = nested_dict()
nest[0][1][2][3][4][5] = 6
Your example says that at any level there can be a value, and also a dictionary of sub-elements. That is called a tree, and there are many implementations available for them. This is one:
from collections import defaultdict
class Tree(defaultdict):
def __init__(self, value=None):
super(Tree, self).__init__(Tree)
self.value = value
root = Tree()
root.value = 1
root['a']['b'].value = 3
print root.value
print root['a']['b'].value
print root['c']['d']['f'].value
Outputs:
1
3
None
You could do something similar by writing the input in JSON and using json.load to read it as a structure of nested dictionaries.
I think the simplest implementation of a recursive dictionary is this. Only leaf nodes can contain values.
# Define recursive dictionary
from collections import defaultdict
tree = lambda: defaultdict(tree)
Usage:
# Create instance
mydict = tree()
mydict['a'] = 1
mydict['b']['a'] = 2
mydict['c']
mydict['d']['a']['b'] = 0
# Print
import prettyprint
prettyprint.pp(mydict)
Output:
{
"a": 1,
"b": {
"a": 1
},
"c": {},
"d": {
"a": {
"b": 0
}
}
}
I'd do it with a subclass of dict that defines __missing__:
>>> class NestedDict(dict):
... def __missing__(self, key):
... self[key] = NestedDict()
... return self[key]
...
>>> table = NestedDict()
>>> table['A']['B1']['C1'] = 1
>>> table
{'A': {'B1': {'C1': 1}}}
You can't do it directly with defaultdict because defaultdict expects the factory function at initialization time, but at initialization time, there's no way to describe the same defaultdict. The above construct does the same thing that default dict does, but since it's a named class (NestedDict), it can reference itself as missing keys are encountered. It is also possible to subclass defaultdict and override __init__.
This is equivalent to the above, but avoiding lambda notation. Perhaps easier to read ?
def dict_factory():
return defaultdict(dict_factory)
your_dict = dict_factory()
Also -- from the comments -- if you'd like to update from an existing dict, you can simply call
your_dict[0][1][2].update({"some_key":"some_value"})
In order to add values to the dict.
Dan O'Huiginn posted a very nice solution on his journal in 2010:
http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html
>>> class NestedDict(dict):
... def __getitem__(self, key):
... if key in self: return self.get(key)
... return self.setdefault(key, NestedDict())
>>> eggs = NestedDict()
>>> eggs[1][2][3][4][5]
{}
>>> eggs
{1: {2: {3: {4: {5: {}}}}}}
You may achieve this with a recursive defaultdict.
from collections import defaultdict
def tree():
def the_tree():
return defaultdict(the_tree)
return the_tree()
It is important to protect the default factory name, the_tree here, in a closure ("private" local function scope). Avoid using a one-liner lambda version, which is bugged due to Python's late binding closures, and implement this with a def instead.
The accepted answer, using a lambda, has a flaw where instances must rely on the nested_dict name existing in an outer scope. If for whatever reason the factory name can not be resolved (e.g. it was rebound or deleted) then pre-existing instances will also become subtly broken:
>>> nested_dict = lambda: defaultdict(nested_dict)
>>> nest = nested_dict()
>>> nest[0][1][2][3][4][6] = 7
>>> del nested_dict
>>> nest[8][9] = 10
# NameError: name 'nested_dict' is not defined
To add to #Hugo To have a max depth:
l=lambda x:defaultdict(lambda:l(x-1)) if x>0 else defaultdict(dict)
arr = l(2)
A slightly different possibility that allows regular dictionary initialization:
from collections import defaultdict
def superdict(arg=()):
update = lambda obj, arg: obj.update(arg) or obj
return update(defaultdict(superdict), arg)
Example:
>>> d = {"a":1}
>>> sd = superdict(d)
>>> sd["b"]["c"] = 2
You could use a NestedDict.
from ndicts.ndicts import NestedDict
nd = NestedDict()
nd[0, 1, 2, 3, 4, 5] = 6
The result as a dictionary:
>>> nd.to_dict()
{0: {1: {2: {3: {4: {5: 6}}}}}}
To install ndicts
pip install ndicts
I have a large list like:
[A][B1][C1]=1
[A][B1][C2]=2
[A][B2]=3
[D][E][F][G]=4
I want to build a multi-level dict like:
A
--B1
-----C1=1
-----C2=1
--B2=3
D
--E
----F
------G=4
I know that if I use recursive defaultdict I can write table[A][B1][C1]=1, table[A][B2]=2, but this works only if I hardcode those insert statement.
While parsing the list, I don't how many []'s I need beforehand to call table[key1][key2][...].
You can do it without even defining a class:
from collections import defaultdict
nested_dict = lambda: defaultdict(nested_dict)
nest = nested_dict()
nest[0][1][2][3][4][5] = 6
Your example says that at any level there can be a value, and also a dictionary of sub-elements. That is called a tree, and there are many implementations available for them. This is one:
from collections import defaultdict
class Tree(defaultdict):
def __init__(self, value=None):
super(Tree, self).__init__(Tree)
self.value = value
root = Tree()
root.value = 1
root['a']['b'].value = 3
print root.value
print root['a']['b'].value
print root['c']['d']['f'].value
Outputs:
1
3
None
You could do something similar by writing the input in JSON and using json.load to read it as a structure of nested dictionaries.
I think the simplest implementation of a recursive dictionary is this. Only leaf nodes can contain values.
# Define recursive dictionary
from collections import defaultdict
tree = lambda: defaultdict(tree)
Usage:
# Create instance
mydict = tree()
mydict['a'] = 1
mydict['b']['a'] = 2
mydict['c']
mydict['d']['a']['b'] = 0
# Print
import prettyprint
prettyprint.pp(mydict)
Output:
{
"a": 1,
"b": {
"a": 1
},
"c": {},
"d": {
"a": {
"b": 0
}
}
}
I'd do it with a subclass of dict that defines __missing__:
>>> class NestedDict(dict):
... def __missing__(self, key):
... self[key] = NestedDict()
... return self[key]
...
>>> table = NestedDict()
>>> table['A']['B1']['C1'] = 1
>>> table
{'A': {'B1': {'C1': 1}}}
You can't do it directly with defaultdict because defaultdict expects the factory function at initialization time, but at initialization time, there's no way to describe the same defaultdict. The above construct does the same thing that default dict does, but since it's a named class (NestedDict), it can reference itself as missing keys are encountered. It is also possible to subclass defaultdict and override __init__.
This is equivalent to the above, but avoiding lambda notation. Perhaps easier to read ?
def dict_factory():
return defaultdict(dict_factory)
your_dict = dict_factory()
Also -- from the comments -- if you'd like to update from an existing dict, you can simply call
your_dict[0][1][2].update({"some_key":"some_value"})
In order to add values to the dict.
Dan O'Huiginn posted a very nice solution on his journal in 2010:
http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html
>>> class NestedDict(dict):
... def __getitem__(self, key):
... if key in self: return self.get(key)
... return self.setdefault(key, NestedDict())
>>> eggs = NestedDict()
>>> eggs[1][2][3][4][5]
{}
>>> eggs
{1: {2: {3: {4: {5: {}}}}}}
You may achieve this with a recursive defaultdict.
from collections import defaultdict
def tree():
def the_tree():
return defaultdict(the_tree)
return the_tree()
It is important to protect the default factory name, the_tree here, in a closure ("private" local function scope). Avoid using a one-liner lambda version, which is bugged due to Python's late binding closures, and implement this with a def instead.
The accepted answer, using a lambda, has a flaw where instances must rely on the nested_dict name existing in an outer scope. If for whatever reason the factory name can not be resolved (e.g. it was rebound or deleted) then pre-existing instances will also become subtly broken:
>>> nested_dict = lambda: defaultdict(nested_dict)
>>> nest = nested_dict()
>>> nest[0][1][2][3][4][6] = 7
>>> del nested_dict
>>> nest[8][9] = 10
# NameError: name 'nested_dict' is not defined
To add to #Hugo To have a max depth:
l=lambda x:defaultdict(lambda:l(x-1)) if x>0 else defaultdict(dict)
arr = l(2)
A slightly different possibility that allows regular dictionary initialization:
from collections import defaultdict
def superdict(arg=()):
update = lambda obj, arg: obj.update(arg) or obj
return update(defaultdict(superdict), arg)
Example:
>>> d = {"a":1}
>>> sd = superdict(d)
>>> sd["b"]["c"] = 2
You could use a NestedDict.
from ndicts.ndicts import NestedDict
nd = NestedDict()
nd[0, 1, 2, 3, 4, 5] = 6
The result as a dictionary:
>>> nd.to_dict()
{0: {1: {2: {3: {4: {5: 6}}}}}}
To install ndicts
pip install ndicts
Is there a built-in function/operator I could use to unpack values from a dictionary and assign it into instance variables?
This is what I intend to do:
c = MyClass()
c.foo = 123
c.bar = 123
# c.foo == 123 and c.bar == 123
d = {'bar': 456}
c.update(d)
# c.foo == 123 and c.bar == 456
Something akin to dictionary update() which load values from another dictionary but for plain object/class instance?
there is also another way of doing it by looping through the items in d. this doesn't have the same assuption that they will get stored in c.__dict__ which isn't always true.
d = {'bar': 456}
for key,value in d.items():
setattr(c,key,value)
or you could write a update method as part of MyClass so that c.update(d) works like you expected it to.
def update(self,newdata):
for key,value in newdata.items():
setattr(self,key,value)
check out the help for setattr
setattr(...)
setattr(object, name, value)
Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
''x.y = v''.
Have you tried
f.__dict__.update( b )
?
Also, maybe it would be good style to have a wrapper around the dict's update method:
def update(self, b):
self.__dict__.update(b)
PS: Sorry for not commenting at #S.Lott 's post but I don't have the rep yet.
You can try doing:
def to_object(my_object, my_dict):
for key, value in my_dict.items():
attr = getattr(my_object, key)
if hasattr(attr, '__dict__'):
to_object(attr, value)
else:
setattr(my_object, key, value)
obj = MyObject()
data = {'a': 1, 'b': 2}
to_object(obj, data)