I'd like to use a SimpleNameSpace which can also act as a mapping so to be able to be used with ** unpacking.
Here is what I've done:
class MySimpleNameSpace(object):
# my initial attempt subclassed SimpleNameSpace and Mapping, with
# possibility to use MySimpleNameSpace as a dict as well as a normal SimpleNameSpace.
def __init__(self, **kw):
self.__dict__.update(kw)
def __getitem__(self, item):
return getattr(self, item)
def keys(self):
return self.__dict__.keys()
So far so good:
def f(**kw):
print(kw)
ns = MySimpleNameSpace(a=42)
f(**ns)
Gives: {'a': 42}
More tricky:
ns.__getitem__ = "what"
ns.__iter__ = "da"
f(**ns)
Now gives:
{'a': 42, '__getitem__': "what", '__iter__', "da" }
But:
ns.keys = "douh"
f(**ns)
Obviously gives:
TypeError: attribute of type 'str' is not callable
Any idea if this would be feasible to have such a custom mapping class but able to use keys as a normal attribute?
I realize that subclassing (Mutable)Mapping makes this actually harder, if at all possible, but I think it's all because the functionality apparently requires the given object to have a keys method, which is unfortunate if we can't find a workaround for that.
As far as I know: iterating (__iter__) a dict gives its keys, then __getitem__ gives the value associated to a given key. As far as I know this would be all enough to implement the functionality?
Related
What is the difference between the two class definitions below,
class my_dict1(dict):
def __init__(self, data):
self = data.copy()
self.N = sum(self.values)
The above code results in AttributeError: 'dict' object has no attribute 'N', while the below code compiles
class my_dict2(dict):
def __init__(self, data):
for k, v in data.items():
self[k] = v
self.N = sum(self.values)
For example,
d = {'a': 3, 'b': 5}
a = my_dict1(d) # results in attribute error
b = my_dict2(d) # works fine
By assigning self itself to anything you assign self to a completely different instance than you were originally dealing with, making it no longer the "self". This instance will be of the broader type dict (because data is a dict), not of the narrower type my_dict1. You would need to do self["N"] in the first example for it to be interpreted without error, but note that even with this, in something like:
abc = mydict_1({})
abc will still not have the key "N" because a completely difference instance in __init__ was given a value for the key "N". This shows you that there's no reasonable scenario where you want to assign self itself to something else.
In regards to my_dict2, prefer composition over inheritance if you want to use a particular dict as a representation of your domain. This means having data as an instance field. See the related C# question Why not inherit from List?, the core answer is still the same. It comes down to whether you want to extend the dict mechanism vs. having a business object based on it.
I would like to know how to convert a python object from a dictionary (using python3 btw). I realize that this question has been asked (and answered) already (here). However, in my case the object is given entirely in terms of #property values, for example:
class Test:
#property
def value(self):
return 1.0
Regarding conversion to a dictionary: The __dict__ dictionary of the Test class is empty, and consequently, the vars
function does not work as expected:
>>> vars(Test())
{}
Still, I can use gettattr(Test(), 'value'), to obtain 1.0, so
the value is present.
Note: The reason I am coming up with this apparently contrived example is that I am trying to convert a cython cdef class (containing parameters) to a dictionary. The recommended way to wrap c structures with properties using cython is indeed based on properties.
I think you could use dir:
a = Test()
dir(a)
Output:
['__doc__', '__module__', 'value']
So you could maybe do something like:
d = {}
for attr in dir(a):
if not attr.startswith("__"):
d[attr] = getattr(a, attr)
Output:
d = {'value': 1.0}
Maybe you could abuse that:
In [10]: type(Test().__class__.__dict__['value']) is property
Out[10]: True
So you check the class of the object and if it has attribute of type property.
Here is how I would do it:
t = Test()
dictionary = {attr_name: getattr(t, attr_name)
for attr_name, method in t.__class__.__dict__.items()
if isinstance(method, property)}
It is even worse that that. You could imagine to build an instance __dict__ at init time, but that would not solve anything, except for read_only constant properties. Because the value in the dict will be a copy of the property at the time it was taken, and will not reflect future changes.
In Python,
Is there a way to access dict similar the way a method is invoked on an object. Scenario is, I thought to create a class with just attributes, there are no methods. And I came across few discussion on this scenario Python: Should I use a class or dictionary?. I've decided to go for dict instead of class.
No I would just like to understand, is there a way I can access elements of dict similar to method invocation on a object?
mydict = {'a': 100, 'b': 20.5, 'c': 'Hello'}
Instead of,
mydict['a']
mydict['a'] = 200
Something like,
mydict.a
mydict.a = 200
namedtuple does solve one part, that is, I can initialize and read. But not to be intended to set/write values.
This is easily done by implementing __getattr__ and __setattr__ in a subclass:
class MyDict(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
I am looking for a way to create a basic python "object" which I can externally assign attributes to.
Currently I am doing it the following way:
I define an empty class with
class C(object):
pass
and then I instantiate an object and assign attributes like this:
c = C()
c.attr = 2
Coming to my question
Is there a way to instantiate an empty class object, which I can then assign attributes like shown above without defining a class C?
Is there maybe an other better way to accomplish what I am after?
It looks like you are looking for a flexible container that has no methods and can take attributes with arbitrary names. That's a dict.
d = dict()
d['myattr'] = 42
If you prefer the attribute syntax that you get with a class (c.myattr = 42), then use a class just as per the code in your question.
Is there a way to instantiate an empty class object, which I can then assign attributes like shown above without defining a class C?
Yes:
>>> C = type("C", (object,), {})
>>> c = C()
>>> c.attr = 2
But as you can see, it's not much of an improvement, and the end result is the same -- it's just another way of creating the same class C.
Addendum:
You can make it prettier by "hiding" it in a function:
def attr_holder(cls=type("C", (object,), {})):
return cls()
c = attr_holder()
c.attr = 2
Though this is just reinventing the wheel -- replace the two line function with
class attr_holder(object):
pass
and it'll work exactly the same, and we've come full circle. So: go with what David or Reorx suggests.
I had come to the same question long ago, and then create this class to use in many of my projects:
class DotDict(dict):
"""
retrieve value of dict in dot style
"""
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError('has no attribute %s' % key)
def __setattr__(self, key, value):
self[key] = value
def __delattr__(self, key):
try:
del self[key]
except KeyError:
raise AttributeError(key)
def __str__(self):
return '<DotDict %s >' % self.__to_dict()
def __to_dict(self):
return dict(self)
When I want a object to store data or want to retrieve value easily from a dict, I always use this class.
Additionally, it can help me serialize the attributes that I set in the object, and reversely get the original dict when needed.
So I think this may be a good solution in many situations, though other tricks look simple,
they are not very helpful further.
I have a class that inherits from a dictionary in order to add some custom behavior - in this case it passes each key and value to a function for validation. In the example below, the 'validation' simply prints a message.
Assignment to the dictionary works as expected, printing messages whenever items are added to the dict. But when I try to use the custom dictionary type as the __dict__ attribute of a class, attribute assignments, which in turn puts keys/values into my custom dictionary class, somehow manages to insert values into the dictionary while completely bypassing __setitem__ (and the other methods I've defined that may add keys).
The custom dictionary:
from collections import MutableMapping
class ValidatedDict(dict):
"""A dictionary that passes each value it ends up storing through
a given validator function.
"""
def __init__(self, validator, *args, **kwargs):
self.__validator = validator
self.update(*args, **kwargs)
def __setitem__(self, key, value):
self.__validator(value)
self.__validator(key)
dict.__setitem__(self, key, value)
def copy(self): pass # snipped
def fromkeys(validator, seq, v = None): pass # snipped
setdefault = MutableMapping.setdefault
update = MutableMapping.update
def Validator(i): print "Validating:", i
Using it as the __dict__ attribute of a class yields behavior I don't understand.
>>> d = ValidatedDict(Validator)
>>> d["key"] = "value"
Validating: value
Validating: key
>>> class Foo(object): pass
...
>>> foo = Foo()
>>> foo.__dict__ = ValidatedDict(Validator)
>>> type(foo.__dict__)
<class '__main__.ValidatedDict'>
>>> foo.bar = 100 # Yields no message!
>>> foo.__dict__['odd'] = 99
Validating: 99
Validating: odd
>>> foo.__dict__
{'odd': 99, 'bar': 100}
Can someone explain why it doesn't behave the way I expect? Can it or can't it work the way I'm attempting?
This is an optimization. To support metamethods on __dict__, every single instance assignment would need to check the existance of the metamethod. This is a fundamental operation--every attribute lookup and assignment--so the extra couple branches needed to check this would become overhead for the whole language, for something that's more or less redundant with obj.__getattr__ and obj.__setattr__.