2016-04-14 2 views
2

Я не уверен, были ли заданы эти вопросы - пока не удалось найти хорошую практику.Лучшая питоническая практика, чтобы избежать повторения кода?

У меня есть два файла python с таким же импортом пакетов и рядом различных методов. Пара переменных меняется только, а другие одинаковы.

ЕСЛИ мне нужно внести изменения в один файл, я должен перейти к другому, чтобы применить те же изменения, которые не кажутся надежными.

Я действительно хочу сохранить эти файлы отдельно (в двух файлах). Я никогда не разбирался в идее class. Должен ли я сделать class в первом файле, имеющем все методы, циклы, переменные и вызывать его во втором, я могу затем переписать переменные, если это необходимо?

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

import csv 
import datetime 
import pylab 
import sys 
import time 
from inspect import getsourcefile 
from os.path import abspath 

import matplotlib.dates as mdates 
import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib import style 
from matplotlib.backends.backend_pdf import PdfPages 


def get_mul_list(*args): 
    return map(list, zip(*args)) 


def str2float(s): 
    if not s == '': 
     s = (float(s)) 
    else: 
     s = np.nan 
    return s 


def clean_nans(x, y, num_nan_gap=24): 
    x_clean, y_clean = [], [] 
    cnt = 0 
    for _x, _y in zip(x, y): 
     if np.isnan(_y): 
      cnt += 1 
      if cnt == num_nan_gap: 
       # on the 5th nan, put it in the list to break line 
       x_clean.append(_x) 
       y_clean.append(_y) 
      continue 
     cnt = 0 
     x_clean.append(_x) 
     y_clean.append(_y) 
    return x_clean, y_clean 


def csv_store_in_dict(filepath, mode): 
    csv_data = open(filepath, mode) 
    data = list(csv.reader(csv_data)) 
    csv_imported_in_dict = dict(zip(data[0], get_mul_list(*data[1:]))) 
    return csv_imported_in_dict 

colors_list = ['deeppink', 'aquamarine', 'yellowgreen', 'orangered', 'darkviolet', 
      'darkolivegreen', 'lightskyblue', 'teal', 'seagreen', 'olivedrab', 'red', 'indigo', 'goldenrod', 'firebrick', 
      'slategray', 'cornflowerblue', 'darksalmon', 'blue', 'khaki', 'wheat', 'dodgerblue', 'moccasin', 'sienna', 
      'darkcyan'] 

current_py_filepath = abspath(getsourcefile(lambda: 0)) # python source file path for figure footnote 

kkk_dict = csv_store_in_dict('CSV/qry_WatLvl_kkk_xlsTS_1c_v4.csv', 'r') # all WL kkk data stored in a dictionary 
yyyddd_dict = csv_store_in_dict('CSV/qry_WatLvl_TimeSeries2_v2.csv', 'r') # all WL kkk data stored in a dictionary 
XX_info_dict = csv_store_in_dict('CSV/XX_info.csv', 'r') # XX_name, XX_group_name, BB_Main, CC, dddd 

XX_groups_chartE = ('XXH_05', 
        'XXH_16', 
        'XXH_11', 
        'DXX_27', 
        'DXX_22', 
        'DXX_21', 
        'DXX_09', 
        'DXX_07', 
        'DXX_01', 
        'DXX_05',) 

y_range = [[5,10], # chart 1 
      [7,12], # chart 2 
      [3,8], # chart 3 
      [7,12], # chart 4 
      [5,10], # chart 5 
      [20,50], # chart 6 
      [12,22], # chart 7 
      [5,25], # chart 8 
      [10,15], # chart 9 
      [22,42]] # chart 10 

# Date conversion 
x_kkk_date = [] 
x_yyy_date = [] 
x_kkk = kkk_dict["DateTime"] 
x_yyyddd = yyyddd_dict["DateTime"] 
for i in x_kkk: 
    x_kkk_date.append(datetime.datetime.strptime(i, "%d/%m/%Y %H:%M:%S")) 
for i in x_yyyddd: 
    x_yyy_date.append(datetime.datetime.strptime(i, "%d/%m/%Y %H:%M:%S")) 

# plotting XX groups 
XXs_curr_grp = [] 
chart_num = 1 
for XX_gr_nam in XX_groups_chartE: 
    for count, elem in enumerate(XX_info_dict['XX_group_name']): 
     if elem == XX_gr_nam: 
      XXs_curr_grp.append(XX_info_dict['XX_name'][count]) 

    fig = plt.figure(figsize=(14, 11)) 

    col_ind = 0 

    for XX_v in XXs_curr_grp: 
     y_kkk = kkk_dict[XX_v] 
     y_yyyddd = yyyddd_dict[XX_v] 

     y_kkk_num = [str2float(i) for i in y_kkk] 
     y_yyyddd_num = [str2float(i) for i in y_yyyddd] 

     ind_XX = XX_info_dict["XX_name"].index(XX_v) 
     BB_Main = XX_info_dict["BB_Main"][ind_XX] 
     CC = XX_info_dict["CC"][ind_XX] 
     dddd = XX_info_dict["dddd"][ind_XX] 

     def label_pl(d_type): 
      label_dis = "%s (%s, %s/%s)" % (XX_v, BB_Main, CC, d_type) 
      return label_dis 

     x_kkk_date_nan_cln, y_kkk_num_nan_cln = clean_nans(x_kkk_date, y_kkk_num, 200) 

     plt.plot_date(x_kkk_date_nan_cln, y_kkk_num_nan_cln, '-', markeredgewidth=0, 
         label=label_pl("kkk data"), color=colors_list[col_ind]) # c = col_rand 

     plt.scatter(x_yyy_date, y_yyyddd_num, label=label_pl("yyy ddds"), marker='x', linewidths=2, 
        s=50, color=colors_list[col_ind]) 
     col_ind += 1 


    XX_grp_title = XX_gr_nam.replace("_", "-") 
    plt.title("kkk Levels \n" + XX_grp_title + " Group", fontsize=20) 
    plt.ylabel('wwL (mmm)') 
    plt.legend(loc=9, ncol=2, prop={'size': 8}) 
    plt.figtext(0.05, 0.05, current_py_filepath, horizontalalignment='left', fontsize=8) # footnote for file path 
    plt.figtext(0.95, 0.05, 'Chart E%s' % (chart_num,), horizontalalignment='right', fontsize=12) # chart number 
    plt.figtext(0.95, 0.95, datetime.date.today(), horizontalalignment='right', fontsize=8) 


    # FIGURE FORMATTING 
    myFmt = mdates.DateFormatter('%d/%m/%Y') 
    ax = plt.gca() 
    ax.xaxis.set_major_formatter(myFmt) 
    plt.gcf().autofmt_xdate() 
    ax.set_ylim(y_range[chart_num-1]) 
    plt.grid() 
    fig.tight_layout() 
    plt.subplots_adjust(left=0.05, right=0.95, top=0.9, bottom=0.15) 
    fig_pdf_file = "PDF/OXX_grp_page %s.pdf" % (chart_num,) 
    fig.savefig(fig_pdf_file) 
    XXs_curr_grp = [] 
    chart_num += 1 # assumed charts numbering is the same as the order of plotting 
plt.show() 
+0

Я думаю, вы хотите добавить свой основной код (все, что в настоящее время не входит в функцию) в качестве функции. Затем вы можете вызвать основную функцию с разными параметрами. Чтобы импортировать функцию из другого файла, используйте 'from file import function' –

ответ

2

Нет, вам не нужно определять класс. Вам нужно удалить общие функции из одного файла и импортировать их. Оператор import может импортировать установленные пакеты python, но также файлы python. Используйте его следующим образом:

# myfile.py 

def f(x): 
    return x * 2 

# main.py 

import myfile 

myfile.f(2) 

Обратите внимание, что для этого примера оба файла должны находиться в одном каталоге.

Однако, если вы хотите хранить myfile.py в другом каталоге, то есть в этой иерархии:

my_project 
----main.py 
----my_modules 
     ----myfile.py 
     ----__init__.py 

Просто создайте пустой __init__.py файл в каталоге «my_modules», и изменить оператор импорта, чтобы отразить import my_modules.myfile.

+0

Как насчет цикла, который не входит в функцию, или я должен поместить его в функцию? Я просто хочу сделать файл как можно более компактным – Curtis

+0

@Kudrat Поместите его в функцию, а затем вызовите его. – Majora320

+0

@Kudrat Если вы хотите иметь код, который выполняется только в том случае, если вы используете файл в качестве основной программы (а не из импорта), оберните его в 'if \ _ \ _ name \ _ \ _ == "\ _ \ _ main \ _ \ _ "» – Majora320