2010-01-21 3 views
1

У меня есть этот код:Очистка вложенным для петель питона

def GetSteamAccts(): #Get list of steam logins on this computer. 
    templist = [] 
    Steamapp_Folders = ["C:\\Program Files (x86)\\Steam\\steamapps\\", "C:\\Program Files\\Steam\\steamapps\\"] #Check both of these directories. 
    for SF_i in range(len(Steamapp_Folders)): 
     if os.path.exists(Steamapp_Folders[SF_i]): #If the directory even exists... 
      Steam_AppDir_Items = os.listdir(Steamapp_Folders[SF_i]) #List items under steam install directory. 
      for S_AD_i in range(len(Steam_AppDir_Items)): #Make sure the user doesn't have any files in here... 
       if os.path.isdir(Steamapp_Folders + Steam_AppDir_Items[S_AD_i]): #If our path is a directory... 
        templist.append(Steam_AppDir_Items[S_AD_i]) #Add it to our list of logins. 
                   #(If some idiot puts extra folders in here, 
                   #it's their own damn fault when it shows on the list.) 
    return templist #Return a (not so) properly filtered list of steam logins. 

Моя проблема, это выглядит некрасиво УЖАСНО мне. Я составил список из двух путей (только один из них будет когда-либо существовать), перейдя по этим путям, затем мне нужно получить список элементов в этих путях, а затем пройти их и отфильтровать из него не каталоги, чтобы получить псевдо-список паровых логинов на компьютере пользователя. (В основном просто получить список любых существующих каталогов (только каталогов!) По любому из этих двух путей)

Есть ли более короткий способ сделать это (кроме конденсации для петель в одну строку?)?

Я бы предпочел дать англоязычное решение, чтобы я мог собрать его вместе; а не кода. Это единственный способ, которым я действительно научусь правильно. Даже приятный маленький намек или выдержка, чтобы я мог понять это сам по себе, было бы неплохо.

И: Есть ли списки в течение петли всегда должны быть пройдена как:

for x in range(len(somelist)): 

или есть что-то короче, чем при использовании диапазона (Len (

+1

Почему вы не используете определение функций, чтобы упростить это? –

+0

Возможно, именно поэтому я задал вопросы, так как я начинаю ... – ThantiK

ответ

9
for i in range(len(somelist)): 
    something(somelist[i]) 

должен быть записан как

?
for x in somelist: 
    something(x) 

Также вы можете написать все гораздо короче:

def GetSteamAccts(): 
    Steamapp_Folders = [f for f in ("C:\\Program Files (x86)\\Steam\\steamapps\\", 
            "C:\\Program Files\\Steam\\steamapps\\") 
          if os.path.isdir(f)] 
    return [os.path.join(root, folder) 
        for root in Steamapp_Folders 
        for folder in os.listdir(root) 
        if os.path.isdir(os.path.join(root, folder)) ] 

Это выглядит чище, и на самом деле делает то, что вы хотите: ;-)

def subfoldernames(root): 
    for folder in os.listdir(root): 
     path = os.path.join(root, folder) 
     if os.path.isdir(path): 
      yield folder # just the name, not the path 

# same, just shorter: 
def subfoldernames(root): 
    # this returns a generator, written as a generator expression 
    return (folder for folder in os.listdir(root) 
        if os.path.isdir(os.path.join(root, folder))) 

def GetSteamAccts(): 
     Steamapp_Folders = ("C:\\Program Files (x86)\\Steam\\steamapps\\", 
              "C:\\Program Files\\Steam\\steamapps\\") 
     for folder in Steamapp_Folders: 
      if os.path.isdir(folder): 
       # only the subfolders of the first path that exists are returned 
       return list(subfoldernames(folder)) 
+1

Хотя это использует длительное понимание списка (два цикла и условие), обратите внимание, что при правильных отступов отступов/строк он все еще доступен для чтения. «Конденсация для петель в одиночные линии» не означает, что она находится на одной линии, или плотная и уродливая! – Ipsquiggle

+1

независимо от того, сколько линий вы его распространите, оно останется плотным, уродливым и нечитаемым, тем не менее. – SilentGhost

+0

Спасибо THC; это изящно и лаконично, что я понимаю, что происходит (за исключением того, что мне нужно больше смотреть на «f for f in»), но, по крайней мере, я понимаю, что он делает. Это в основном лишает список путей, которые не существуют, прежде чем делать следующий раздел кода. Еще раз спасибо, я буду играть с этим;) – ThantiK

5

И: Есть ли списки в течение петли всегда быть пройден, как:

для й в диапазон (len (somelist)): или там что-то короче, чем использование диапазон (len (?

Конечно, есть, если вы хотите получить доступ только деталь и вы не заинтересованы в его индексе вы могли бы сделать это:

for x in somelist: 

Если вы хотите, чтобы индекс, а вы могли бы сделать это:

for index, x in enumerate(somelist): 
4

Вы должны потерять представление о том, что цикл for всегда выполняет итерации по номерам от нуля до чего-то, как на других языках. Вы просто обход списков, так что используйте цикл, как это:

def GetSteamAccts(): 
    templist = [] 
    Steamapp_Folders = ["C:\\Program Files (x86)\\Steam\\steamapps\\", "C:\\Program Files\\Steam\\steamapps\\"] #Check both of these directories. 
    for steamapp_folder in Steamapp_Folders: 
     if os.path.exists(steamapp_folder): 
      for steam_appDir_item in os.listdir(steamapp_folder): 
       if os.path.isdir(os.path.join(steamapp_folder, steam_appDir_item)): 
        templist.append(steam_appDir_item) 
    return templist 

В Python, для цикла переходит все, что может быть итерированным. Для тех немногих раз, когда вам действительно нужны номера (и только цифры), есть range.В те времена, когда вам нужны номер и элементы, используйте:

for number, item in enumerate(my_list): 

При комбинировании for с и if с, вы должны также взглянуть на выражениях генератора и списковых (см docs).

+0

Спасибо. К сожалению, я работал с такими, как ... VB4 назад, когда я был молодым подростком, а затем неожиданно перестал программировать. Много очень запутанных штучек держится со мной, и я стараюсь многое отучить, чтобы облегчить делать вещи более гладкими. – ThantiK

+0

@ThantiK: Переполнение стека - это именно то место для этого :-) И, что касается изучения Python, вы будете ценить многие вещи, которые Py.thon делает для облегчения вашей жизни, чем VB4 – balpha

+1

Программа на Python достаточно долгое время будет другим способом. Когда вы работаете на каком-то другом языке, чтобы настроить целочисленную переменную, чтобы подсчитать, сколько раз вы прошли через цикл, будет казаться огромная боль. –

0

Я хотел бы предложить что-то вроде этого:

def check_subfolder(*args): 
    for folder in args: 
     for root, dirs, _ in os.walk(folder): 
       return [os.path.join(root, i) for i in dirs] # since only 1 will ever exist 

это просто экономит на все эти if заявления. Конечно, первый цикл for может быть удален из функции, потому что это не является существенным для логики кода.

Редактировать: обновлено, чтобы возвращать поддиры первого существующего каталога, в соответствии с вопросом.

2

Как уже упоминалось, удаление предположения о целых индексах устраняет значительную сложность.

Идти дальше, вы можете заменить шаблоны, в которых вы создаете список, добавив в цикл for с list comprehension. Сколько (и нужно ли) они улучшают читаемость спорна, как только вы получите в нескольких слоев вложенности, но они делают код более кратким:

def GetSteamAccts(): 
    Steamapp_Folders = ["C:\\Program Files (x86)\\Steam\\steamapps\\", "C:\\Program Files\\Steam\\steamapps\\"] #Check both of these directories. 
    return [ item for folder in Steamapp_Folders if os.path.exists(folder) 
        for item in os.listdir(folder) if os.path.isdir(os.path.join(folder, item)) ] 
Смежные вопросы