এটা কি অজগর থেকে ভিতরে ফাংশন আমদানি করা?


126

পিইপি 8 বলেছেন:

  • আমদানি সর্বদা ফাইলের শীর্ষে রাখা হয় কেবল কোনও মডিউল মন্তব্য এবং ডকাস্ট্রিংয়ের পরে এবং মডিউল গ্লোবাল এবং ধ্রুবকগুলির আগে।

উপলক্ষে, আমি পিইপি 8 লঙ্ঘন করি Some একটি সাধারণ নিয়ম হিসাবে, যদি এমন কোনও আমদানি হয় যা কেবলমাত্র একটি ফাংশনের মধ্যে ব্যবহার করা হয় তবে আমি এটি করি।

কোন মতামত?

সম্পাদনা করুন (ফাংশনগুলিতে আমদানি করা বোধ করার কারণটি ভাল ধারণা হতে পারে):

মূল কারণ: এটি কোডকে আরও পরিষ্কার করতে পারে।

  • কোনও ফাংশনের কোডটি দেখার সময় আমি নিজেকে জিজ্ঞাসা করতে পারি: "ফাংশন / ক্লাস এক্সএক্সএক্সএক্স কি?" (ফাংশনের অভ্যন্তরে xxx ব্যবহৃত হচ্ছে)। আমার যদি আমার সমস্ত আমদানি মডিউলের শীর্ষে থাকে তবে এক্সএক্সএক্স কি তা নির্ধারণ করতে আমাকে সেখানে যেতে হবে। এটি ব্যবহার করার সময় এটি একটি সমস্যা বেশি from m import xxx। দেখতে দেখতে m.xxxফাংশনে সম্ভবত আমাকে আরো বলে। কিসের উপর নির্ভর করে m: এটি কি সুপরিচিত শীর্ষ-স্তরের মডিউল / প্যাকেজ ( import m)? নাকি এটি একটি উপ-মডিউল / প্যাকেজ ( from a.b.c import m)?
  • কিছু ক্ষেত্রে যে অতিরিক্ত তথ্য রয়েছে ("এক্সএক্সএক্সএক্স কি?") যেখানে এক্সএক্সএক্সএক্স ব্যবহৃত হয় তার কাছাকাছি ফাংশনটি বুঝতে সহজ করে তুলতে পারে।

2
এবং আপনি কি পারফরম্যান্সের জন্য এটি করেন?
ম্যাকার্সে

4
আমি মনে করি এটি কিছু ক্ষেত্রে কোডকে আরও পরিষ্কার করে দেয়। আমি অনুমান করব যে কোনও ফাংশনে আমদানি করার সময় কাঁচা পারফরম্যান্স হ্রাস পাবে (যেহেতু আমদানি বিবৃতিটি প্রতিবার ফাংশনটি বলা হবে তখনই কার্যকর হবে)।
কোডপ

আপনি উত্তর দিতে পারেন "ফাংশন / ক্লাস এক্সএক্সএক্সএক্স কি?" জাইজেড আমদানি অ্যাবিসি সিনট্যাক্সের চেয়ে আমদানি জাইজেড সিনট্যাক্স ব্যবহার করে
টম লেস

1
যদি স্পষ্টতা একমাত্র ফ্যাক্টর হয় তবে আপনি সেই প্রসঙ্গে একটি প্রাসঙ্গিক মন্তব্যও অন্তর্ভুক্ত করতে পারেন। ;)
লক্ষ্মণ প্রসাদ

5
@ বেকমিংগুরু: অবশ্যই, তবে মন্তব্যগুলি বাস্তবতার সাথে সিঙ্ক থেকে বেরিয়ে আসতে পারে ...
কোডেপ

উত্তর:


88

দীর্ঘমেয়াদে আমি মনে করি আপনি ফাইলটির শীর্ষে আপনার বেশিরভাগ আমদানি করার প্রশংসা করবেন, এইভাবে আপনি এক নজরে বলতে পারবেন যে আপনার মডিউলটি কী কী আমদানি করা দরকার তার দ্বারা কতটা জটিল।

যদি আমি কোনও বিদ্যমান ফাইলে নতুন কোড যুক্ত করি তবে আমি সাধারণত যেখানে প্রয়োজন সেখানে আমদানি করব এবং তারপরে যদি কোডটি না থেকে থাকে তবে আমি ফাইলের শীর্ষে আমদানি লাইনটি সরিয়ে জিনিসগুলিকে আরও স্থায়ী করব।

অন্য একটি বিষয়, আমি ImportErrorকোনও কোড চালানোর আগে একটি ব্যতিক্রম পেতে পছন্দ করি - স্যানিটি চেক হিসাবে, যাতে শীর্ষে আমদানি করার অন্য কারণ।

আমি pyCheckerঅব্যবহৃত মডিউলগুলি পরীক্ষা করতে ব্যবহার করি ।


47

দুটি অনুষ্ঠান আছে যেখানে আমি এই বিষয়ে পিইপি 8 লঙ্ঘন করেছি:

  • বিজ্ঞপ্তি আমদানি: মডিউল একটি আমদানি করে মডিউল বি, তবে মডিউলের বিতে কিছু মডিউলের একটি প্রয়োজন (যদিও এটি প্রায়শই একটি চিহ্ন যা আমি বৃত্তাকার নির্ভরতা দূর করতে মডিউলগুলি রিফ্যাক্টর করতে পারি)
  • একটি পিডিবি ব্রেকপয়েন্টটি সন্নিবেশ করা: import pdb; pdb.set_trace()এটি হ'ল সহজ বি / সি আমি যে import pdbপ্রতিটি মডিউলটি ডিবাগ করতে চাইব তার শীর্ষে রাখতে চাই না এবং ব্রেকপয়েন্টটি সরিয়ে ফেললে আমদানি সরিয়ে ফেলা সহজ মনে হয়।

এই দুটি ক্ষেত্রে বাইরে, সবকিছুকে শীর্ষে রাখাই ভাল ধারণা। এটি নির্ভরতা আরও পরিষ্কার করে তোলে।


7
আমি সম্মত হই এটি সামগ্রিকভাবে মডিউলটির সাথে নির্ভরতা আরও পরিষ্কার করে দেয়। তবে আমি বিশ্বাস করি যে শীর্ষে থাকা সমস্ত কিছু আমদানি করার জন্য এটি ফাংশন স্তরে কোডটি কম স্পষ্ট করতে পারে। আপনি যখন কোনও ফাংশনের কোডটি দেখছেন তখন আপনি নিজেকে জিজ্ঞাসা করতে পারেন: "ফাংশন / ক্লাস এক্সএক্সএক্সএক্স কি?" (এক্সএক্সএক্সএক্স ফাংশনের অভ্যন্তরে ব্যবহৃত হয়)। এবং এক্সএক্সএক্স কোথা থেকে এসেছে তা দেখতে আপনাকে ফাইলের একেবারে শীর্ষে দেখতে হবে। এম ইম্পোর্ট এক্সএক্সএক্সএক্স ব্যবহার করার সময় এটি আরও একটি সমস্যা of এম.এক্স.এক্সএক্সএক্স দেখে আপনাকে আরও বলে - কমপক্ষে এম কী তা নিয়ে সন্দেহ না থাকলে।
কোডেপ

20

আমরা যে চারটি আমদানি ব্যবহারের মামলা ব্যবহার করব তা এখানে

  1. import(এবং from x import yএবং import x as y) উপরের

  2. আমদানির জন্য পছন্দগুলি। উপরে.

    import settings
    if setting.something:
        import this as foo
    else:
        import that as foo
  3. শর্তসাপেক্ষ আমদানি। জেএসএন, এক্সএমএল লাইব্রেরি এবং এর মতো ব্যবহার করে। উপরে.

    try:
        import this as foo
    except ImportError:
        import that as foo
  4. গতিশীল আমদানি। এখনও অবধি, আমাদের কেবল এটির একটি উদাহরণ রয়েছে।

    import settings
    module_stuff = {}
    module= __import__( settings.some_module, module_stuff )
    x = module_stuff['x']

    নোট করুন যে এই গতিশীল আমদানি কোডটি নিয়ে আসে না, তবে পাইথনে লিখিত জটিল ডেটা কাঠামো নিয়ে আসে। এটি হ'ল একজাতীয় টুকরো টুকরো টুকরো যেমন হ'ল হাতের নাগালে।

    এটি একটি মডিউলের শীর্ষে আরও কম-বেশি


কোড পরিষ্কার করার জন্য আমরা যা করি তা এখানে:

  • মডিউলগুলি সংক্ষিপ্ত রাখুন।

  • যদি আমার সমস্ত আমদানি মডিউলের শীর্ষে থাকে তবে নাম কী তা নির্ধারণ করতে আমাকে সেখানে যেতে হবে। মডিউলটি যদি ছোট হয় তবে এটি করা সহজ।

  • কিছু ক্ষেত্রে যেখানে নাম ব্যবহার করা হয়েছে তার কাছে কাছে অতিরিক্ত তথ্য থাকা ফাংশনটি বুঝতে সহজ করে তুলতে পারে। মডিউলটি যদি ছোট হয় তবে এটি করা সহজ।


মডিউলগুলি সংক্ষিপ্ত রাখা অবশ্যই খুব ভাল ধারণা। তবে সর্বদা উপলব্ধ ক্রিয়াকলাপের জন্য "আমদানি তথ্য" থাকার সুবিধা পেতে, সর্বাধিক মডিউল দৈর্ঘ্যের একটি পর্দা হতে পারে (সম্ভবত 100 লাইন সর্বাধিক)। এবং এটি সম্ভবত বেশিরভাগ ক্ষেত্রে ব্যবহারিক হতে সংক্ষিপ্ত হবে।
কোডেপ

আমি মনে করি আপনি এটিকে যৌক্তিক চরম দিকে নিয়ে যেতে পারেন। আমি মনে করি একটি ব্যালেন্স পয়েন্ট থাকতে পারে যেখানে আপনার মডিউলটি "যথেষ্ট ছোট" যা আপনার জটিলতা পরিচালনা করতে অভিনব আমদানি কৌশলগুলির প্রয়োজন নেই। আমাদের গড় মডিউল আকার - কাকতালীয়ভাবে - প্রায় 100 লাইন।
এসলট

8

একটি বিষয় মনে রাখবেন: অযথা আমদানি সম্পাদন সমস্যা তৈরি করতে পারে problems সুতরাং এটি যদি এমন কোনও ফাংশন হয় যা ঘন ঘন বলা হয়, আপনি কেবলমাত্র আমদানিটিকে শীর্ষে রাখাই ভাল better অবশ্যই এটি একটি অপ্টিমাইজেশন, সুতরাং যদি কোনও বৈধ কেস তৈরি করতে হয় যে কোনও ফাংশনের অভ্যন্তরে আমদানি করা কোনও ফাইলের শীর্ষে আমদানি করার চেয়ে আরও স্পষ্ট হয়, যা বেশিরভাগ ক্ষেত্রে পারফরম্যান্সকে ট্রাম্প করে।

আপনি যদি আয়রন পাইথন করছেন, তবে আমাকে বলা হয়েছে যে ফাংশনগুলির ভিতরে আমদানি করা ভাল (যেহেতু আয়রন পাইথনে কোড সংকলন ধীর হতে পারে)। সুতরাং, আপনি তখন ফাংশনগুলির ভিতরে আমদানি করে কোনও উপায় পেতে সক্ষম হতে পারেন। তবে এগুলি বাদে আমি যুক্তি দিয়েছি যে সম্মেলনটি লড়াইয়ের পক্ষে এটি উপযুক্ত নয়।

একটি সাধারণ নিয়ম হিসাবে, যদি এমন কোনও আমদানি হয় যা কেবলমাত্র একটি ফাংশনের মধ্যে ব্যবহার করা হয় তবে আমি এটি করি।

আমি আর একটি বিষয় উল্লেখ করতে চাই তা হ'ল এটি একটি সম্ভাব্য মেইনটেন্স সমস্যা হতে পারে। আপনি যদি এমন কোনও ফাংশন যুক্ত করেন যা মডিউল ব্যবহার করে যা কেবলমাত্র একটি ফাংশন দ্বারা ব্যবহৃত হয়েছিল? আপনি কি ফাইলটির শীর্ষে আমদানিটি যুক্ত করতে মনে রাখবেন? বা আপনি কি আমদানির জন্য প্রতিটি ফাংশন স্ক্যান করতে যাচ্ছেন?

এফডাব্লুআইডাব্লু, এমন কোনও মামলা রয়েছে যেখানে এটি কোনও ফাংশনের অভ্যন্তরে আমদানি করে তোলে। উদাহরণস্বরূপ, আপনি যদি ভাষাটি cx_Oracle এ সেট করতে চান, আপনার আমদানি করার আগে NLS _LANG এনভায়রনমেন্ট ভেরিয়েবল সেট করতে হবে । সুতরাং, আপনি এই কোড দেখতে পারেন:

import os

oracle = None

def InitializeOracle(lang):
    global oracle
    os.environ['NLS_LANG'] = lang
    import cx_Oracle
    oracle = cx_Oracle

2
আমি আপনার মূল বক্তব্য ইস্যুতে একমত। রিফ্যাক্টরিং কোডটি কিছুটা সমস্যাযুক্ত হতে পারে। যদি আমি একটি দ্বিতীয় ফাংশন যুক্ত করি যা কেবলমাত্র একটি ফাংশন দ্বারা ব্যবহৃত মডিউলটি ব্যবহার করে - আমি হয় আমদানিটিকে শীর্ষে নিয়ে যাই, বা দ্বিতীয় ফাংশনেও মডিউলটি আমদানি করে আমার নিজের সাধারণ নিয়মটি ভেঙে দেয়।
কোডেপ

2
আমি মনে করি পারফরম্যান্স যুক্তি অন্যভাবেও যেতে পারে। মডিউল আমদানি সময় সাপেক্ষ হতে পারে। সুপার কম্পিউটারগুলির মতো বিতরণ করা ফাইল সিস্টেমগুলিতে, নাম্পির মতো একটি বড় মডিউল আমদানি করতে কয়েক সেকেন্ড সময় নিতে পারে। যদি কোনও একক, খুব কম ব্যবহৃত ফাংশনের জন্য মডিউল প্রয়োজন হয় তবে ফাংশনে আমদানি করা সাধারণ ক্ষেত্রে উল্লেখযোগ্যভাবে গতি বাড়িয়ে তুলবে।
amaurea

6

স্ব-পরীক্ষামূলক মডিউলগুলির জন্য আমি আগে এই নিয়মটি ভঙ্গ করেছি। এটি হ'ল এগুলি সাধারণত সমর্থনের জন্য ব্যবহৃত হয় তবে আমি তাদের জন্য একটি প্রধান সংজ্ঞা দিচ্ছি যাতে আপনি এগুলি তাদের দ্বারা চালিত করলে আপনি তাদের কার্যকারিতা পরীক্ষা করতে পারেন। সেক্ষেত্রে আমি মাঝে মাঝে আমদানি করি getoptএবং cmdকেবল প্রধানত, কারণ আমি কোডটি পড়ে এমন কারও কাছে এটি স্পষ্ট হওয়া চাই যে এই মডিউলগুলির মডিউলটির সাধারণ ক্রিয়াকলাপের কোনও সম্পর্ক নেই এবং কেবল পরীক্ষার জন্য এটি অন্তর্ভুক্ত করা হচ্ছে।


5

মডিউলটি দু'বার লোড করা নিয়ে প্রশ্ন থেকে আসা - কেন উভয় নয়?

স্ক্রিপ্টের শীর্ষে থাকা একটি আমদানি এই ফাংশনটিকে আরও বেশি পারমাণবিক তৈরি করে নির্ভরতা এবং ফাংশনটিতে অন্য একটি আমদানি নির্দেশ করবে, কারণ ক্রমাগত আমদানি সস্তা হওয়ায় আপাতদৃষ্টিতে কোনও কার্যকারিতা অসুবিধে না ঘটায়।


3

যতক্ষণ importনা এটি হয় এবং ততক্ষণ from x import *আপনার এগুলি শীর্ষে রাখা উচিত। এটি গ্লোবাল নেমস্পেসে কেবল একটি নাম যুক্ত করে এবং আপনি পিইপি ৮ এ আটকে যান Plus প্লাস, পরে যদি আপনার এটি অন্য কোথা থেকে প্রয়োজন হয়, আপনার কাছাকাছি কিছু স্থানান্তর করতে হবে না।

এটি কোনও বড় বিষয় নয়, তবে যেহেতু প্রায় কোনও পার্থক্য নেই আমি পিইপি 8 বলে যা করার পরামর্শ দেব।


3
আসলে, from x import *একটি ফাংশন ভিতরে রাখলে একটি সিনট্যাক্স ওয়ার্নিং তৈরি হবে, কমপক্ষে 2.5 তে।
রিক কোপেল্যান্ড

3

স্ক্ল্যাচমিটিতে ব্যবহৃত বিকল্প পদ্ধতির দিকে একবার নজর দিন: নির্ভরতা ইনজেকশন:

@util.dependencies("sqlalchemy.orm.query")
def merge_result(query, *args):
    #...
    query.Query(...)

লক্ষ্য করুন কীভাবে আমদানিকৃত লাইব্রেরিটি ডেকরেটারে ঘোষণা করা হয়, এবং ফাংশনের আর্গুমেন্ট হিসাবে পাস করা হয় !

এই পদ্ধতির কোড ক্লিনার করে তোলে, এবং একটি বিবৃতি চেয়ে 4.5 গুণ দ্রুত কাজ করে import!

বেঞ্চমার্ক: https://gist.github.com/kolypto/589e84fbcfb6312532658df2fabdb796


2

মডিউলগুলিতে যা উভয়ই 'নরমাল' মডিউল এবং if __name__ == '__main__':সম্পাদনযোগ্য (যেমন একটি- সেকশন থাকতে পারে), আমি সাধারণত মডিউলগুলি আমদানি করি যা কেবলমাত্র প্রধান বিভাগের ভিতরে মডিউলটি সম্পাদন করার সময় ব্যবহৃত হয়।

উদাহরণ:

def really_useful_function(data):
    ...


def main():
    from pathlib import Path
    from argparse import ArgumentParser
    from dataloader import load_data_from_directory

    parser = ArgumentParser()
    parser.add_argument('directory')
    args = parser.parse_args()
    data = load_data_from_directory(Path(args.directory))
    print(really_useful_function(data)


if __name__ == '__main__':
    main()

1

আর একটি (সম্ভবত "কোণার") কেস রয়েছে যেখানে এটি importবিরল ব্যবহৃত ফাংশনগুলির ভিতরে উপকারী হতে পারে : শুরুর সময় time

আমি ছোট্ট আইওটি সার্ভারে একটি সিরিয়াল লাইন থেকে আদেশগুলি গ্রহণ করে এবং অপারেশনগুলি সম্পাদন করে, সম্ভবত খুব জটিল অপারেশন দিয়ে চলার পরিবর্তে একটি জটিল প্রোগ্রাম দিয়ে আমি সেই প্রাচীরটি একবার আঘাত করি।

স্থাপন importআছে বোঝানো ফাইল উপরের বিবৃতি সব আমদানির সার্ভার শুরুর আগে প্রক্রিয়াভুক্ত; যেহেতু importতালিকা অন্তর্ভুক্ত jinja2, lxml, signxmlএবং অন্যান্য "ভারী ওজন" (এবং SoC খুব শক্তিশালী ছিল না) এই বোঝানো মিনিট প্রথম নির্দেশ সামনে আসলে মৃত্যুদন্ড কার্যকর করা হয়।

ওটিওএইচ বেশিরভাগ আমদানি ফাংশনে রেখে আমি সেকেন্ডের মধ্যে সিরিয়াল লাইনে সার্ভারটি "জীবিত" রাখতে সক্ষম হয়েছি। অবশ্যই যখন মডিউলগুলি সত্যই প্রয়োজন ছিল তখন আমাকে মূল্য দিতে হয়েছিল (দ্রষ্টব্য: importঅলস সময়ে একটি ব্যাকগ্রাউন্ড টাস্ক তৈরি করে এটি প্রশমিত করা যেতে পারে )।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.