python - কিভাবে পাইথন মডিউল-প্রশস্ত ভেরিয়েবল তৈরি করতে?




variables singleton (4)

এই প্রশ্নটি ইতিমধ্যে একটি উত্তর আছে:

একটি মডিউল ভিতরে একটি গ্লোবাল ভেরিয়েবল সেট আপ করার একটি উপায় আছে কি? যখন আমি এটি নিম্নরূপ প্রদর্শিত হিসাবে সবচেয়ে স্পষ্ট উপায় করার চেষ্টা করেছি, পাইথন ইন্টারপ্রেটার বলেছেন পরিবর্তনশীল __DBNAME__ বিদ্যমান ছিল না।

...
__DBNAME__ = None

def initDB(name):
    if not __DBNAME__:
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
...

এবং একটি পৃথক ফাইল মডিউল আমদানি করার পরে

...
import mymodule
mymodule.initDB('mydb.sqlite')
...

এবং ট্রেসব্যাকটি ছিল: UnboundLocalError: local variable '__DBNAME__' referenced before assignment

কোন ধারনা? আমি এই সহকর্মীর সুপারিশ অনুযায়ী একটি মডিউল ব্যবহার করে একটি সিঙ্গলটন সেট আপ করার চেষ্টা করছি।


আপনি একটি সূক্ষ্ম quirk জন্য পতিত হয়। আপনি পাইথন ফাংশনের ভিতরে মডিউল স্তর স্তর পরিবর্তন করতে পারবেন না। আমি এই দুর্ঘটনা দ্বারা একটি ফাংশন ভিতরে মানুষ পুনরায় নিয়োগ স্টাফ থামাতে মনে হয়।

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

আপনি করতে পারেন:

__DB_NAME__ = None

def func():
    if __DB_NAME__:
        connect(__DB_NAME__)
    else:
        connect(Default_value)

কিন্তু আপনি ফাংশনের ভিতরে __DB_NAME__ পুনরায় বরাদ্দ করতে পারবেন না।

এক কাজকর্ম

__DB_NAME__ = [None]

def func():
    if __DB_NAME__[0]:
        connect(__DB_NAME__[0])
    else:
        __DB_NAME__[0] = Default_value

মনে রাখবেন, আমি __DB_NAME__ পুনরায় বরাদ্দ করছি না, আমি কেবল তার বিষয়বস্তু সংশোধন করছি।


এই জন্য, আপনি পরিবর্তনশীল ঘোষণা গ্লোবাল হিসাবে প্রয়োজন। যাইহোক, module_name.var_name ব্যবহার করে একটি বিশ্বব্যাপী পরিবর্তনশীল মডিউল থেকে অ্যাক্সেসযোগ্য। আপনার মডিউল প্রথম লাইন হিসাবে এটি যোগ করুন:

global __DBNAME__

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

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

পাইলন 1.3.1 পাইথন 2.7 এর অধীনে আপনি বিশ্বব্যাপী বরাদ্দ না করলে গ্লোবাল ব্যবহার করে না।

module_var = '/dev/hello'

def readonly_access():
    connect(module_var)

def readwrite_access():
    global module_var
    module_var = '/dev/hello2'
    connect(module_var)

মডিউলের উপর তাদের ব্যাখ্যা অ্যাক্সেস করে মডিউল স্তরের ভেরিয়েবলগুলিতে স্পষ্ট অ্যাক্সেস

সংক্ষেপে: এখানে বর্ণিত কৌশলটি steveha এর উত্তরের মতোই , ব্যতীত , কোনও কৃত্রিম সহায়ক বস্তু স্পষ্টভাবে স্কোপ ভেরিয়েবলগুলির জন্য তৈরি করা হয় না। পরিবর্তে মডিউল অবজেক্ট নিজেই একটি পরিবর্তনশীল পয়েন্টার দেওয়া হয়, এবং সেইজন্য সর্বত্র থেকে অ্যাক্সেস উপর স্পষ্ট scoping উপলব্ধ করা হয়। (স্থানীয় ফাংশন সুযোগ বরাদ্দ মত)

বর্তমান উদাহরণের পরিবর্তে বর্তমান মডিউলের জন্য নিজের মত মনে করুন!

# db.py
import sys

# this is a pointer to the module object instance itself.
this = sys.modules[__name__]

# we can explicitly make assignments on it 
this.db_name = None

def initialize_db(name):
    if (this.db_name is None):
        # also in local function scope. no scope specifier like global is needed
        this.db_name = name
        # also the name remains free for local use
        db_name = "Locally scoped db_name variable. Doesn't do anything here."
    else:
        msg = "Database is already initialized to {0}."
        raise RuntimeError(msg.format(this.db_name))

মডিউলগুলি ক্যাশে করা হয় এবং সেইজন্য শুধুমাত্র একবার আমদানি করা হয় , আপনি যতটা ক্লায়েন্টের উপর প্রায়শই ক্লায়েন্ট আমদানি করতে পারেন, একই সাথে সার্বজনীন অবস্থাটি ম্যানিপুলিউটিং করতে পারেন:

# client_a.py
import db

db.initialize_db('mongo')
# client_b.py
import db

if (db.db_name == 'mongo'):
    db.db_name = None  # this is the preferred way of usage, as it updates the value for all clients, because they access the same reference from the same module object
# client_c.py
from db import db_name
# be careful when importing like this, as a new reference "db_name" will
# be created in the module namespace of client_c, which points to the value 
# that "db.db_name" has at import time of "client_c".

if (db_name == 'mongo'):  # checking is fine if "db.db_name" doesn't change
    db_name = None  # be careful, because this only assigns the reference client_c.db_name to a new value, but leaves db.db_name pointing to its current value.

অতিরিক্ত বোনাস হিসাবে আমি এটি সম্পূর্ণরূপে পাইথনিক খুঁজে পেয়েছি কারণ এটি স্পষ্টভাবে পাইথন নীতিমালাটি স্পষ্টভাবে ফিট করে তুলনায় ভাল





scope