Checking for change in dictionaries - python

I am using python 3.6, In the program I am writing is comparing a set of dictionaries for any difference. if found it updates a reference dictionary and clears the data.
On first start up it works and registers the first change but everyone after that it does not, and just displays the information but does not identify that it has changed. It acts as Πython is linking the two dictionaries together. Is there anything else Ι can do?
def Check_Data():
global Ref_Readings
print('Ref_Readings')
print(Ref_Readings)
print('Data')
print(Data)
a=Ref_Readings
b=Data
if (a != b):
print('**************Updated Data')
del Ref_Readings[:]
Ref_Readings = Data
#print(Ref_Readings)#
Store_Readings()
else:
print('checking Settings')
del Data[:]
print(Data)

Ref_Readings = Data => a = b
Python uses references. If you want to have two different dictionaries you must do a copy.
import copy
Ref_Readings = copy.deepcopy(Data)

list_a = list_b makes "memory pointer match". You have to use copy library.
Add to begin:
import copy from copy
Change:
Ref_Readings = copy(Data)
you can also remove
a=Ref_Readings
b=Data
and change:
if (Data != Ref_readings):

Related

How to reset value of multiple dictionaries elegantly in python

I am working on a code which pulls data from database and based on the different type of tables , store the data in dictionary for further usage.
This code handles around 20-30 different table so there are 20-30 dictionaries and few lists which I have defined as class variables for further usage in code.
for example.
class ImplVars(object):
#dictionary capturing data from Asset-Feed table
general_feed_dict = {}
ports_feed_dict = {}
vulns_feed_dict = {}
app_list = []
...
I want to clear these dictionaries before I add data in it.
Easiest or common way is to use clear() function but this code is repeatable as I will have to write for each dict.
Another option I am exploring is with using dir() function but its returning variable names as string.
Is there any elegant method which will allow me to fetch all these class variables and clear them ?
You can use introspection as you suggest:
for d in filter(dict.__instancecheck__, ImplVars.__dict__.values()):
d.clear()
Or less cryptic, covering lists and dicts:
for obj in ImplVars.__dict__.values():
if isinstance(obj, (list, dict)):
obj.clear()
But I would recommend you choose a bit of a different data structure so you can be more explicit:
class ImplVars(object):
data_dicts = {
"general_feed_dict": {},
"ports_feed_dict": {},
"vulns_feed_dict": {},
}
Now you can explicitly loop over ImplVars.data_dicts.values and still have other class variables that you may not want to clear.
code:
a_dict = {1:2}
b_dict = {2:4}
c_list = [3,6]
vars_copy = vars().copy()
for variable, value in vars_copy.items():
if variable.endswith("_dict"):
vars()[variable] = {}
elif variable.endswith("_list"):
vars()[variable] = []
print(a_dict)
print(b_dict)
print(c_list)
result:
{}
{}
[]
Maybe one of the easier kinds of implementation would be to create a list of dictionaries and lists you want to clear and later make the loop clear them all.
d = [general_feed_dict, ports_feed_dict, vulns_feed_dict, app_list]
for element in d:
element.clear()
You could also use list comprehension for that.

Python list being appended when not (directly) referenced

Okay so this is just a rough bit of code I made when trying to make a Guess Who(TM) for class challenge and I wanted to make a random character generator function (its only a proof of concept and I would expand it complexity later! Please don't judge!). However the character's template feature list seems to be appended every iteration (and so skewing my other loops) when it aught not to. It should be adding an item to the end of each new generated list - not the template. Yet the template variable is not appended to in the code, only a temporary copy is/should be. Here's the code:
tempfeatures = characters = []
for i in range(len(characternames)):
tempfeatures = []
charactername = characternames[random.randint(0,len(characternames)-1)]
characternames.remove(charactername)
a = features
tempfeatures = a
### "Debug bit" ###
print(features)
print("loooooop")
for y in range(len(features)):
print(len(features))
temp = random.randint(0,1)
if temp == 1:
tempfeatures[y][1] = True
else:
tempfeatures[y][1] = False
tempfeatures.append(["Dead",True])
characters.append([charactername,tempfeatures])
print(characters)
Thank you!
Apparently the tempfeature variable is "call by reference" and not "call by value". - thanks python.
So when duplicating lists, one must use this on the end of the variable name
tempfeature = feature[:]
(the [:] bit)
Thanks all for your comments!
This is called a shallow copy, it just referenciates the list to another variable, as seen here:
https://docs.python.org/2/library/copy.html
You need to make and intependent copy, or a deep copy, as: tempfeature = list(feature) so changing tempfeature won't interfere with feature

It's possibile to use set function on a object basing only one attribute?

I'm creating this type of object:
class start_url_mod ():
link = ""
id = 0
data = ""
I'm creating a list of this object and I want to know if there is some way in order to delete one of then if I find same link attribute.
I know the function set() for the deleting of duplicates in a "sample" list, but there is something very fast and computational acceptable?
Use a dict key-ed on the attribute. You can preserve order with collections.OrderedDict:
from collections import OrderedDict
# Keep the last copy with a given link
kept_last = OrderedDict((x.link, x) for x in nonuniquelist).values()
# Keep the first copy with a given link (still preserving input order)
kept_first = list(reversed(OrderedDict((x.link, x) for x in reversed(nonuniquelist)).viewvalues()))
If order is not important, plain dict via dict comprehensions is significantly faster in Python 2.7 (because OrderedDict is implemented in Python, not C, and because dict comprehensions are optimized more than constructor calls; in Python 3.5 it's implemented in C):
# Keep the last copy with a given link but order not preserved in result
kept_last = {x.link: x for x in nonuniquelist}.values()
# Keep the first copy with a given link but order not preserved in result
kept_first = {x.link: x for x in reversed(nonuniquelist)}.values()
You can use a dictionary with the attribute that you're interested in being the key ...

Pass large data structure in Python

In C++, it's good practice to pass references to large data structures to avoid the overhead of copying the whole thing by value. Python works very differently, though, and I'm wondering how best to pass a large data structure.
Here's the simple version. Is this what I should use, or is there something better?
foo(hugeArray):
# Change values in hugeArray
return hugeArray
hugeArray = foo(hugeArray)
Solution (Kudos to jonrsharpe!)
foo(hugeArray)
hugeArray[0] = "New!"
myArray[0] = "Old."
foo(myArray)
print myArray[0] # Prints "New!"
The function changes the original array, so there's no need to assign the return value to the original to change it.
No need to copy stuff
def foo(array):
array[0] = 3 # do stuff to the array in place
huge_array = [1, 2, 3]
foo(huge_array) # returns None
print(huge_array) # [3, 2, 3]
Python will do this for you, unless you explicitly copy it or modify.
foo(hugeArray):
# Change values in hugeArray
return hugeArray
hugeArray2 = foo(hugeArray)
print("Was Python Clever? - ", hugeArray2 is hugeArray)
Note that if you want to re-assign hugeArray without making a copy, you can use slicing. so
hugeArray[:] = hugeNewArray
Instead of
hugeArray = hugeNewArray

Cloned list being altered when the original list is being altered

Here is the code:
def Class(clas12):
inputData = ''.join(clas12.readlines())
line=inputData.split('\n')
line2=[]
for a in line:
b=a.split(' ')
line2.append(b)
return line2
clas12=open('class12.txt','r')
Class12=Class(clas12)
Class13=list(Class12)
When I alter Class12( such by .remove, .append), the same change will be applied to Class13. This is frustrating because I need the original list for another function. Is there a way to keep the original list or copy it so that it won't be altered?
By default python uses references rather than copies, it is faster an more memory efficient that way - if you need a copy that you can alter without changing the original:
import copy
def Class(clas12):
inputData = ''.join(clas12.readlines())
line=inputData.split('\n')
line2=[]
for a in line:
b=a.split(' ')
line2.append(b)
return line2
clas12=open('class12.txt','r')
Class12=Class(clas12)
Class13=copy.deepcopy(Class12)

Categories