Python path coding

I just spent the last semester on Uni learning python. I really enjoyed it, and I was hoping for some tips on how to write more "pythonic" code.

This is the __init__ class from a recent assignment that I did. At the time I wrote this, I was trying to figure out how I could rewrite this using lambda, or in a more accurate, more efficient way, but I did not have enough time.

 def __init__(self, dir): def _read_files(_, dir, files): for file in files: if file == "classes.txt": class_list = readtable(dir+"/"+file) for item in class_list: Enrol.class_info_dict[item[0]] = item[1:] if item[1] in Enrol.classes_dict: Enrol.classes_dict[item[1]].append(item[0]) else: Enrol.classes_dict[item[1]] = [item[0]] elif file == "subjects.txt": subject_list = readtable(dir+"/"+file) for item in subject_list: Enrol.subjects_dict[item[0]] = item[1] elif file == "venues.txt": venue_list = readtable(dir+"/"+file) for item in venue_list: Enrol.venues_dict[item[0]] = item[1:] elif file.endswith('.roll'): roll_list = readlines(dir+"/"+file) file = os.path.splitext(file)[0] Enrol.class_roll_dict[file] = roll_list for item in roll_list: if item in Enrol.enrolled_dict: Enrol.enrolled_dict[item].append(file) else: Enrol.enrolled_dict[item] = [file] try: os.path.walk(dir, _read_files, None) except: print "There was a problem reading the directory" 

As you can see, this is a little cumbersome. If anyone has the time or inclination, I would really appreciate some tips on python best practices.

Thanks.

+6
python
source share
3 answers

A couple of things that can clear up your code a bit:

Use the setdefault dictionary. If the key is missing, then it sets it by default, which you provide to it, and then returns it. Otherwise, it simply ignores the second parameter and returns what was in the dictionary. This avoids clumsy if-statements.

 Enrol.venues_dict.setdefault(key, []).append(file) >>> x = {} >>> x.setdefault(99, []).append(5) >>> x.setdefault(99, []).append(6) >>> x {99: [5, 6]} >>> x.setdefault(100, []).append(1) >>> x {99: [5, 6], 100: [1]} 

Another possibility is to use os.path.join to create file paths. This is safer than just concatenating strings.

 os.path.join(dir, file) 

Other than that, it looks good in terms of style, IMO.

+5
source share

In addition to the orangeoctopus suggestions for using setdefault you can reorganize if-else into a dispatcher (a typical replacement for large if-else and switch statements):

 # list of 2-tuples: (bool func(string filename), handler_function) handlers = [ ((lambda fn: fn == "classes.txt"), HandleClasses), ((lambda fn: fn == "subjects.txt"), HandleSubjects), ((lambda fn: fn.endswith(".roll")), HandleRoll) ] 

then do

 for filename in files: for matcher, handler in handlers: if matcher(filename): handler(filename) break 
+3
source share

Another important point if you want to use your script for a long time (some people say for a very long time) is not to use outdated functions in the new code:

os.path.walk disapeared in python 3.x. Now you can use os.walk . However, os.walk is different from os.path.walk : it does not accept the processing function in its signature. Therefore, refactoring your code will mean a little more than changing names.

+2
source share

All Articles