In Python, to find all attributes, there is:
dir(object)
object.__dict__.keys()
But what i want is to list what is in the second branch, not only the first branch, it's kind of a recursive operation?
How to do that?
it's like
dir(dir(x) for x in dir(math))
tried this and still get the same result duplicated:
>>> for i in dir(math):
... for j in i:
... print dir(j)
and all results are the methods of str
Update: it seems that the dir() commande returns a list of str, here is a simple hack; I tried to exclude the reserved names to see if i go further, but the result was only str
[i for i in dir(math) if i[0]!="_"]
[type(i) for i in dir(math) if i[0]!="_"]
Thank you again :)
object.__dict__.keys() # Just keys
object.__dict__.values() # Just values
object.__dict__.items() # Key-value pairs
Edit wait! I think I misunderstood. You want to list an object's properties, and those properties' properties and so on and so forth? Try something like this:
def discover(object):
for key in dir(object):
value = getattr(object, key)
print key, value
discover(value)
It's pretty crude, but that's the recursion I think you're looking for. Note that you will have to stop it manually at some point. There's no turtles at the bottom, it goes on and on.
Related
I currently have a dictionary that looks like this:
{OctetString('Ethernet8/6'): Integer(1),
OctetString('Ethernet8/7'): Integer(2),
OctetString('Ethernet8/8'): Integer(2),
OctetString('Ethernet8/9'): Integer(1),
OctetString('Vlan1'): Integer(2),
OctetString('Vlan10'): Integer(1),
OctetString('Vlan15'): Integer(1),
OctetString('loopback0'): Integer(1),
OctetString('mgmt0'): Integer(1),
OctetString('port-channel1'): Integer(1),
OctetString('port-channel10'): Integer(1),
OctetString('port-channel101'): Integer(1),
OctetString('port-channel102'): Integer(1)}
I want my dictionary to look like this:
{OctetString('Ethernet8/6'): Integer(1),
OctetString('Ethernet8/7'): Integer(2),
OctetString('Ethernet8/8'): Integer(2),
OctetString('Ethernet8/9'): Integer(1)}
I am not sure what is the best way to find these key, value pairs. I really want anything that matches '\Ethernet(\d*)/(\d*)'. However I am not sure the best way to go about this. My main goal is to match all the Ethernet Values and then count them. For example: After I have the dict matching all of Ethernetx/x I want to count the amount of 1's and 2's.
Also, why do I get only Ethernet8/6 when I iterate the dictionary and print, but when I pprint the dictionary I end up with OctetString('Ethernet8/6')?
for k in snmp_comb: print k
Ethernet2/18
Ethernet2/31
Ethernet2/30
Ethernet2/32
Ethernet8/46
This should do it:
new_dict = dict()
for key, value in orig_dict.items():
if 'Ethernet' in str(key):
new_dict[key] = value
When you use print, python calls the __str__ method on the OctetString object, which returns Ethernet8/6. However, I think pprint defaults to printing the object type.
EDIT:
Stefan Pochmann has rightly pointed out below that if 'Ethernet' in will match any string which contains the word Ethernet. The OP did mention using regex in his post to match Ethernet(\d*)/(\d*), so this answer may not be suitable to anyone else looking to solve a similar problem.
(I'll use the same 'Ethernet' in str(key) test as the accepted answer.)
If you want to keep the original dict and have the filtered version as a separate dictionary, I'd use a comprehension:
newdict = {key: value
for key, value in mydict.items()
if 'Ethernet' in str(key)}
If you don't want to keep the original dict, you can also just remove the entries you don't want:
for key in list(mydict):
if 'Ethernet' in str(key):
del mydict[key]
The reason you get "OctetString('...')" is the same as this one:
>>> 'foo'
'foo'
>>> pprint.pprint('foo')
'foo'
>>> print('foo')
foo
The first two tests show you a representation you can use in source code, that's why there are quotes. It's what the repr function gets you. The third test prints the value for normal pleasure, so doesn't add quotes. The "OctetString('...')" is simply such a representation as well, and you can copy&paste it into source code and get actual OctetString objects again, rather than Python string objects. I guess pprint is mostly intended for developing, where it's more useful to get the full repr version.
I am practically repeating the same code with only one minor change in each function, but an essential change.
I have about 4 functions that look similar to this:
def list_expenses(self):
explist = [(key,item.amount) for key, item in self.expensedict.iteritems()] #create a list from the dictionary, making a tuple of dictkey and object values
sortedlist = reversed(sorted(explist, key = lambda (k,a): (a))) #sort the list based on the value of the amount in the tuples of sorted list. Reverse to get high to low
for ka in sortedlist:
k, a = ka
print k , a
def list_income(self):
inclist = [(key,item.amount) for key, item in self.incomedict.iteritems()] #create a list from the dictionary, making a tuple of dictkey and object values
sortedlist = reversed(sorted(inclist, key = lambda (k,a): (a))) #sort the list based on the value of the amount in the tuples of sorted list. Reverse to get high to low
for ka in sortedlist:
k, a = ka
print k , a
I believe this is what they refer to as violating "DRY", however I don't have any idea how I can change this to be more DRYlike, as I have two seperate dictionaries(expensedict and incomedict) that I need to work with.
I did some google searching and found something called decorators, and I have a very basic understanding of how they work, but no clue how I would apply it to this.
So my request/question:
Is this a candidate for a decorator, and if a decorator is
necessary, could I get hint as to what the decorator should do?
Pseudocode is fine. I don't mind struggling. I just need something
to start with.
What do you think about using a separate function (as a private method) for list processing? For example, you may do the following:
def __list_processing(self, list):
#do the generic processing of your lists
def list_expenses(self):
#invoke __list_processing with self.expensedict as a parameter
def list_income(self):
#invoke __list_processing with self.incomedict as a parameter
It looks better since all the complicated processing is in a single place, list_expenses and list_income etc are the corresponding wrapper functions.
I was just wondering if there is a simple way to do this. I have a particular structure that is parsed from a file and the output is a list of a dict of a list of a dict. Currently, I just have a bit of code that looks something like this:
for i in xrange(len(data)):
for j, k in data[i].iteritems():
for l in xrange(len(data[i]['data'])):
for m, n in data[i]['data'][l].iteritems():
dostuff()
I just wanted to know if there was a function that would traverse a structure and internally figure out whether each entry was a list or a dict and if it is a dict, traverse into that dict and so on. I've only been using Python for about a month or so, so I am by no means an expert or even an intermediate user of the language. Thanks in advance for the answers.
EDIT: Even if it's possible to simplify my code at all, it would help.
You never need to iterate through xrange(len(data)). You iterate either through data (for a list) or data.items() (or values()) (for a dict).
Your code should look like this:
for elem in data:
for val in elem.itervalues():
for item in val['data']:
which is quite a bit shorter.
Will, if you're looking to decend an arbitrary structure of array/hash thingies then you can create a function to do that based on the type() function.
def traverse_it(it):
if (isinstance(it, list)):
for item in it:
traverse_it(item)
elif (isinstance(it, dict)):
for key in it.keys():
traverse_it(it[key])
else:
do_something_with_real_value(it)
Note that the average object oriented guru will tell you not to do this, and instead create a class tree where one is based on an array, another on a dict and then have a single function to process each with the same function name (ie, a virtual function) and to call that within each class function. IE, if/else trees based on types are "bad". Functions that can be called on an object to deal with its contents in its own way "good".
I think this is what you're trying to do. There is no need to use xrange() to pull out the index from the list since for iterates over each value of the list. In my example below d1 is therefore a reference to the current data[i].
for d1 in data: # iterate over outer list, d1 is a dictionary
for x in d1: # iterate over keys in d1 (the x var is unused)
for d2 in d1['data']: # iterate over the list
# iterate over (key,value) pairs in inner most dict
for k,v in d2.iteritems():
dostuff()
You're also using the name l twice (intentionally or not), but beware of how the scoping works.
well, question is quite old. however, out of my curiosity, I would like to respond to your question for much better answer which I just tried.
Suppose, dictionary looks like: dict1 = { 'a':5,'b': [1,2,{'a':100,'b':100}], 'dict 2' : {'a':3,'b':5}}
Solution:
dict1 = { 'a':5,'b': [1,2,{'a':100,'b':100}], 'dict 2' : {'a':3,'b':5}}
def recurse(dict):
if type(dict) == type({}):
for key in dict:
recurse(dict[key])
elif type(dict) == type([]):
for element in dict:
if type(element) == type({}):
recurse(element)
else:
print element
else:
print dict
recurse(dict1)
It's my first Python program and my first excercise is that I just need to swap places in a tuple:
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
Is the tuple, and I need to swap Frans with Eefje (those are just names) and then swap the second tuple.
I read the whole data structure tutorial off Python and I thought I could do this like this:
#!/path/to/python
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
def switchplace(x):
stamboom[x], stamboom[x + 1] = stamboom[x + 1], stamboom[x]
return stamboom
map(switchplace, range(0, len(stamboom)))
It doens't give syntax errors but it doesn't show anything.
To show something you have to print it.
Change the last line to:
print map(switchplace,range(0,len(stamboom)))
That was very complicated code for a simple task. Check out something called list comprehension.
Change the code to:
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
stamboom = [(item[1], item[0]) for item in stamboom]
print stamboom
Update
I saw your solution in the comment. I don't know if there are more premisses to the excersise that I'm not aware of. But I would probably do this instead:
def switchplace(x):
return x[1], x[0]
stamboom = [("Frans","Eefje"),("Klaar","Eefje"),("Eefje","Mattho"), ("Eefje","Salammbo"),("Gustave","Mattho"),("Gustave","Salammbo")]
print map(switchplace, stamboom)
The iterable argument to map don't have to be a numeric range. It could be the list itself. But maybe I missed something and you already got it :)
Tuples are immutable in Python:
http://docs.python.org/reference/datamodel.html
I have a dict that has string-type keys whose exact values I can't know (because they're generated dynamically elsewhere). However, I know that that the key I want contains a particular substring, and that a single key with this substring is definitely in the dict.
What's the best, or "most pythonic" way to retrieve the value for this key?
I thought of two strategies, but both irk me:
for k,v in some_dict.items():
if 'substring' in k:
value = v
break
-- OR --
value = [v for (k,v) in some_dict.items() if 'substring' in k][0]
The first method is bulky and somewhat ugly, while the second is cleaner, but the extra step of indexing into the list comprehension (the [0]) irks me. Is there a better way to express the second version, or a more concise way to write the first?
There is an option to write the second version with the performance attributes of the first one.
Use a generator expression instead of list comprehension:
value = next(v for (k,v) in some_dict.iteritems() if 'substring' in k)
The expression inside the parenthesis will return an iterator which you will then ask to provide the next, i.e. first element. No further elements are processed.
How about this:
value = (v for (k,v) in some_dict.iteritems() if 'substring' in k).next()
It will stop immediately when it finds the first match.
But it still has O(n) complexity, where n is the number of key-value pairs. You need something like a suffix list or a suffix tree to speed up searching.
If there are many keys but the string is easy to reconstruct from the substring, then it can be faster reconstructing it. e.g. often you know the start of the key but not the datestamp that has been appended on. (so you may only have to try 365 dates rather than iterate through millions of keys for example).
It's unlikely to be the case but I thought I would suggest it anyway.
e.g.
>>> names={'bob_k':32,'james_r':443,'sarah_p':12}
>>> firstname='james' #you know the substring james because you have a list of firstnames
>>> for c in "abcdefghijklmnopqrstuvwxyz":
... name="%s_%s"%(firstname,c)
... if name in names:
... print name
...
james_r
class MyDict(dict):
def __init__(self, *kwargs):
dict.__init__(self, *kwargs)
def __getitem__(self,x):
return next(v for (k,v) in self.iteritems() if x in k)
# Defining several dicos ----------------------------------------------------
some_dict = {'abc4589':4578,'abc7812':798,'kjuy45763':1002}
another_dict = {'boumboum14':'WSZE x478',
'tagada4783':'ocean11',
'maracuna102455':None}
still_another = {12:'jfg',45:'klsjgf'}
# Selecting the dicos whose __getitem__ method will be changed -------------
name,obj = None,None
selected_dicos = [ (name,obj) for (name,obj) in globals().iteritems()
if type(obj)==dict
and all(type(x)==str for x in obj.iterkeys())]
print 'names of selected_dicos ==',[ name for (name,obj) in selected_dicos]
# Transforming the selected dicos in instances of class MyDict -----------
for k,v in selected_dicos:
globals()[k] = MyDict(v)
# Exemple of getting a value ---------------------------------------------
print "some_dict['7812'] ==",some_dict['7812']
result
names of selected_dicos == ['another_dict', 'some_dict']
some_dict['7812'] == 798
I prefer the first version, although I'd use some_dict.iteritems() (if you're on Python 2) because then you don't have to build an entire list of all the items beforehand. Instead you iterate through the dict and break as soon as you're done.
On Python 3, some_dict.items(2) already results in a dictionary view, so that's already a suitable iterator.