ক্রস-মডিউল পরিবর্তনশীল কীভাবে করবেন?


122

__debug__প্রতি মডিউল প্রভাবিত কারণ পরিবর্তনশীল অংশে সুবিধাজনক। আমি যদি অন্য ভেরিয়েবল তৈরি করতে চাই যা একইভাবে কাজ করে তবে আমি কীভাবে এটি করব?

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

উত্তর:


114

আমি কোনওভাবেই, আকার বা আকারে এই সমাধানটিকে সমর্থন করি না। তবে আপনি যদি __builtin__মডিউলে কোনও পরিবর্তনশীল যুক্ত করেন তবে এটি অ্যাক্সেসযোগ্য হবে যেন কোনও গ্লোবাল অন্য যে কোনও মডিউল থেকে অন্তর্ভুক্ত থাকে __builtin__- এটি সমস্তই ডিফল্টরূপে।

a.py রয়েছে

print foo

বি.পি. রয়েছে

import __builtin__
__builtin__.foo = 1
import a

ফলাফলটি "1" মুদ্রিত হয়।

সম্পাদনা:__builtin__ মডিউল স্থানীয় প্রতীক হিসাবে পাওয়া যায় __builtins__- এই উত্তরগুলোর দুজনের মধ্যে অমিল জন্য কারণ যে। এছাড়াও নোট করুন যে পাইথন 3 এ __builtin__নামকরণ করা হয়েছে builtins


2
কোনও কারণ, আপনি এই পরিস্থিতি পছন্দ করেন না?
সফটওয়্যার উত্সাহী

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

9
যদি পাইথনের ভবিষ্যতের কোনও সংস্করণ আপনার প্রকৃত বিল্টিন হিসাবে বেছে নেওয়া নামটি ব্যবহার করা শুরু করে তবে তা ধ্বংসস্তূপে ক্ষতিগ্রস্থ হওয়ার পক্ষেও সংবেদনশীল।
intuited

4
আমদানি করা মডিউলগুলির সাথে ডিবি সংযোগ ভাগ করার মতো জিনিসগুলির জন্য এটি একটি দুর্দান্ত সমাধান। স্যানিটি পরীক্ষা হিসাবে, আমি নিশ্চিত হয়েছি যে আমদানি করা মডিউলটি জোর দিয়েছিল hasattr(__builtin__, "foo")
মাইক এলিস

4
যে কেউ এই উত্তরটি পড়ছেন তাদের জন্য: না ! কর! এই ! সত্যি, না।
ব্রুনো desthuilliers

161

আপনার যদি কোনও বিশ্বব্যাপী ক্রস-মডিউল ভেরিয়েবলের প্রয়োজন হয় তবে কেবল সাধারণ গ্লোবাল মডিউল-স্তরের ভেরিয়েবল যথেষ্ট।

a.py:

var = 1

b.py:

import a
print a.var
import c
print a.var

c.py:

import a
a.var = 2

টেস্ট:

$ python b.py
# -> 1 2

রিয়েল-ওয়ার্ল্ড উদাহরণ: জ্যাঙ্গোর গ্লোবাল_সেটিংস.পি (যদিও জ্যাঙ্গো অ্যাপ্লিকেশন সেটিংস অবজেক্টটি আমদানি করে ব্যবহার করা হয় django.conf.settings)।


3
আরও ভাল কারণ এটি সম্ভাব্য নেমস্পেস বিরোধগুলি এড়িয়ে চলে
বিজিডাব্লু

এই ক্ষেত্রে আপনি যে মডিউলটি আমদানি করছেন তা যদি a.pyথাকে main()? এটা কোন ব্যাপার?
sedh

4
@ সিদেহ: না যদি এপিও স্ক্রিপ্ট হিসাবে চালিত হয় তবে if __name__=="__main__"আমদানিতে অপ্রত্যাশিত কোডটি চালনা এড়াতে এতে প্রহরী ব্যবহার করুন।
jfs

6
বাস্তব বিশ্বে আপনাকে এই সমাধানটি সম্পর্কে কিছুটা সতর্ক থাকতে হবে। যদি কোনও প্রোগ্রামার 'আমদানি ভেরি' ব্যবহার করে আপনার 'গ্লোবাল' ভেরিয়েবলটি তুলেন, (সিপিপিতে এই প্রকরণটি চেষ্টা করুন) তারা আমদানির সময় ভেরিয়েবলের একটি অনুলিপি পান।
পল হিপ্প

1
@ পলহ্লিপ: ভুল (ইঙ্গিত: id()পরিচয় যাচাই করতে ব্যবহার করুন )
jfs

25

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

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

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

নোট করুন যে জিনিসগুলিকে কিছুটা আরও দৃly়ভাবে নিয়ন্ত্রণ করতে আপনার মডিউলগুলির বিভিন্ন সাবসেট দ্বারা ভাগ করা এমন একাধিক গ্লোবাল মডিউলও থাকতে পারে। আমি আমার গ্লোবাল মডিউলগুলির জন্য সংক্ষিপ্ত নামগুলি ব্যবহার করার কারণটি হ'ল কোডটির সংঘটনগুলির সাথে অত্যধিক বিশৃঙ্খলা এড়ানো। কেবলমাত্র একটি সামান্য অভিজ্ঞতা থাকলে তারা কেবলমাত্র 1 বা 2 টি অক্ষরের সাথে যথেষ্ট পরিমাণে স্মৃতিচারণে পরিণত হয়।

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


7
এই আকর্ষণীয় পর্যবেক্ষণটি আমার সমস্যার সমাধান করেছে: 'আমি "জি ইম্পোর্ট ভেরি" ব্যবহার করি না, কারণ এটি কেবলমাত্র স্থানীয় ভেরিয়েবলের ফলস্বরূপ যা কেবলমাত্র আমদানির সময় জি থেকে শুরু করা হয়েছিল' ' এটা মনে করা যুক্তিসঙ্গত বলে মনে হয় যে "থেকে..ইম্পোর্ট" "আমদানি" হিসাবে একই তবে এটি সত্য নয়।
কর্টিস ইয়ালাপ

24

একটি মডিউল সংজ্ঞায়িত করুন (এটিকে "গ্লোবালবাজ" বলুন) এবং এর ভিতরে ভেরিয়েবলগুলি সংজ্ঞায়িত করুন। এই "সিউডোগ্লোবাল" ব্যবহার করে সমস্ত মডিউল "গ্লোবালবাজ" মডিউল আমদানি করা উচিত এবং "গ্লোবালবাজ.ভার_নাম" ব্যবহার করে এটিকে উল্লেখ করা উচিত

পরিবর্তনের স্থান নির্বিশেষে এটি কাজ করে, আপনি আমদানির আগে বা পরে পরিবর্তনশীল পরিবর্তন করতে পারবেন। আমদানি করা মডিউল সর্বশেষ মানটি ব্যবহার করবে। (আমি এটি খেলনার উদাহরণে পরীক্ষা করেছি)

স্পষ্টকরণের জন্য, গ্লোবালবাজ.পি.এর মতো দেখতে:

var_name = "my_useful_string"

9

আপনি অনোথর করতে একটি মডিউল গ্লোবাল পাস করতে পারেন:

মডিউল এ:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

মডিউল বিতে:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

7

গ্লোবাল ভেরিয়েবলগুলি সাধারণত একটি খারাপ ধারণা, তবে আপনি এইগুলি অর্পণ করে এটি করতে পারেন __builtins__:

__builtins__.foo = 'something'
print foo

এছাড়াও, মডিউলগুলি নিজেরাই চলক যা আপনি যে কোনও মডিউল থেকে অ্যাক্সেস করতে পারেন। সুতরাং আপনি যদি একটি মডিউল নামক সংজ্ঞা দেন my_globals.py:

# my_globals.py
foo = 'something'

তারপরে আপনি এটিকে যে কোনও জায়গা থেকেও ব্যবহার করতে পারেন:

import my_globals
print my_globals.foo

পরিবর্তনের পরিবর্তে মডিউলগুলি ব্যবহার __builtins__করা সাধারণত এই ধরণের গ্লোবালগুলি করার একটি ক্লিনার উপায়।


3
__builtins__সিপিথন বিশেষত্ব, আপনার সত্যই এটি ব্যবহার করা উচিত নয় - গ্রহণযোগ্য উত্তর শো হিসাবে ভাল ব্যবহার __builtin__(বা builtinsপাইথন 3 এ)
টোবিয়াস কেইনজলার

5

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

এটি কোনও কাজ করার জন্য সাধারণত কোনও দুর্দান্ত উপায় নয় - গ্লোবালগুলি খুব কমই ব্যবহার করা হয় - তবে আমি মনে করি এটি এটি করার সবচেয়ে পরিষ্কার উপায়।


3

আমি একটি উত্তর পোস্ট করতে চেয়েছিলাম যে এমন একটি কেস রয়েছে যেখানে ভেরিয়েবলটি খুঁজে পাওয়া যাবে না।

চক্রীয় আমদানিগুলি মডিউলটির আচরণ ভেঙে দিতে পারে।

উদাহরণ স্বরূপ:

first.py

import second
var = 1

second.py

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

import first

এটি উদাহরণস্বরূপ এটি সুস্পষ্ট হওয়া উচিত, তবে একটি বৃহত কোড-বেসে এটি সত্যিই বিভ্রান্তিকর হতে পারে।


1

এটি __builtin__নামের জায়গার পরিবর্তনের মতো শোনাচ্ছে । এটি করতে:

import __builtin__
__builtin__.foo = 'some-value'

__builtins__সরাসরি ব্যবহার করবেন না (অতিরিক্ত "গুলি" লক্ষ্য করুন) - সম্ভবত এটি অভিধান বা মডিউল হতে পারে। এটি নির্দেশ করার জন্য ধন্যবাদ,, আরও এখানে পাওয়া যাবে

এখন fooসর্বত্র ব্যবহারের জন্য উপলব্ধ।

আমি সাধারণত এটি করার প্রস্তাব দিই না, তবে এটির ব্যবহার প্রোগ্রামার পর্যন্ত।

এটিকে নির্ধারণ করা অবশ্যই উপরের কাজ হিসাবে সম্পন্ন foo = 'some-other-value'হবে , কেবল সেটিংস কেবলমাত্র বর্তমান নামস্থানে সেট করবে।


1
আমার মনে আছে ( কমপ্লেং.প্যাথথন থেকে) যে সরাসরি বিল্টিনগুলি ব্যবহার করা এড়ানো উচিত; পরিবর্তে, আমদানি builtin এবং ব্যবহারের যে, যেমন কার্ট Hagenlocher সুপারিশ করেছে।
tzot

1

আমি এটি দুটি অন্তর্নির্মিত আদিম ফাংশনগুলির জন্য ব্যবহার করি যা আমার মনে হয়েছিল যে সত্যই অনুপস্থিত ছিল। একটি উদাহরণ হ'ল ফাইন্ড ফাংশন যা ফিল্টার, মানচিত্র, হ্রাস হিসাবে একই রকম শব্দার্থক শব্দ ব্যবহার করে।

def builtin_find(f, x, d=None):
    for i in x:
        if f(i):
            return i
    return d

import __builtin__
__builtin__.find = builtin_find

এটি একবার চালানো হয়ে গেলে (উদাহরণস্বরূপ, আপনার প্রবেশের পয়েন্টের কাছাকাছি আমদানি করে) আপনার সমস্ত মডিউলগুলি () ব্যবহার করতে পারেন যেমন স্পষ্টতই এটি অন্তর্নির্মিত ছিল।

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

দ্রষ্টব্য: আপনি অবশ্যই এটি ফিল্টার এবং শূন্য দৈর্ঘ্যের জন্য পরীক্ষা করার জন্য অন্য একটি লাইন দিয়ে বা এক ধরণের অদ্ভুত লাইনের মাধ্যমে হ্রাস করতে পারেন, তবে আমি সর্বদা অনুভব করেছি যে এটি অদ্ভুত was


1

আমি একটি অভিধান ব্যবহার করে ক্রস-মডিউল পরিবর্তনযোগ্য (বা পরিবর্তনযোগ্য ) ভেরিয়েবলগুলি অর্জন করতে পারি :

# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60

# in myapp.mod1
from myapp import Timeouts

def wait_app_up(project_name, port):
    # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
    # ...

# in myapp.test.test_mod1
from myapp import Timeouts

def test_wait_app_up_fail(self):
    timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
    Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
    with self.assertRaises(hlp.TimeoutException) as cm:
        wait_app_up(PROJECT_NAME, PROJECT_PORT)
    self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
    Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak

আরম্ভ করার সময় test_wait_app_up_fail, আসল সময়সীমাটি 3 সেকেন্ড।


1

ভেবেছিলাম ভেরিয়েবলের মানগুলি পাস করার জন্য গ্লোবাল / মডিউল নেমস্পেসের পরিবর্তে ক্লাস নেমস্পেস ব্যবহার করে বৈশ্বিক ভেরিয়েবলগুলি ব্যবহারের কিছু অসুবিধা (যেমন উদাহরণস্বরূপ http://wiki.c2.com/?GlobalVariablesAreBad ) এড়ানো সম্ভব হবে কিনা ? । নিম্নলিখিত কোডটি নির্দেশ করে যে দুটি পদ্ধতি মূলত অভিন্ন। ক্লাসের নেমস্পেসগুলি নীচে বর্ণিত হিসাবে ব্যবহার করার ক্ষেত্রে সামান্য সুবিধা রয়েছে।

নিম্নলিখিত কোড টুকরাগুলি আরও দেখায় যে বৈশিষ্ট্য বা ভেরিয়েবলগুলি গ্লোবাল / মডিউল উভয় নেমস্পেস এবং শ্রেণীর নেমস্পেসে গতিশীলভাবে তৈরি এবং মোছা হতে পারে।

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

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

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

এই মডিউলটি প্রাচীর আমদানি করে এবং একটি একক ফাংশন sourcefnসংজ্ঞায়িত করে যা একটি বার্তা সংজ্ঞায়িত করে এবং দুটি পৃথক প্রক্রিয়া দ্বারা এটিকে নির্গত করে, একটি গ্লোবালের মাধ্যমে এবং একটি রাউটার ফাংশনের মাধ্যমে। লক্ষ্য করুন ভেরিয়েবল wall.msgএবং wall.router.messageএখানে তাদের নিজ নিজ নামব্যবধান প্রথমবারের সংজ্ঞায়িত করা হয়।

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

এই মডিউলটি এমন একটি ফাংশন সংজ্ঞায়িত করে destfnযা উত্স দ্বারা প্রেরিত বার্তাগুলি গ্রহণ করতে দুটি পৃথক প্রক্রিয়া ব্যবহার করে। এটি সম্ভাব্যতার জন্য অনুমতি দেয় যে চলক 'msg' উপস্থিত থাকতে পারে না। destfnভেরিয়েবলগুলি প্রদর্শিত হওয়ার পরে তা মুছে দেয়।

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

এই মডিউলটি পূর্বনির্ধারিত ফাংশনগুলিকে ক্রমানুসারে কল করে। প্রথম কল করার পর dest.destfnভেরিয়েবল wall.msgএবং wall.router.msgএখন আর বিদ্যমান নেই।

প্রোগ্রাম থেকে আউটপুট হয়:

গ্লোবাল: হ্যালো ওয়ার্ল্ড!
রাউটার: হ্যালো ওয়ার্ল্ড!
গ্লোবাল: কোনও বার্তা
রাউটার: কোনও বার্তা নেই

উপরের কোডের টুকরোগুলি দেখায় যে মডিউল / গ্লোবাল এবং শ্রেণি / শ্রেণি পরিবর্তনশীল প্রক্রিয়াগুলি মূলত অভিন্ন।

যদি প্রচুর ভেরিয়েবলগুলি ভাগ করে নেওয়া হয় তবে বেশ কয়েকটি ওয়াল-টাইপ মডিউল, যেমন: ওয়াল 1, ওয়াল 2 ইত্যাদি ব্যবহার করে বা একক ফাইলে বেশ কয়েকটি রাউটার-ধরণের ক্লাস নির্ধারণ করে নেমস্পেস দূষণ পরিচালনা করা যায় can পরবর্তীটি সামান্য পরিপাটিযুক্ত, সুতরাং সম্ভবত শ্রেণি-পরিবর্তনশীল প্রক্রিয়াটি ব্যবহারের জন্য একটি প্রান্তিক সুবিধা উপস্থাপন করে।

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