বাইরের স্কোপগুলিতে শ্যাডিংয়ের নামগুলি কতটা সংজ্ঞায়িত করা হয়?


207

আমি কেবল পাইচার্মে স্যুইচ করেছি এবং আমি আমার কোডটি উন্নত করতে সমস্ত সতর্কতা এবং ইঙ্গিতগুলি সম্পর্কে খুব খুশি। আমি বুঝতে পারি না এটি বাদে:

This inspection detects shadowing names defined in outer scopes.

আমি জানি বাহ্যিক ক্ষেত্র থেকে পরিবর্তনশীল অ্যাক্সেস করা খারাপ অভ্যাস তবে বাইরের সুযোগটি ছায়া নেওয়ার ক্ষেত্রে কী সমস্যা?

এখানে একটি উদাহরণ রয়েছে, যেখানে পাইচার্ম আমাকে সতর্কতা বার্তা দেয়:

data = [4, 5, 6]

def print_data(data): # <-- Warning: "Shadows 'data' from outer scope
    print data

print_data(data)

1
এছাড়াও আমি "এই পরিদর্শনটি সনাক্ত করে ..." স্ট্রিংটি অনুসন্ধান করেছিলাম তবে পাইচার্ম অনলাইন সহায়তা পাওয়া যায়নি: jetbrains.com/pycharm/webhelp/getting-help.html
ফ্রেমেস্টার

1
পাইচার্মে এই বার্তাটি বন্ধ করতে: <Ctrl> + < Al>> গুলি (সেটিংস), সম্পাদক , পরিদর্শন , " বাইরের স্কোপ থেকে নাম ছায়া "। আনচেক করুন।
চেইমজি

উত্তর:


222

আপনার উপরের স্নিপেটে কোনও বড় কথা নয়, তবে কয়েকটি আরও যুক্তি এবং কোডের বেশ কয়েকটি আরও লাইন সহ একটি ফাংশনটি কল্পনা করুন। তারপরে আপনি নিজের dataযুক্তির নাম পরিবর্তন করার সিদ্ধান্ত yaddaনিয়েছেন তবে ফাংশনটির শরীরে এটি যে কোনও স্থান ব্যবহার করা হয় তা মিস করুন ... এখন dataগ্লোবালকে বোঝায়, এবং আপনি অদ্ভুত আচরণ শুরু করেন - যেখানে আপনি NameErrorযদি না থাকেন তবে আরও অনেক স্পষ্টতই আপনি থাকবেন একটি বিশ্বব্যাপী নাম আছে data

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

শেষ অবধি, অন্তর্নির্মিত ফাংশন এবং প্রকারগুলিও একই নামস্থানে বাস করে এবং একইভাবে ছায়া গোছানো যায়।

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


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

পাইচার্মের নাম পরিবর্তনের অপারেশন ছাড়াও আমি বহিরাগত স্কোপগুলিকে উল্লেখ করে এমন ভেরিয়েবলগুলির জন্য বিশেষ সিনট্যাক্স হাইলাইট থাকতে পছন্দ করব। এই দু'জনের এই সময়টি ছায়ার রেজোলিউশন গেমকে অপ্রাসঙ্গিকভাবে উপভোগ করা উচিত।
লিও

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

147

বর্তমানে সর্বাধিক আপ-ভোট এবং গ্রহণযোগ্য উত্তর এবং সর্বাধিক উত্তরগুলি এখানে বিন্দুটি মিস করে।

আপনার ফাংশনটি কত দিন বা আপনি কীভাবে আপনার পরিবর্তনশীলটির নাম বর্ণনামূলকভাবে নাম রাখবেন (সম্ভাব্য নামের সংঘর্ষের সম্ভাবনা হ্রাস করার জন্য) এটি গুরুত্বপূর্ণ নয়।

আপনার ফাংশনের স্থানীয় পরিবর্তনশীল বা এর পরামিতি বিশ্বব্যাপী কোনও নাম ভাগ করে নেওয়ার ঘটনাটি সম্পূর্ণ অপ্রাসঙ্গিক। এবং প্রকৃতপক্ষে, আপনি স্থানীয় ভেরিয়েবলের নামটি কতটা সাবধানতার সাথে বেছে নিচ্ছেন, আপনার ফাংশনটি কখনই "আমার শীতল নামটিও yaddaবিশ্বব্যাপী পরিবর্তনশীল হিসাবে ব্যবহৃত হবে কিনা" তা আগে থেকেই আশা করতে পারে না " সমাধান? কেবল যে সম্পর্কে চিন্তা করবেন না! সঠিক মানসিকতা হ'ল আপনার ফাংশনটি কেবলমাত্র স্বাক্ষর হিসাবে এবং এর পরামিতিগুলি থেকে ইনপুট গ্রাস করতে ডিজাইন করা , এইভাবে আপনাকে বিশ্বব্যাপী সুযোগে কী (বা হবে) তার যত্ন নেওয়ার দরকার নেই এবং তার পরে ছায়া কাটা মোটেও সমস্যা হয়ে উঠবে না।

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

def print_data(data):
    print data

def main():
    data = [4, 5, 6]
    print_data(data)

main()

আপনার বৈশ্বিক জিনিস ঠিক করে / অপসারণ করে, আপনার বর্তমান স্থানীয় কার্যকারিতা সামঞ্জস্য না করেই এই সমস্যাটিকে "সমাধান" করার সঠিক উপায়।


11
ঠিক আছে, নিশ্চিত, একটি নিখুঁত বিশ্বে আপনি প্যারামিটারটি পরিবর্তন করার সময় আপনার কোনও অনুসন্ধান-প্রতিস্থাপনের কথা ভুলে যান, তবে ভুলগুলি ঘটে এবং তাই পাইচার্ম বলছে - "সতর্কতা - কোনও কিছুই প্রযুক্তিগতভাবে ত্রুটিযুক্ত নয়, তবে এটি সহজেই একটি সমস্যা হয়ে উঠতে পারে "
দ্বিয়ান্ডারসন

1
@ ডোয়ান্ডারসন আপনি যে পরিস্থিতিটি উল্লেখ করেছেন তা নতুন কিছু নয়, এটি বর্তমানে নির্বাচিত উত্তরে পরিষ্কারভাবে বর্ণিত হয়েছে। যাইহোক, আমি যে বক্তব্যটি তৈরি করার চেষ্টা করছি তা হ'ল আমাদের বৈশ্বিক পরিবর্তনশীল এড়ানো উচিত, বৈশ্বিক চলককে ছায়া এড়ানো উচিত নয়। দ্বিতীয়টি পয়েন্টটি মিস করে। এটা নাও? বুঝেছি?
রায়লুও

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

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

2
একমত। এখানে সমস্যা পাইথন স্কোপিং। বর্তমান ক্ষেত্রের বাইরে অবজেক্টগুলিতে সুস্পষ্ট অ্যাক্সেস সমস্যার জন্য জিজ্ঞাসা করছে। কে চাইবে! একটি লজ্জা কারণ অন্যথায় পাইথন হ'ল একটি সুন্দর চিন্তাভাবনা করা ভাষা (মডিউল নামকরণের ক্ষেত্রে একই রকম অস্পষ্টতার বিরুদ্ধে নয়)।
কোডকবি

24

কিছু ক্ষেত্রে ভারসাম্যহীন কাজটি হতে পারে ভার্স + কোডটি অন্য ফাংশনে স্থানান্তর করা:

def print_data(data):
    print data

def main():
    data = [4, 5, 6]
    print_data(data)

main()

হ্যাঁ. আমি মনে করি একটি ভাল আদর্শ রিফ্যাক্টরিংয়ের মাধ্যমে স্থানীয় ভেরিয়েবল এবং গ্লোবাল ভেরিয়েবলগুলি পরিচালনা করতে সক্ষম। আপনার টিপ সত্যই আদিম
আদর্শের

5

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

আপনার উদাহরণ ফাংশনের জন্য, আমি মনে করি যে বিশ্বব্যাপী ছায়া কাটা মোটেই খারাপ নয়।


5

এটা কর:

data = [4, 5, 6]

def print_data():
    global data
    print(data)

print_data()

3
data = [4, 5, 6] #your global variable

def print_data(data): # <-- Pass in a parameter called "data"
    print data  # <-- Note: You can access global variable inside your function, BUT for now, which is which? the parameter or the global variable? Confused, huh?

print_data(data)

47
আমি একটার জন্য বিভ্রান্ত নই এটি বেশ স্পষ্টতই প্যারামিটার।

2
@ ডেলানান আপনি এই তুচ্ছ উদাহরণে বিভ্রান্ত নাও হতে পারেন, তবে কাছাকাছি সংজ্ঞায়িত অন্যান্য ফাংশনগুলি dataকয়েক শত কোডের গভীরতার মধ্যে বিশ্বব্যাপী ব্যবহার করলে কী হবে?
জন কোলান্ডুনি

13
@ হেভাইটলাইট আমাকে কাছের অন্যান্য ফাংশনগুলি দেখার দরকার নেই। আমি কেবল এই ফাংশনটি দেখি এবং এটি দেখতে পারি যে dataএটি এই ফাংশনের স্থানীয় নাম , তাই আমি একই নামের একটি বিশ্বব্যাপী উপস্থিত কিনা তা চেক / স্মরণ করতেও বিরক্ত করি না , এতে কী রয়েছে তা ছেড়ে দেওয়া।

4
আমি মনে করি না এই যুক্তিটি বৈধ, কেবলমাত্র একটি গ্লোবাল ব্যবহার করার জন্য, আপনাকে ফাংশনের অভ্যন্তরে "গ্লোবাল ডেটা" সংজ্ঞায়িত করতে হবে। অন্যথায়, গ্লোবাল অ্যাক্সেসযোগ্য নয়।
কোডিএফ

1
@ কোডিএফ False- আপনি যদি সংজ্ঞায়িত না করেন তবে কেবল ব্যবহারের চেষ্টা করুন data, এটি কোনও সন্ধান না পাওয়া পর্যন্ত এটি স্কোপগুলির মাধ্যমে দেখায়, যাতে এটি বিশ্বব্যাপী খুঁজে পায় না datadata = [1, 2, 3]; def foo(): print(data); foo()
ডোয়ান্ডারসন

3

আমি পাইচার্মের উপরের ডানদিকে একটি সবুজ টিক দেখতে চাই see আমি কেবলমাত্র এই সতর্কতাটি পরিষ্কার করার জন্য আন্ডারস্কোর সহ পরিবর্তনশীল নামগুলি সংযোজন করি যাতে আমি গুরুত্বপূর্ণ সতর্কতাগুলিতে ফোকাস করতে পারি।

data = [4, 5, 6]

def print_data(data_): 
    print(data_)

print_data(data)

2

দেখে মনে হচ্ছে এটি 100% পাইস্টেস্ট কোড প্যাটার্ন

দেখা:

https://docs.pytest.org/en/latest/fixture.html#conftest-py-sharing-fixture-functions

আমার একই সমস্যা ছিল, এই কারণেই আমি এই পোস্টটি খুঁজে পেয়েছি;)

# ./tests/test_twitter1.py
import os
import pytest

from mylib import db
# ...

@pytest.fixture
def twitter():
    twitter_ = db.Twitter()
    twitter_._debug = True
    return twitter_

@pytest.mark.parametrize("query,expected", [
    ("BANCO PROVINCIAL", 8),
    ("name", 6),
    ("castlabs", 42),
])
def test_search(twitter: db.Twitter, query: str, expected: int):

    for query in queries:
        res = twitter.search(query)
        print(res)
        assert res

এবং এটি দিয়ে সতর্ক করবে This inspection detects shadowing names defined in outer scopes.

এটি ঠিক করতে কেবল আপনার twitterস্থিতিশীলিকে সরিয়ে দিন move./tests/conftest.py

# ./tests/conftest.py
import pytest

from syntropy import db


@pytest.fixture
def twitter():
    twitter_ = db.Twitter()
    twitter_._debug = True
    return twitter_

এবং twitterমত ফিক্সচার অপসারণ./tests/test_twitter2.py

# ./tests/test_twitter2.py
import os
import pytest

from mylib import db
# ...

@pytest.mark.parametrize("query,expected", [
    ("BANCO PROVINCIAL", 8),
    ("name", 6),
    ("castlabs", 42),
])
def test_search(twitter: db.Twitter, query: str, expected: int):

    for query in queries:
        res = twitter.search(query)
        print(res)
        assert res

এটি কিউএ, পাইচার্ম এবং সবাইকে খুশি করবে

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