I add dynamically new values to a dictionary. When I call it, I am expecting it to be loaded with the recently added values.
class Elements():
def __init__(self, length):
self.dict = {}
self.length = length
self.init_dict()
def init_dict(self):
self.dict[0] = self.length
return self.dict[0]
def dict_update(self):
self.dict.update({1: self.dict[0] + 1})
return self.dict
Elements(100)
print Elements(100).dict
print Elements(100).dict_update()
print Elements(100).dict
This returns back:
{0: 100}, {0: 100, 1: 101}, {0: 100}
whereas I am expecting
{0: 100}, {0: 100, 1: 101}, {0: 100, 1: 101}
Let me explain:
Elements(100) # New element created.
print Elements(100).dict # Print dict from a new element created.
print Elements(100).dict_update() # Print what is returned from dict_update from a new element created. In this case, the dict is updated as well.
print Elements(100).dict # Print dict from a new element created. So this object is not related to the old updated one.
So you are printing the dict value from a newly created object of Element, and it is not related to the object you updated.
To fix this problem, you need to refer to 1 object only.
ele = Elements(100)
print ele.dict
print ele.dict_update()
print ele.dict
Try this:
class Elements():
def __init__(self, length):
self.dict = {}
self.length = length
self.init_dict()
def init_dict(self):
self.dict[0] = self.length
return self.dict[0]
def dict_update(self):
self.dict.update({1: self.dict[0] + 1})
return self.dict
E = Elements(100)
print E.dict
print E.dict_update()
print E.dict
Related
I'm working on project and got a problem. When I tried to get the element of dictionary I got key error. Although when I doesn't use variable numer the program works. Even when variable = 2 The program doesn't work. Code:
from typing import Sequence
class Lot:
def __init__(self, numer_lotu, id_samolotu,
czas_lotu, trasa, bramka,
cenaek, cenabiz, cenapr,
nrwolek = None, nrwolbiz= None, nrwolpr = None):
self.numer_lotu = numer_lotu
self.id_samolotu = id_samolotu
self.czas_lotu = czas_lotu
self.trasa = trasa
self.bramka = bramka
self.cenaek = cenaek
self.cenabiz = cenabiz
self.cenapr = cenapr
self.nrwolek = nrwolek
self.nrwolbiz = nrwolbiz
self.nrwolpr = nrwolpr
def get_numer_lotu(self):
return self.numer_lotu
def get_id_samolotu(self):
return self.id_samolotu
def get_czas_lotu(self):
return self.czas_lotu
def get_trasa(self):
return self.trasa
def get_bramka(self):
return self.bramka
def get_cenaek(self):
return self.cenaek
def get_cenabiz(self):
return self.cenabiz
def get_cenapr(self):
return self.cenapr
def get_wolnemiejscaek(self):
return self.nrwolek
def get_wolnemiejscabiz(self):
return self.nrwolbiz
def get_wolnemiejscapr(self):
return self.nrwolpr
class DatabaseofLoty():
def __init__(self, list_of_samolot : Sequence[Lot] = ()):
self.list_of_samoloty = {lot.get_numer_lotu() : lot
for lot in list_of_samolot}
print(self.list_of_samoloty)
self.list_of_samolot = list_of_samolot
def get_list(self):
return self.list_of_samolot
def get_dictionary(self):
return self.list_of_samoloty
def get_loty_by_numer_lotu(self, numer):
print(self.list_of_samoloty[2])
print(numer)
return self.list_of_samoloty[numer]
When I tried to run this I got this as an output:
{1: <lociki.Lot object at 0x7f4443f9ec70>}
{1: <lociki.Lot object at 0x7f4443f9ec70>, 2: <lociki.Lot object at 0x7f4443f9edc0>}
{1: <lociki.Lot object at 0x7f4443fa2c10>}
{1: <lociki.Lot object at 0x7f4443fa2c10>, 2: <lociki.Lot object at 0x7f4443f42670>}
<lociki.Lot object at 0x7f4443f42670>
2
KeyError: '2'
2 (int), which is your key is not the same as '2' (str), which is what numer contains
Consider this simplified class:
class test(object):
def __init__(self):
self.inner_dict = {}
def nested_set_method(self, keys,value=None):
end = len(keys) - 1
for index, component in enumerate(keys):
if index < end or value is None:
self.inner_dict = self.inner_dict.setdefault(component, {})
else:
self.inner_dict[component] = value
and this function which is identical to nested_set_method of the above class:
def nested_set_standalone(input_dict, keys,value=None):
end = len(keys) - 1
for index, component in enumerate(keys):
if index < end or value is None:
input_dict = input_dict.setdefault(component, {})
else:
input_dict[component] = value
This is a sample usage of the class:
>>> a = test()
>>> a.inner_dict
{}
>>> a.nested_set_method([1,2,3,4],'l')
>>> a.inner_dict
{4: 'l'}
This is the sample usage of the function over an instance of the class:
>>> b = test()
>>> b.inner_dict
{}
>>> nested_set_standalone(b.inner_dict,[1,2,3,4],'l')
>>> b.inner_dict
{1: {2: {3: {4: 'l'}}}}
I expected the class's nested_set_method with this output {4: 'l'} to have the same output as the function nested_set_standalone which is {1: {2: {3: {4: 'l'}}}}.
But why are they different?
EDIT: I ran these examples on Python 3.6.6
inner_dict in the function is a local variable, but in the method it changes the attribute. Simply, use a local variable, too:
class test(object):
def __init__(self):
self.inner_dict = {}
def get_nested_dict(self, keys):
inner_dict = self.inner_dict
for component in keys:
inner_dict = inner_dict.setdefault(component, {})
return inner_dict
def nested_set_method(self, keys,value=None):
if value is None:
return self.get_nested_dict(keys)
else:
inner_dict = self.get_nested_dict(keys[:-1])
inner_dict[keys[-1]] = value
I'm trying to implement simple tree class which is inherited from dictionary.
Here my code:
class tree(dict):
def __init__(self, hsymbol="/"):
self.hsymbol = hsymbol
def __setitem__(self, key, value):
if key[0] == self.hsymbol : key = key[1:]
parts = key.split(self.hsymbol, 1)
if len(parts) == 2:
if parts[0] not in self: self[parts[0]] = tree(hsymbol = self.hsymbol)
self[parts[0]].__setitem__(parts[1], value)
else:
super(tree, self).__setitem__(key, value)
def __getitem__(self, key):
if key[0] == self.hsymbol : key = key[1:]
parts = key.split(self.hsymbol, 1)
if len(parts) == 2:
if parts[0] not in self: raise KeyError(parts[0])
return self[parts[0]][parts[1]]
else:
if key not in self: raise KeyError(parts[0])
return super(tree, self).__getitem__(key)
def __contains__(self,key):
if key[0] == self.hsymbol : key = key[1:]
parts = key.split(self.hsymbol, 1)
if len(parts) == 2:
if not super(tree, self).__contains__(parts[0]): return False
return parts[1] in self[parts[0]]
else:
if not super(tree, self).__contains__(key): return False
return True
def __delitem__(self, key):
if key[0] == self.hsymbol : key = key[1:]
parts = key.split(self.hsymbol, 1)
if len(parts) == 2:
if parts[0] not in self: raise KeyError(parts[0])
self[parts[0]].__delitem__(parts[1])
else:
if key not in list(self): raise KeyError(parts[0])
super(tree,self).__delitem__(key)
def keys(self,parent=""):
#if parent is None: parent = self.hsymbol
names = []
for name in super(tree, self).keys():
if isinstance(self[name], tree):
names += self[name].keys(parent=parent+self.hsymbol+name)
else:
names.append(parent+self.hsymbol+name)
return names
So everything works quite well, although I'm not sure about keys function realization:
>>> t=tree()
>>> t['/user/Johnson/incoming'] = 2200
>>> t['/user/Johnson/family'] = 4
>>> t['/user/Johnson/play'] = False
>>> t['/user/Smith/incoming'] = 12000
>>> t['/user/Smith/family'] = 1
>>> t['/user/Smith/play'] = True
>>> t['user/Smith/incoming']
12000
>>> print t
{'user': {'Smith': {'play': True, 'incoming': 12000, 'family': 1}, 'Johnson': {'play': False, 'incoming': 2200, 'family': 4}}}
>>> print t.keys()
['/user/Smith/play', '/user/Smith/incoming', '/user/Smith/family', '/user/Johnson/play', '/user/Johnson/incoming', '/user/Johnson/family']
>>> t
{'user': {'Smith': {'play': True, 'incoming': 12000, 'family': 1}, 'Johnson': {'play': False, 'incoming': 2200, 'family': 4}}}
...but not an iteration through it:
>>> for k in t:
... print k
...
user
>>>
How can I get something like this?
/user/Smith/play
/user/Smith/incoming
/user/Smith/family
/user/Johnson/play
/user/Johnson/incoming
/user/Johnson/family
Pretty sure that it must be __iter__ and next attributes of tree class, but I haven't figured out how to write it yet.
I've searched over Stack Overflow with no luck:
python recursive iteration nested dictionaries
python class inherited from dictionary iteration through nested dictionaries
python iteration through nested dictionaries
Yes, you need __iter__ (an iterator will have a next() automatically).
Following your existing logic:
def __iter__(self, parent=""):
for name in super(tree, self).keys():
if isinstance(self[name], tree):
for item in self[name].__iter__(parent=parent+self.hsymbol+name):
yield item
else:
yield parent+self.hsymbol+name
Unlike your current keys() implementation, this only walks the tree on an as-needed basis: If a client only needs the first two keys, it only calls next() twice, and so the iterator only proceeds past two yields.
(I might suggest implementing keys as simply return list(iter(self)) -- that way you have the lazy approach available for those that want to avoid the inefficiency of unnecessarily walking a full tree, and the non-lazy approach otherwise).
I dont understand how changed type from list to dict on constructor in main class if i got to subclass another type - dict.
What is magic is this?
class Adder:
def __init__(self, data = [ ]):
self.data = data
def __add__(self, other):
return "Not Implemented"
class DictAdder(Adder):
def __add__(self, y):
z = {}
for k in self.data.keys(): z[k] = self.data[k]
for k in y.keys(): z[k] = y[k]
return z
y = DictAdder({1:'a', 2:'b'})
l = y + { 3: 'c', 4: 'd'}
print(l)
and answer:
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
Pycharm show what self.data.keys() dont have attribute keys() and this must be try, because data is a list, but this is work
data defaults to a list, but Python isn't a statically typed language so it doesn't have to be. data is just a name. Just because we have this:
class Adder:
def __init__(self, data = [ ]):
self.data = data
Doesn't limit our usage. I can still do:
i = Adder(4)
s = Adder('hello')
d = Adder({1: 2})
o = Adder(SomeOtherType())
As long as whatever uses Adder.data uses it correctly for the type it happens to be. Since in this case, DictAdder interprets data as a dict, and it is, that works fine. Of course, if you tried to use a DictAdder constructed with a non-dict, you would get an error.
Can you please help me, i am trying to sort the linked lists according to the documentation in the add function but i am getting an error which says:
f.add('b', 2)
File "", line 69, in add
AttributeError: 'NoneType' object has no attribute 'next'
how can i avoid this?
Thankyou.
class Frequency(object):
"""
Stores a letter:frequency pair.
>>> f = Frequency('c', 2)
>>> f.letter
'c'
>>> f.frequency
2
>>> f
{c: 2}
"""
def __init__(self, letter, frequency):
self.letter = letter
self.frequency = frequency
self.next = None
def __repr__(self):
return '{%s: %d}' % (self.letter, self.frequency)
class SortedFrequencyList(object):
"""
Stores a collection of Frequency objects as a sorted linked list.
Items are sorted from the highest frequency to the lowest.
"""
def __init__(self):
self.head = None
def add(self, letter, frequency):
"""
Adds the given `letter`:`frequency` combination as a Frequency object
to the list. If the given `letter` is already in the list, the given
`frequency` is added to its frequency.
>>> f = SortedFrequencyList()
>>> f.add('a', 3)
>>> f
({a: 3})
>>> f.add('b', 2)
>>> f
({a: 3}, {b: 2})
>>> f.add('c', 4)
>>> f
({c: 4}, {a: 3}, {b: 2})
>>> f.add('b', 3)
>>> f
({b: 5}, {c: 4}, {a: 3})
"""
current = self.head
found = False
if self.head is None:
self.head = Frequency(letter, frequency)
else:
prev = None
while current is not None:
if current.letter == letter:
current.frequency = current.frequency + frequency
found = True
prev = current
current = current.next
next1 = current.next
if next1 is None:
current = next1
if current.frequency < next1.frequency:
temp = current
current = next1
next1 = temp
else:
current = next1
next1 = current.next.next
if found is False:
prev.next = Frequency(letter, frequency)
In the lines
current = current.next
next1 = current.next
what happens if current.next == None?
I don't know if you are doing this as a Python exercise or because you actually need the functionality; if the latter, there is already a built-in class that does this for you. It's collections.Counter (in Python 2.7 or 3.x); if you're using an earlier version then you can make one yourself by subclassing collections.defaultdict. It also uses Python dictionaries instead of storing data as key-value pairs.
Example:
>>> from collections import Counter
>>> x = Counter()
>>> x['a'] += 2
>>> x['b'] += 3
>>> x['c'] += 1
>>> x
Counter({'b': 3, 'a': 2, 'c': 1})
You can recover the sorted key-value pair representation of your data with
x.most_common()