0

優れたプログラミング手法に準拠するようにプログラムを改善しようとしています。だから私は何かをプログラムした方法がそれを行う良い方法であるかどうかについての提案を探しています.

私が定義した dbfunctions.py というモジュールがあります。

dbparams = {
    'dbname': 'qualitysimparams',
    'tablename': 'qualityparams',
    'tablecols': ('numpeople', 'numreviews', 'prophunters', 
                  'utility_funcform', 'goods'
    )

そして関数:

def obtainid_ifrecord(dbname, tablename, tablecols, values):
    '''Checks if there already exists a record with given <values>. 
    If so, returns the id of that record, otherwise returns zero.'''
    con, c = connecttodb()
    q1 = "use {0}".format(dbname)
    c.execute(q1)
    q2p1 = "select id from {0} ".format(tablename)
    q2p2 = "where " + " = %s and ".join(tablecols) + " = %s"
    q2 = q2p1 + q2p2    
    c.execute(q2, values)
    res = c.fetchall()
    c.close()
    con.close()
    if res:
        return res[-1][0]
    else:
        return 0

上記の 2 つ以外にも関数と変数がありますが、この投稿には関係ありません。

別のファイルに関数があります:

def checkif_paramcomboexists(numpeople, numreviews, prophunters, 
                             utility_funcform, goods):
    '''Check in the database if the simulation has been run with the 
    specified parameters. If so return the id of that run.
    '''
    goodsjson = sjson.dumps(goods)

    # paramvalues: in same order as listed in dbf.dbparams['tablecols']
    paramvalues = (numpeople, numreviews, prophunters, 
                   utility_funcform, goodsjson)

    id = dbf.obtainid_ifrecord(dbf.dbparams['dbname'],
                               dbf.dbparams['tablename'], 
                               dbf.dbparams['tablecols'],
                               paramvalues)
    return id 

paramvalues関数内の変数で変数名をハードコーディングすること checkif_paramcomboexistsは良い習慣ではないように思えます。後で何らかの理由で dbfunctions.dbparams['tablecols'] の変数の順序を変更すると、checkif_paramcomboexists関数は失敗します (データ型によってはサイレントに失敗する可能性があります)。これを回避する 1 つの方法は、次のように定義することです。

paramvalues = [eval(x) for x in dbf.dbparams['tablecols']]

しかし、一般的に使用するのは悪い習慣だと聞いたことがありますeval(ただし、いつ使用してもよい理由はわかりません)。私の質問は次のとおりです。

(i) 私が抱えている懸念に関して、これをコード化した方法でよろしいですか? 答えは「いいえ」だと思いますが、ここで専門家に確認したいだけです。(ii)eval私が示したような使用は容認できる解決策ですか? (iii) (ii) の答えが「いいえ」の場合、代替手段は何ですか?

これを読んでいただきありがとうございます。

4

2 に答える 2

3

この状況は本当にオブジェクトを必要とします。tablecols特定のデータベース テーブルに関する本質的にインスタンス情報を 2 か所で複製しているため、これらの関数を両方とも、属性を持つある種のデータベース テーブル インターフェイス オブジェクトのself.tablecolsメソッドにして、両方のメソッドで使用することは理にかなっています。

于 2012-12-19T14:43:23.913 に答える
3

ハードコーディングがうまくいかないことについてはあなたの言うとおりですeval*argsor**kwargsを使用したくない場合(ちなみに、これは実際にはより優れたオプションです)、inspectモジュールを使用して、実行しようとしていることを実行できます。

import inspect, collections
def checkif_paramcomboexists(numpeople, numreviews, prophunters, 
                             utility_funcform, goods):

    ...

    temp = inspect.getargvalues(inspect.currentframe())
    args = temp[0]
    valuedict = temp[-1]
    ordered_args_dict = collections.OrderedDict(sorted(valuedict.items(), key=lambda x: args.index(x[0])))
    paramvalues = ordered_args_dict.values()

    ...

基本的に、ここで行われているのはinspect.getargvalues(inspect.currentframe())、最初の項目が適切に順序付けられた引数名のリストであり、最後の項目が引数名と値の辞書であるオブジェクトを取得することです。次に、ディクショナリから引数の名前/値のマッピングを取得し、リストの順序に基づいて順序付けすることで、順序付きディクショナリを作成します。

最終的に得られるのは、OrderedDictすべての引数とその値を持ち、それらを正しい順序で持つ です。そうすれば、それらを名前で参照することもできます (例: ordered_args_dict['numpeople'])。ただし、すべての値を で必要な順序で取得できる場合は、ordered_args_dict.values()探している出力が得られますparamvalues: 適切に順序付けられた名前に関係なく、引数のリスト。

于 2012-12-19T15:38:55.207 に答える