2016-04-14 53 views
2

我不確定這個問題是否被問到 - 到目前爲止找不到一個好的做法。避免重複代碼的最佳pythonic實踐?

我有兩個完全相同的包導入,以及一些不同的方法的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

不,你不需要定義一個類。您需要從一個文件中刪除共享函數,並將其導入另一個文件。導入語句可以導入已安裝的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語句,以反映import my_modules.myfile

+0

for循環不在函數中,或者我應該將它放入函數中?我只是想讓第二個文件儘可能小巧 – Curtis

+0

@Kudrat把它放在一個函數中,然後調用它。 – Majora320

+0

@Kudrat如果你想讓代碼只在你運行這個文件作爲主程序(而不是從導入文件)中運行,那麼把它包裝在'if \ _ \ _ name \ _ \ _ =='中。\ _ \ _ main \ _ \ _「」 – Majora320