71

from module import functionFMIFコーディングスタイルと呼びましょう。

import moduleIMコーディングスタイルと呼びましょう。

from package import moduleFPIMコーディングスタイルと呼びましょう。

IM + FPIMがFMIFよりも優れたコーディングスタイルと見なされるのはなぜですか?(この質問のインスピレーションについては、この投稿を参照してください。)

IMよりもFMIFを好むようになるいくつかの基準は次のとおりです。

  1. コードの短さ:短い関数名を使用できるため、1行あたり80列の規則に従うことができます。
  2. 読みやすさ:chisquare(...)より読みやすいように見えます scipy.stats.stats.chisquare(...)。これは主観的な基準ですが、ほとんどの人が同意すると思います。
  3. リダイレクトのしやすさ:FMIFを使用していて、後で何らかの理由でPythonをリダイレクトして定義するのfunctionではalt_moduleなく、module1行だけ変更する必要がある場合:from alt_module import function。IMを使用する場合は、コードの多くの行を変更する必要があります。
FPIMが最初の2つの問題を無効にする方法があることはわかっていますが、3番目の問題はどうでしょうか。

IM + FPIMがFMIFよりも優れている理由はすべて興味がありますが、特に、ここで説明する次の点について詳しく説明したいと思います。

IMの長所:

  1. テストでのモック/注入の容易さ。(私は最近、この用語の意味を学びましたが、モックについてはあまり詳しくありません。ここで、IMがFMIFよりも優れていることを示すコードを示していただけますか?)
  2. 一部のエントリを再定義することにより、モジュールを柔軟に変更する機能。(これはIMに対するFMIFの利点のように思われるため、私は何かを誤解しているに違いありません。上記のFMIFを支持する私の3番目の理由を参照してください。)
  3. データのシリアル化とリカバリに関する予測可能で制御可能な動作。(IMまたはFMIFの選択がこの問題にどのように影響するかは本当にわかりません。詳しく説明してください。)
  4. FMIFが「私の名前空間を汚染する」ことは理解していますが、否定的な言い回しであるだけでなく、これがコードを具体的にどのように傷つけるかについては理解していません。
PS。この質問を書いているときに、質問が主観的であり、閉じられる可能性が高いという警告を受け取りました。閉じないでください。私は主観的な意見を探しているのではなく、IM+FPIMがFMIFよりも明らかに優れている具体的なコーディング状況を探しています。

どうもありがとう。

4

5 に答える 5

47

IM/FPIM のマイナス面は、多くの場合、as節を適切に使用することで改善できます。 from some.package import mymodulewithalongname as mymodコードを短くして可読性を高めることができます。名前mymodulewithalongnamesomethingcompletelydifferent明日に変更すると、as句を単一のステートメントとして使用して編集できます。

FMIF 支持のポイント 3 (リダイレクトの場合は R と呼ぶ) と FPIM 支持の場合のポイント 2 (柔軟性のために F と呼ぶ) を考えてみてください。R はモジュール境界の完全性の喪失を助長し、F はそれを強化します。モジュール内の複数の関数、クラス、および変数は、多くの場合、一緒に動作するように意図されています。それらは、異なる意味に個別に切り替えられるべきではありません。たとえば、modulerandomとその関数seedandを考えuniformてみましょう。そのうちの 1 つだけのインポートを別のモジュールに切り替えると、 へseedの呼び出しと への呼び出しの結果の間の通常の接続が切断されuniformます。モジュールがまとまりと整合性を持って適切に設計されている場合、モジュールの境界を壊す R の促進は実際にはマイナスです。していません

逆に、F は結合された関数、クラス、および変数 (つまり、一般に、モジュール性によって一緒に属するエンティティ) の調整された切り替えを可能にするものです。たとえば、テストを繰り返し可能にする (FPIM プロポイント 1) には、モジュール内でとの両方をモックします。コードが FPIM に従っている場合は、準備が整い、調整が保証されます。ただし、関数を直接インポートしたコードがある場合は、そのようなモジュールをそれぞれ探し出し、モックを何度も何度も繰り返さなければなりません。テストを完全に再現可能にするには、通常、日付と時刻の関数の「調整されたモック」も必要です。一部のモジュールで使用する場合は、それらすべてを見つけてモックする必要があります (実行しているすべてのモジュールも同様です)。seedrandomrandomfrom datetime import datetimefrom time import timeなど) システムのさまざまな部分が「今何時ですか?」完全に一貫しています (FPIM を使用する場合は、関連する 2 つのモジュールをモックするだけです)。

私は FPIM が好きです。なぜなら、単独で修飾された名前ではなく、複数修飾された名前を使用してもあまり付加価値がないからです(ベアネームと修飾名の違いは非常に大きいです、単独で修飾された名前を使用すると、はるかに多くの制御が得られます。または、裸の名前でできるよりも乗算します!)。

ええと、あなたの指摘の一つ一つに答えるのに一日のすべてを費やすことはできません -- あなたの質問はおそらく半ダースの質問であるべきです;-)。これが少なくとも「F が R よりも優れている理由」といくつかのモック/テストの問題に対処することを願っています。つまり、適切に設計されたモジュール性を (R を介して) 損なうのではなく、(F を介して)維持および強化することになります。

于 2009-11-16T19:49:15.377 に答える
18

これに関する古典的なテキストは、よくあることですが、effbot である Fredrik Lundh からのものです。彼のアドバイス:使用すべきでない場合を除いて、常にインポートを使用してください。

言い換えれば、賢明であること。個人的には、いくつかのモジュールが深いものは何でもインポートされる傾向があることがわかりましたfrom x.y.z import a- 主な例は Django モデルです。しかし、それは何よりもスタイルの問題であり、一貫したものを持つ必要があります。特にdatetime、モジュールとそれに含まれるクラスの両方が同じものと呼ばれる のようなモジュールでは。書く必要がありますdatetime.datetime.now()datetime.now()?(私のコードでは、常に前者です。)

質問リストの項目 1 と 2 は同じ問題のようです。Python の動的な性質により、使用するメソッドに関係なく、モジュールの名前空間内の項目を簡単に置き換えることができます。モジュール内の 1 つの関数が、モックしたい別の関数を参照している場合、問題が生じます。この場合、関数ではなくモジュールをインポートすることでmodule.function_to_replace = myreplacementfunc、すべてが透過的に機能しますが、IM を使用する場合と同じように FPIM を使用しても簡単に実行できます。

また、項目 3 がどのように関係しているのかもわかりません。しかし、あなたの項目 4 は少し誤解に基づいていると思います。あなたが与える方法はどれも「あなたの名前空間を汚染する」ことはありません。つまり、何をインポートしているのかまったくわからないため、関数がどこから来たのか、読者に手がかりが与えられずにコードに表示される可能性がありますfrom module import *それは恐ろしいことであり、何としても避けるべきです。

于 2009-11-16T19:32:11.213 に答える
6

ここに素晴らしい答えがあります(私はそれらすべてに賛成しました)、そしてこれがこの問題に関する私の考えです:

まず、各箇条書きに対処します。

(伝えられるところでは) FMIF の長所:

  • コードの短さ: 関数名を短くすると、1 行あたり 80 カラムを維持するのに役立ちます。

おそらくですが、モジュール名は通常十分に短いため、これは関係ありません。確かにdatetime, だけでなくos, re,sysなどもあります。Python では 内に自由な改行があり{ [ (ます。ネストされたモジュールの場合、常にasIM と FPIM の両方にあります

  • 読みやすさ: chisquare(...) は scipy.stats.stats.chisquare(...) よりも読みやすいようです。

強く同意しない。外部コード (または数か月後の自分のコード) を読むと、各関数がどこから来たのかを知るのは困難です。修飾名のおかげで、2345 行目からモジュール宣言ヘッダーまで行ったり来たりする必要がなくなりました。また、コンテキストも提供ますchisquarescypy繰り返しになりますが、いつでも省略できますscipy.stats.stats as scypystscypyst.chisquare(...)修飾名のすべての利点を備えた十分な短さです。

import os.path as ospjoin(expanduser(),basename(splitext())) などのように、3 つ以上の関数を 1 回の呼び出しで一緒にチェーンすることは非常に一般的であることを考えると、もう 1 つの良い例です。

  • リダイレクションの容易さ: モジュールの代わりに altmodule からの関数の 1 行の再定義。

モジュール全体ではなく、単一の関数を再定義する頻度はどれくらいですか? モジュールの境界と機能の調整は維持する必要があります。これについては、Alex がすでに詳しく説明しています。ほとんどの (すべての?) 現実世界のシナリオでalt_module.xは、 が の実行可能な代替品であるmodule.x場合、おそらくalt_moduleそれ自体が の代替品となるためmodule、 を使用する場合、IM と FPIM の両方が FMIF と同じようにワンライナーになりますas

  • FPIM は、最初の 2 つの問題を無効にするのにある程度役立つことを認識しています...

実際にasは、FPIM ではなく、最初の 2 つの問題 (および 3 つ目) を軽減するものです。そのためにも IM を使用できます import some.long.package.path.x as x。FPIM と同じ結果が得られます。


したがって、上記のいずれも FMIF の長所ではありません。私が IM/FPIM を好む理由は次のとおりです。

単純さと一貫性のために、IM または FPIM のいずれかをインポートするときは、モジュールからのオブジェクトではなく、常にモジュールをインポートしています。FMIF は、関数、クラス、変数、さらには他のモジュールをインポートするために (ab-) 使用できることを覚えておいてください! の混乱について考えてみてくださいfrom somemodule import sys, somevar, os, SomeClass, datetime, someFunc

また、モジュールから複数のオブジェクトが必要な場合、FMIF は、使用するオブジェクトの数に関係なく単一の名前を使用する IM や FPIM よりも多くの名前空間を汚染します。そして、そのようなオブジェクトには修飾 名が付けられますが、これは短所ではなく長所です。問題 2 で述べたように、私見では読みやすさが向上します。

それはすべて、一貫性、シンプルさ、組織に帰着します。「オブジェクトではなく、モジュールをインポートする」という考え方は、従うのに適した簡単なマインド モデルです。

于 2013-11-07T03:26:18.597 に答える
5

Alex Martelli のように、私はas関数をインポートするときに好んで使用します。

私が行ったことの 1 つは、同じモジュールからインポートされたすべての関数にいくつかのプレフィックスを使用することです。

from random import seed as r_seed
from random import random as r_random

r_seedよりも入力が短くなりrandom.seedますが、モジュールの境界が多少保持されます。あなたのコードを何気なく見ている誰かが、それらが関連していることを見r_seed()r_random()、理解する機会を得ることができます。

もちろん、いつでも簡単に実行できます。

import random as r

そして、 と を使用r.random()r.seed()ます。これは、この場合の理想的な妥協点である可能性があります。モジュールから 1 つまたは 2 つの関数をインポートする場合にのみ、プレフィックス トリックを使用します。同じモジュールから多くの関数を使用したい場合は、おそらくas名前を短縮するために を使用して、モジュールをインポートします。

于 2009-11-16T20:16:09.987 に答える
1

私はここでMestreLionに最も同意します(そして賛成です)。

私の見解: 私はよく知らないコードを頻繁にレビューしますが、関数を見ただけで関数がどのモジュールから来ているのかわからないのは非常にイライラします。

コードは一度書かれ、何度も読まれます。

同様に、通常、コードはコーダーの利益のために書かれているのではなく、別のエンティティの利益のために書かれています。

あなたのコードは、あなたよりも Python をよく知っているが、コードに不慣れな人にとっては読みやすいものでなければなりません。

フル パスのインポートは、IDE が参照している関数またはオブジェクトの正しいソースを示すのにも役立ちます。

これらすべての理由と MestreLion が指摘した理由から、フル パスをインポートして使用することがベスト プラクティスであると結論付けています。

于 2013-11-10T01:56:54.650 に答える