getting a dictionary of class variables and values - python

I am working on a method to return all the class variables as keys and values as values of a dictionary , for instance i have:
first.py
class A:
a = 3
b = 5
c = 6
Then in the second.py i should be able to call maybe a method or something that will return a dictionary like this
import first
dict = first.return_class_variables()
dict
then dict will be something like this:
{'a' : 3, 'b' : 5, 'c' : 6}
This is just a scenario to explain the idea, of course i don't expect it to be that easy, but i will love if there are ideas on how to handle this problem just like dict can be used to set a class variables values by passing to it a dictionary with the variable, value combination as key, value.

You need to filter out functions and built-in class attributes.
>>> class A:
... a = 3
... b = 5
... c = 6
...
>>> {key:value for key, value in A.__dict__.items() if not key.startswith('__') and not callable(key)}
{'a': 3, 'c': 6, 'b': 5}

Something like this?
class A(object):
def __init__(self):
self.a = 3
self.b = 5
self.c = 6
def return_class_variables(A):
return(A.__dict__)
if __name__ == "__main__":
a = A()
print(return_class_variables(a))
which gives
{'a': 3, 'c': 6, 'b': 5}

Use a dict comprehension on A.__dict__ and filter out keys that start and end with __:
>>> class A:
a = 3
b = 5
c = 6
...
>>> {k:v for k, v in A.__dict__.items() if not (k.startswith('__')
and k.endswith('__'))}
{'a': 3, 'c': 6, 'b': 5}

Best solution and most pythonic is to use var(class_object) or var(self) (if trying to use inside class).
This although do avoids dictionary pairs where the key is another object and not a default python type.
>>> class TheClass():
>>> def __init__(self):
>>> self.a = 2
>>> self.b = 1
>>> print(vars(self))
>>> class_object= TheClass()
{'a'=2, 'b'=1}
Or outside class
>>> vars(class_object)
{'a': 2, 'b': 1}

You can use __dict__ to get the list of a class variables. For example, if you have a class like this:
class SomeClass:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def to_dict(self) -> dict:
return {key: value for key, value in self.__dict__.items()}
You can get the list of variables this way:
some_class = SomeClass(1,2,3)
some_class.to_dict()
And the output will be:
{'a':1, 'b':2, 'c':3}

Related

Python: modify variable stored as a value in a dictionary

I have the following situation:
>>> a = 1
>>> d = {"a": a}
>>> d
{'a': 1}
>>> d["a"] = 2
>>> d
{'a': 2}
>>> a
1
Of course this is the desired behaviour. However, when I assign 2 to the key "a" of the dictionary d, I would like to know if I can access the variable a instead of its value to modify the value of the variable a directly, accessing it through the dictionary. I.e. my expected last output would be
>>> a
2
Is there any way of doing this?
I suppose you know the idea of mutable and immutable objects. Immutable objects (str, int, float, etc) are passed by value. That's why your desired behaviour can't work. When you do:
a = 1
d["a"] = a
you just pass the value of a variable to your dict key 'a'. d['a'] knows nothing about variable a. They just both point to same primitive value in memory.
I don't know your case and why you need this behaviour, but you can try to use mutable object.
For example:
class A:
def __init__(self, a: int):
self._value = a
#property
def value(self) -> int:
return self._value
#value.setter
def value(self, a: int):
# you can put some additional logic for setting new value
self._value = a
def __int__(self) -> int:
return self._value
And then you can use it in this way:
>>> a = A(1)
>>> d = {"a": a}
>>> d['a'].value
1
>>> d["a"].value = 2
>>> d['a'].value
2
>>> a.value
2
>>> int(a)
2
But it still seems like an overhead and you should rethink whether you really need this behaviour.
When you do
>>> a
, you are calling the value of the variable, a that you set on the first line. You have not changed the value of that variable, hence the output of 1. If you did
>>> d["a"]
, your output would be
>>> 2
. If you want this value to be the variable a's value too, set the value of a to the value of d["a"].
Example-
>>> a = 1
>>> d = {"a": a}
>>> d
{'a': 1}
>>> d["a"] = 2
>>> d
{'a': 2}
>>> a = d["a"]
>>> a
2

Access Key of Dictionary inside self

Is it possible to access the key of a dictionary inside of the same dictionary?
For example, I know this doesn't work, but I want to do something like this:
d = {
'a': 1,
'b': 2,
'c': d['a'] + d['b'] # or actually more like: self.a + self.b
}
print(d['c']) # 3
You have to add the derived (key, value) pairs after contructing the dict.
d = {
'a': 1,
'b': 2
}
d['c'] = d['a'] + d['b']

Python: How to only pass needed arguments into function from a dictionary?

Assume now I have a well-defined function
def f1(a):
...
and i can not change its definition. Now I want to call it with a argument from a dictionary
D={ 'a':1 , 'b':2}
If I call it like
f1(**D)
there will be a syntax error (because b is not defined in f1). My question is if I can find a smart way to let the function to find the argument it needed only?
You can use inspect.getargspec:
d = {'a': 5, 'b': 6, 'c': 7}
def f(a,b):
return a + b
f(*[d[arg] for arg in inspect.getargspec(f).args])
which gives 11.
Thanks Eugene, getargspec is legacy, instead you should use getfullargspec which has the same usage in this case.
You could get the argument names from the function's code object, then lookup the values for them in the dictionary:
>>> def f(a):
... b = 2
... return a + b
...
>>> D = {'a': 1, 'b': 2, 'c': 3}
>>> nargs = f.__code__.co_argcount
>>> varnames = f.__code__.co_varnames
>>> f(*(D[arg] for arg in varnames[:nargs]))
3
Here is an example of function that got a dictionary and use only the 'b' key :
In [14]: def f1(mydict):
...: return mydict['b']
...:
In [15]: x={'a': 1, 'b':2}
In [16]: f1(x)
Out[16]: 2

When defining a Python dictionary, how can I use values of given fields to calculate an other field?

Consider the code
a = 2
b = 3
mylist = {'a' : a, 'b' : b, 'product' : a * b}
This produces a dictionary of three fields, of which the third is calculated using the values of the first and second. I am looking for a more compact definition of mylist. I have tried (1)
mylist = {'a' : 2, 'b' : 3, 'product' : a * b}
which gives the error
NameError: name 'a' is not defined
and (2)
mylist = {'a' : 2, 'b' : 3, 'product' : mylist['a'] * mylist['b']}
which gives the error
NameError: name 'mylist' is not defined
I would like to find a shorter command of the form (1) because you do not need to need to mention the name of the dictionary. Maybe there exists something like currentdictionary['a']?
I'd use something like a computed property in this case. It'll lazily evaluate the property when you need it; at call time. Much more robust than actively managing the product as a key-value pair.
class Pair(object):
def __init__(self, a, b):
self.a = a
self.b = b
#property
def product(self):
return self.a * self.b
Sample Output:
>>> Pair(2, 3).product
6
Using a dictionary here is possible but strikes me as a shoehorned solution, (1) you'd need to contend with checking if key(s) exist on lookup and (2) also maintaining a synchronized product should a or b change.
You could use a function to specify the desired keys of the dictionary and use inspect to view the signature at run time:
import inspect
a = 2
b = 3
def get_list(a, b, product):
pass
mylist = inspect.getcallargs(get_list, a, b, a*b)
Output:
{'a': 2, 'product': 6, 'b': 3}
The benefit of using a function in this case is that you can built a solution to find mylist around other potential objects in your code.
I can not think of a one liner to do that.
from functools import reduce
mylist = {'a' : 2, 'b' : 3}
mylist["product"] = reduce(lambda x,y: x*y, mylist.values())

How to set default value to all keys of a dict object in python?

I know you can use setdefault(key, value) to set default value for a given key, but is there a way to set default values of all keys to some value after creating a dict ?
Put it another way, I want the dict to return the specified default value for every key I didn't yet set.
You can replace your old dictionary with a defaultdict:
>>> from collections import defaultdict
>>> d = {'foo': 123, 'bar': 456}
>>> d['baz']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'baz'
>>> d = defaultdict(lambda: -1, d)
>>> d['baz']
-1
The "trick" here is that a defaultdict can be initialized with another dict. This means
that you preserve the existing values in your normal dict:
>>> d['foo']
123
Use defaultdict
from collections import defaultdict
a = {}
a = defaultdict(lambda:0,a)
a["anything"] # => 0
This is very useful for case like this,where default values for every key is set as 0:
results ={ 'pre-access' : {'count': 4, 'pass_count': 2},'no-access' : {'count': 55, 'pass_count': 19}
for k,v in results.iteritems():
a['count'] += v['count']
a['pass_count'] += v['pass_count']
In case you actually mean what you seem to ask, I'll provide this alternative answer.
You say you want the dict to return a specified value, you do not say you want to set that value at the same time, like defaultdict does. This will do so:
class DictWithDefault(dict):
def __init__(self, default, **kwargs):
self.default = default
super(DictWithDefault, self).__init__(**kwargs)
def __getitem__(self, key):
if key in self:
return super(DictWithDefault, self).__getitem__(key)
return self.default
Use like this:
d = DictWIthDefault(99, x=5, y=3)
print d["x"] # 5
print d[42] # 99
42 in d # False
d[42] = 3
42 in d # True
Alternatively, you can use a standard dict like this:
d = {3: 9, 4: 2}
default = 99
print d.get(3, default) # 9
print d.get(42, default) # 99
defaultdict can do something like that for you.
Example:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d
defaultdict(<class 'list'>, {})
>>> d['new'].append(10)
>>> d
defaultdict(<class 'list'>, {'new': [10]})
Is this what you want:
>>> d={'a':1,'b':2,'c':3}
>>> default_val=99
>>> for k in d:
... d[k]=default_val
...
>>> d
{'a': 99, 'b': 99, 'c': 99}
>>>
>>> d={'a':1,'b':2,'c':3}
>>> from collections import defaultdict
>>> d=defaultdict(lambda:99,d)
>>> d
defaultdict(<function <lambda> at 0x03D21630>, {'a': 1, 'c': 3, 'b': 2})
>>> d[3]
99
Not after creating it, no. But you could use a defaultdict in the first place, which sets default values when you initialize it.
You can use the following class. Just change zero to any default value you like. The solution was tested in Python 2.7.
class cDefaultDict(dict):
# dictionary that returns zero for missing keys
# keys with zero values are not stored
def __missing__(self,key):
return 0
def __setitem__(self, key, value):
if value==0:
if key in self: # returns zero anyway, so no need to store it
del self[key]
else:
dict.__setitem__(self, key, value)

Categories