পাইথনে সিঙ্গলটন তৈরি করা হচ্ছে


945

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

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

সেরা পদ্ধতি:


পদ্ধতি 1: একটি সাজসজ্জা

def singleton(class_):
    instances = {}
    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]
    return getinstance

@singleton
class MyClass(BaseClass):
    pass

পেশাদাররা

  • সজ্জাকারীরা এমন এক উপায়ে সংযোজিত যা প্রায়শই একাধিক উত্তরাধিকারের চেয়ে স্বজ্ঞাত।

কনস

  • মাইক্লাস () ব্যবহার করে তৈরি বস্তুগুলি সত্য সিঙ্গলটন অবজেক্ট হতে পারে, মাইক্লাস নিজেই একটি ফাংশন, কোনও শ্রেণি নয়, সুতরাং আপনি এটি থেকে শ্রেণি পদ্ধতিতে কল করতে পারবেন না। এছাড়াও m = MyClass(); n = MyClass(); o = type(n)();তারপরm == n && m != o && n != o

পদ্ধতি 2: একটি বেস শ্রেণি

class Singleton(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass

পেশাদাররা

  • এটি একটি সত্য শ্রেণি

কনস

  • একাধিক উত্তরাধিকার - ughু! __new__দ্বিতীয় বেস শ্রেণীর উত্তরাধিকারের সময় ওভাররাইট করা যেতে পারে? একজনকে প্রয়োজনের চেয়ে বেশি চিন্তা করতে হবে।

পদ্ধতি 3: একটি মেটাক্লাস

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

#Python2
class MyClass(BaseClass):
    __metaclass__ = Singleton

#Python3
class MyClass(BaseClass, metaclass=Singleton):
    pass

পেশাদাররা

  • এটি একটি সত্য শ্রেণি
  • স্ব-যাদুকরভাবে উত্তরাধিকারকে কভার করে
  • __metaclass__এর সঠিক উদ্দেশ্যে ব্যবহার করে (এবং আমাকে এটি সম্পর্কে সচেতন করেছেন)

কনস

  • কোন আছে?

পদ্ধতি 4: সাজসজ্জা একই নামে একটি ক্লাস ফিরছে

def singleton(class_):
    class class_w(class_):
        _instance = None
        def __new__(class_, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w,
                                    class_).__new__(class_,
                                                    *args,
                                                    **kwargs)
                class_w._instance._sealed = False
            return class_w._instance
        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True
    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(BaseClass):
    pass

পেশাদাররা

  • এটি একটি সত্য শ্রেণি
  • স্ব-যাদুকরভাবে উত্তরাধিকারকে কভার করে

কনস

  • প্রতিটি নতুন ক্লাস তৈরি করার জন্য কি ওভারহেড নেই? এখানে আমরা প্রতিটি শ্রেণীর জন্য দুটি ক্লাস তৈরি করছি যা আমরা একটি সিঙ্গলটন তৈরি করতে চাই। যদিও এটি আমার ক্ষেত্রে ঠিক আছে, আমি আশঙ্কা করছি যে এটি স্কেল নাও হতে পারে। অবশ্যই এই বিতর্কটি খুব বড় হওয়া উচিত যে এই ধরণটি স্কেল করা খুব সহজ ...
  • _sealedবৈশিষ্ট্যের বিন্দু কি
  • বেস ক্লাসে একই নামের পদ্ধতিগুলি কল করতে পারে না super()কারণ তারা পুনরাবৃত্তি করবে। এর অর্থ আপনি কাস্টমাইজ করতে পারবেন না __new__এবং এমন একটি শ্রেণীর সাবক্লাস করতে পারবেন না যাতে আপনাকে কল করতে হবে __init__

পদ্ধতি 5: একটি মডিউল

একটি মডিউল ফাইল singleton.py

পেশাদাররা

  • সহজ জটিল চেয়ে ভাল

কনস


12
আরও তিনটি কৌশল: পরিবর্তে একটি মডিউল ব্যবহার করুন (প্রায়শই - সাধারণত, আমি মনে করি - এটি পাইথনের জন্য আরও উপযুক্ত প্যাটার্ন তবে এটি আপনি এটি দিয়ে যা করছেন তার উপর এটি কিছুটা নির্ভর করে); একক উদাহরণ তৈরি করুন এবং পরিবর্তে এটির সাথে ডিল করুন ( foo.xবা আপনি যদি Foo.xপরিবর্তে জেদ করেন Foo().x); শ্রেণীর বৈশিষ্ট্য এবং স্থির / শ্রেণি পদ্ধতি ( Foo.x) ব্যবহার করুন।
ক্রিস মরগান

10
@ ক্রিসমোরগান: আপনি যদি কেবল ক্লাস / স্ট্যাটিক পদ্ধতি ব্যবহার করতে চলেছেন তবে সত্যই কোনও ক্লাস বানাবেন না।
বিড়াল প্লাস প্লাস

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

14
@ বিগগল: সিলেটলেটনগুলি পাইথোনিক নয় , আপনি সেগুলি কীভাবে প্রয়োগ করেন তা বিবেচনাধীন। এগুলি সেরা ত্রুটিযুক্ত ডিজাইনের লক্ষণ।
ক্যাট প্লাস প্লাস

8
অ্যান্টি-সিগলেটন সেন্টিমেন্টটি সবচেয়ে খারাপ সময়ে কার্গো কাল্ট প্রোগ্রামিং। লোকেরা শ্রবণকারীদের সাথে একই (কিছু লোক আসলে পড়তে বিরক্ত হয়) "গোটো বিবৃতি ক্ষতিকারক হিসাবে বিবেচিত" এবং মনে হয় গোটোস প্রসঙ্গ নির্বিশেষে খারাপ কোডের একটি চিহ্ন।
হিজাজমান

উত্তর:


657

একটি মেটাক্লাস ব্যবহার করুন

আমি পদ্ধতি # 2 সুপারিশ করব , তবে আপনি বেস ক্লাসের চেয়ে মেটাক্লাস ব্যবহার করা ভাল । এখানে একটি নমুনা বাস্তবায়ন:

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Logger(object):
    __metaclass__ = Singleton

বা পাইথন 3 এ

class Logger(metaclass=Singleton):
    pass

__init__ক্লাসটি ডাকা হলে প্রতিবার চালাতে চাইলে অ্যাড করুন

        else:
            cls._instances[cls].__init__(*args, **kwargs)

থেকে ifবিবৃতি Singleton.__call__

মেটাক্লাস সম্পর্কে কয়েকটি শব্দ। একটি মেটাক্লাস একটি শ্রেণীর শ্রেণি ; অর্থাৎ, একটি বর্গ তার মেটাক্লাসের উদাহরণ । পাইথনের সাথে আপনি কোনও বস্তুর মেটাক্লাস খুঁজে পান type(obj)। সাধারন নতুন স্টাইলের শ্রেণীর ধরনের typeLoggerউপরের কোডটিতে টাইপ হবে class 'your_module.Singleton', ঠিক যেমন (কেবল) উদাহরণ Loggerটাইপ হবে class 'your_module.Logger'। যখন আপনার সাথে এটির কল Logger(), পাইথন প্রথম ক্লাসের অধীনে একটি ক্লাস জিজ্ঞেস Logger, Singleton, কি করতে হবে, যার ফলে উদাহরণস্বরূপ সৃষ্টি প্রাক empted হবে। এই প্রক্রিয়া পাইথন একটি বর্গ কি কল করে না জিজ্ঞাসা হিসাবে একই __getattr__যখন আপনি করছেন তা এমন সব গুণাবলীর এক রেফারেন্স myclass.attribute

একটি মেটাক্লাস মূলত সিদ্ধান্ত নেয় যে কোনও শ্রেণীর সংজ্ঞা কী এবং কীভাবে সেই সংজ্ঞাটি প্রয়োগ করা যায় implement উদাহরণস্বরূপ দেখুন http://code.activestate.com/recines/498149/ , যা মূলত structমেটাক্লাস ব্যবহার করে পাইথনে সি-স্টাইল গুলি পুনরায় তৈরি করে। থ্রেডটি मेटाটাক্লাসগুলির জন্য কিছু (কংক্রিট) ব্যবহারের ক্ষেত্রে কী কী? এছাড়াও কিছু উদাহরণ সরবরাহ করে, তারা সাধারণত ঘোষিত প্রোগ্রামিংয়ের সাথে সম্পর্কিত বলে মনে হয়, বিশেষত ওআরএম-তে ব্যবহৃত হিসাবে।

এই পরিস্থিতিতে আপনি যদি আপনার পদ্ধতি # 2 ব্যবহার করেন এবং একটি সাবক্লাস কোনও __new__পদ্ধতি সংজ্ঞায়িত করে তবে আপনি যতবার কল করবেন ততক্ষণে এটি কার্যকর করা হবে SubClassOfSingleton()- কারণ সঞ্চিত উদাহরণটি ফিরে আসে এমন পদ্ধতিতে কল করার জন্য এটি দায়বদ্ধ। একটি মেটাক্লাসের সাহায্যে এটি কেবল একবার কল করা হবে , যখন একমাত্র উদাহরণ তৈরি করা হবে। ক্লাসটি বলতে কী বোঝায় তা আপনি কাস্টমাইজ করতে চান , যা এটি টাইপ দ্বারা স্থির হয়।

সাধারণভাবে, একটি সিঙ্গলটন বাস্তবায়নের জন্য একটি মেটাক্লাস ব্যবহার করা বোধগম্য । একটি সিঙ্গলটন বিশেষ কারণ শুধুমাত্র একবার তৈরি করা হয় , এবং একটি ক্লাস তৈরির পদ্ধতিটি মেটাকগ্লাসকেই আপনি অনুকূলিত করেন । আপনি যদি অন্যভাবে সিঙ্গলটন শ্রেণির সংজ্ঞাটি কাস্টমাইজ করতে চান তবে একটি মেটাক্লাস ব্যবহার আপনাকে আরও নিয়ন্ত্রণ দেয় ।

আপনার সিঙ্গেলটনের একাধিক উত্তরাধিকারের প্রয়োজন হবে না (কারণ মেটাক্লাস একটি বেস শ্রেণি নয়) তবে একাধিক উত্তরাধিকার ব্যবহার করে তৈরি শ্রেণীর সাবক্লাসগুলির জন্য আপনাকে নিশ্চিত করতে হবে যে মেটাক্লাসের সাথে সিঙ্গেলটন শ্রেণি প্রথম / বামতম এক যা পুনরায় সংজ্ঞায়িত করে __call__এটি খুব সমস্যা হওয়ার সম্ভাবনা নেই। উদাহরণস্বরূপ ডক উদাহরণস্বরূপ এর নামস্থানে নেই তাই এটি দুর্ঘটনাক্রমে এটি ওভাররাইট হবে না।

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

পাইথন 2 এবং 3 সামঞ্জস্যপূর্ণ সংস্করণ

পাইথন 2 এবং 3 উভয় ক্ষেত্রে কাজ করে এমন কিছু লেখার জন্য আরও জটিল জটিল স্কিম ব্যবহার করা দরকার। যেহেতু মেটাক্লাসগুলি সাধারণত ধরণের সাবক্লাস হয় তাই এটি রানাকালীন typeসময়ে একটি মধ্যস্থতাকার বেস ক্লাসটিকে তার মেটাক্লাস হিসাবে গতিশীলভাবে তৈরি করতে এবং তারপরে পাবলিক বেস শ্রেণির বেসক্লাস হিসাবে ব্যবহার করা সম্ভব Singleton। এটি করার চেয়ে ব্যাখ্যা করা আরও শক্ত, পরবর্তী চিত্রিত:

# works in Python 2 & 3
class _Singleton(type):
    """ A metaclass that creates a Singleton base class when called. """
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Singleton(_Singleton('SingletonMeta', (object,), {})): pass

class Logger(Singleton):
    pass

এই পদ্ধতির একটি হাস্যকর দিক হ'ল এটি একটি মেটাক্লাস বাস্তবায়নের জন্য সাবক্লাসিং ব্যবহার করছে। একটি সম্ভাব্য সুবিধা হ'ল শুদ্ধ মেটাক্লাসের বিপরীতে isinstance(inst, Singleton)ফিরে আসবে True

সংশোধণী

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

class Singleton(object):
  _instances = {}
  def __new__(class_, *args, **kwargs):
    if class_ not in class_._instances:
        class_._instances[class_] = super(Singleton, class_).__new__(class_, *args, **kwargs)
    return class_._instances[class_]

class MyClass(Singleton):
  pass

c = MyClass()

সাজসজ্জা এক ক্লাস রিটার্নিং

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

ক্লাসটি হ'ল মূল সমস্যাটি হ'ল এটি নিজস্ব বেস ক্লাস। প্রথমত, ক্লাসটি প্রায় একইরকম বর্গের একই নাম যা কেবল তার __class__বৈশিষ্ট্যে উপস্থিত রয়েছে তার একটি সাবক্লাস হওয়া কি অদ্ভুত নয় ? এটাও এর মানে হল যে আপনি সংজ্ঞায়িত করতে পারবে না কোনো পদ্ধতি যে তাদের বেস বর্গ উপর একই নামের পদ্ধতি কল সঙ্গে super(), কারণ তারা recurse হবে। এর অর্থ আপনার ক্লাসটি অনুকূলিতকরণ করতে পারে না __new__, এবং যে কোনও ক্লাসের প্রয়োজন __init__তাদের থেকে নেওয়া যাবে না ive

সিঙ্গলটন প্যাটার্নটি কখন ব্যবহার করবেন

আপনার ব্যবহারের ক্ষেত্রে সিঙ্গলটন ব্যবহার করতে চাওয়ার অন্যতম সেরা উদাহরণ । আপনি একটি মন্তব্যে বলছেন "আমার কাছে লগিং সর্বদা সিঙ্গলটনের প্রাকৃতিক প্রার্থী বলে মনে হয়।" আপনি একেবারে ঠিক বলেছেন

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

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

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

Http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html- এর একটি উদ্ধৃতি এখানে রয়েছে :

এখন, এখানে এক ধরণের সিঙ্গল আছে যা ঠিক আছে। এটি এমন একক সিঙ্গলটন যেখানে পৌঁছনযোগ্য সমস্ত বস্তু অপরিবর্তনীয়। সমস্ত বস্তু যদি অবিচল থাকে তবে সিঙ্গেলনের কোনও বৈশ্বিক অবস্থা নেই, কারণ সবকিছু অবিচ্ছিন্ন। তবে এই ধরণের সিঙ্গলটনকে পরিবর্তনীয় স্থানে রূপান্তর করা এত সহজ, এটি খুব পিচ্ছিল opeাল। অতএব, আমি এই সিঙ্গলটনের বিরুদ্ধেও আছি, এগুলি খারাপ হওয়ার কারণে নয়, কারণ খারাপ হওয়া তাদের পক্ষে খুব সহজ। (পার্শ্ব দ্রষ্টব্য হিসাবে জাভা গণনাটি কেবল এই ধরণের সিলেটলেট let

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


5
না, একা কখনও ভাল হয় না। লগিং বিশ্বব্যাপী হওয়ার জন্য ভাল প্রার্থী হতে পারে (তারা যতটা ভয়ঙ্কর) তবে অবশ্যই সিঙ্গলটন নয়।
ক্যাট প্লাস প্লাস

11
googletesting.blogspot.com/2008/08/... । এটি সাধারনত অ্যান্টি-সিঙ্গেলটন (সঙ্গত কারণে) তবে আপনি যদি যত্নশীল হন তবে কেন পার্শ্বপ্রতিক্রিয়াবিহীন অপরিবর্তনীয় সিঙ্গললেট এবং সিলেটলেটগুলির একই সমস্যা হয় না তার একটি ভাল ব্যাখ্যা রয়েছে। আমি আমার পোস্টের শেষে এটি কিছুটা উদ্ধৃত করব।
অগফ

4
সিলেটলেটসের সাথে আমার সমস্যা হ'ল "কেবলমাত্র একটি উদাহরণ" এর বোকামি ise এটি এবং টন থ্রেড সুরক্ষা সমস্যা। এবং নির্ভরতা গোপন। গ্লোবালগুলি খারাপ, এবং সিলেটলেটগুলি আরও সমস্যা সহ কেবল গ্লোবাল।
ক্যাট প্লাস প্লাস

4
@ গুগল সিলেটলেটের জন্য খুব ভাল ব্যবহার রয়েছে। হার্ডওয়্যার মডিউলগুলির অলস ইনস্ট্যান্টেশন (বিশেষত একক থ্রেডেড অ্যাপ্লিকেশনগুলিতে) এর মধ্যে একটি (তবে থ্রেড নিরাপদ সিঙ্গলেটগুলিও বিদ্যমান)।
পল মানতা

3
@Alcott __new__একটি ক্লাসের অধীনে একটি ক্লাস যখন হয় বর্গ নতুন - যখন এটি সংজ্ঞায়িত, তাই না যখন উদাহরণস্বরূপ নতুন হতে হবে। ক্লাসকে কল করা ( MyClass()) ক্লাসের সংজ্ঞা নয়, আপনি যে কাজটি ওভাররাইড করতে চান তা। পাইথন কীভাবে কাজ করে তা যদি আপনি সত্যিই বুঝতে চান তবে আপনি যা করতে পারেন তা হ'ল ডকস.পিথথন.আর . / রেফারেন্স / ডেডামোডেলHtml পড়ুন । মেটাক্লাসগুলির উপর একটি ভাল রেফারেন্স হ'ল eli.thegreenplace.net/2011/08/14/python-metaclass-by- উদাহরণ । সিঙ্গেলটনের উপর একটি ভাল নিবন্ধটি এই উত্তরটিতে আমি সংযুক্ত গুগল ব্লগের সিরিজ।
agf

91
class Foo(object):
     pass

some_global_variable = Foo()

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


14
আপনি কেন "সিলেটলেট ব্যবহার করবেন না" বলেছিলেন? যে কোনো কারণে?
অ্যালকোট

3
যদি সিঙ্গলটনকে পিক করতে হয় তবে এটি কাজ করবে না। আপনি যে উদাহরণটি দিয়েছেন তা ব্যবহার করে:s = some_global_variable; str = pickle.dumps(s); s1 = pickle.loads(str); print s is s1; # False
ডিভাইডবাইজারো

4
@ ডিভিডিবিজেরো: isপয়েন্টার সমতার জন্য অপারেটর পরীক্ষা করে। আমি বরং বিস্মিত হব --- এটিকে বাগ বলার বিন্দুতে --- যদি pickle.loadsসদ্য তৈরি হওয়া কোনও রেফারেন্সের চেয়ে প্রাক-বিদ্যমান বস্তুর কোনও রেফারেন্স ফেরত দেয় returned সুতরাং, s is s1সিঙ্গেলন হিসাবে মডিউলগুলি ব্যবহারের উপযুক্ততার বিষয়ে আপনাকে কিছু না বলে কিনা তা পরীক্ষা করে।
জোনাস কলকার

1
@ JonasKölker pickle.loads()দৃষ্টান্ত যে কাজ করে ইতিমধ্যে, যেমন boolএবং NoneTypepickle.loads(pickle.dumps(False)) is FalseফলনTrue
ড্যান পাসারো

2
@ লিও-দ্য ম্যানিক: ফেয়ার পয়েন্ট; তবে, যে পাইথন শুধু একটি পার্শ্ব প্রতিক্রিয়া বস্তু interning এর True, Falseএবং None, এবং কোড পিছনে সঙ্গে কিছুই করার আছে pickle.loads। এছাড়াও, কেবল পঠনযোগ্য অবজেক্টের জন্য করা নিরাপদ। যদি pickle.loadsইতিমধ্যে বিদ্যমান একটি সংশোধনযোগ্য বস্তুর যেমন একটি মডিউল to কোনও রেফারেন্স ফেরত দেওয়া হয় তবে এটি একটি বাগ। (এবং তাই আমি আমার জড়িত হয়ে দাঁড়িয়ে আছি যে ডিভাইডবিজারোর কোড উদাহরণটি কোনও প্রমাণ দেয় না))
জোনাস কলকার

69

একটি মডিউল ব্যবহার করুন। এটি একবারে আমদানি করা হয়। এটিতে কিছু বৈশ্বিক পরিবর্তনগুলি সংজ্ঞায়িত করুন - সেগুলি সিঙ্গলটনের 'বৈশিষ্ট্যগুলি' হবে। কিছু ফাংশন যুক্ত করুন - সিঙ্গলটনের 'পদ্ধতি'।


11
সুতরাং আপনি যা শেষ করেছেন তা হল ... কোনও ক্লাস নয়। আপনি এটিকে একটি শ্রেণি হিসাবে ব্যবহার করতে পারবেন না, আপনি অন্যান্য শ্রেণীর উপর ভিত্তি করে চলতে পারবেন না, আপনি আমদানি বাক্য গঠন ব্যবহার করেন এবং হঠাৎ আপনি
ওওপির

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

এটি মডিউল জুড়ে কাজ করে না। আমার "প্রধান" মডিউলটিতে আমি একটি মান সেট করি। আমি তখন এটি অন্য মডিউলে এবং এর নালটিতে উল্লেখ করি। দীর্ঘশ্বাস.
পল কেনজোরা

1
@ পোলকেনজোরা আপনার কোডটিতে আপনার একটি ত্রুটি থাকতে হবে। আপনি যদি কোনও মডিউলে গ্লোবাল ভেরিয়েবল সংজ্ঞায়িত করেন, আপনি অন্য মডিউল থেকে এটি অ্যাক্সেস করার সময় এর মান হওয়া উচিত।
ওয়ারওয়ারিচ

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

29

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

আপনার যদি সত্যই সিঙ্গলটন ক্লাস করতে হয় তবে আমি সাথে যাব:

class My_Singleton(object):
    def foo(self):
        pass

my_singleton = My_Singleton()

ব্যবহার করা:

from mysingleton import my_singleton
my_singleton.foo()

যেখানে মাইজিংলেটন.পি আপনার ফাইলের নাম যা মাই_সিংলেটন সংজ্ঞায়িত হয়েছে This এটি কাজ করে কারণ প্রথমবার কোনও ফাইল আমদানির পরে পাইথন কোডটি পুনরায় কার্যকর করে না।


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

আপনি যদি আমার_সিংটনকে প্যাচ করার সময় আপনার কোডটি পরীক্ষা করে দেখেন, তা কি সম্ভব হবে? যেহেতু এই মাই_সিংলেটনটিকে অন্য কোনও মডিউলে ইনস্ট্যান্ট করা যেতে পারে।
নবীন

@ নতুন - মাই_সিংলেটন একটি একক বস্তু। আপনি যদি এটি "প্যাচ" করেন তবে পরিবর্তনটি ভবিষ্যতের সমস্ত রেফারেন্সগুলিকে এমনকি অন্য মডিউলগুলিতেও প্রভাব ফেলবে।
অ্যালান ডাইক

16

আপনার জন্য এখানে একটি ওয়ান-লাইনার রয়েছে:

singleton = lambda c: c()

আপনি এটি কীভাবে ব্যবহার করবেন তা এখানে:

@singleton
class wat(object):
    def __init__(self): self.x = 1
    def get_x(self): return self.x

assert wat.get_x() == 1

আপনার অবজেক্টটি আগ্রহের সাথে তাত্ক্ষণিকভাবে আসে। এটি আপনি যা চান তা হতে পারে বা নাও পারে।


5
-1। এটি খুব খারাপ এবং নির্বোধ। আপনি অবজেক্ট হিসাবে ব্যবহার করার জন্য কোনও শ্রেণি সংজ্ঞায়িত করেন না। আপনি খুব কুৎসিত type(wat)বা পছন্দ মতো না হয়ে ক্লাসে আর অ্যাক্সেস করতে পারবেন না wat.__class__। আপনি যদি সত্যিই এটি অর্জন করতে চান তবে ক্লাসটি আরও ভালভাবে সংজ্ঞায়িত করুন এবং এখনই এটি ইনস্ট্যানিয়েট করুন, সাজসজ্জারের সাথে বিভ্রান্ত হওয়ার দরকার নেই।
0xc0de

2
আপনি কেন একটি একক এর ক্লাস ব্যবহার জানতে হবে? কেবল সিঙ্গলটন অবজেক্টটি ব্যবহার করুন ..
টোলি

1
এটি সিঙ্গলটন প্যাটার্ন নয় , সুতরাং IMO ফাংশনটির নাম আলাদাভাবে দেওয়া উচিত।
জিঞ্জারপ্লাসপ্লাস

8
উইকিপিডিয়া: "সিঙ্গলটন প্যাটার্ন হ'ল একটি নকশার প্যাটার্ন যা কোনও শ্রেণীর ইনস্ট্যান্টেশনকে একটি বস্তুর মধ্যে সীমাবদ্ধ করে"। আমি বলব যে আমার সমাধানটি কেবল এটি করে। ঠিক আছে, আমি অনুমান করি যে কেউ এটি করতে পারে wat2 = type(wat)()তবে এটি অজগর, আমরা সকলেই প্রাপ্তবয়স্কদের এবং সমস্ত কিছুর সম্মতি দিই। আপনি গ্যারান্টি দিতে পারবেন না যে কেবলমাত্র একটি উদাহরণ থাকবে, তবে আপনি গ্যারান্টি দিতে পারবেন যে লোকেরা যদি দ্বিতীয়টি তৈরি করে তবে এটি দেখতে খারাপ হবে — এবং যদি তারা ভদ্র, জনগণকে উত্সাহিত করে — তাদের কাছে একটি সতর্কতার চিহ্ন হিসাবে। আমি কী মিস করছি?
জোনাস কলকার

7

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

অ্যালেক্স মার্টেলির অজগর নকশার নকশাগুলির উপর আলাপটি দেখার জন্য আমি দৃ strongly়ভাবে সুপারিশ করব: অংশ 1 এবং অংশ 2 । বিশেষত, অংশ 1 এ তিনি সিলেটলেট / অংশীদারি রাষ্ট্রের বিষয়গুলি সম্পর্কে কথা বলেছেন।


2
যদিও এটি আমার প্রশ্নের উত্তর আসলেই নয়, আপনি যে সংস্থানগুলি দেখিয়েছেন এটি খুব কার্যকর। আমি
ভিক্ষাবৃত্তিতে

3

এখানে আমার নিজস্ব একক প্রয়োগ আছে। আপনাকে যা করতে হবে তা হল ক্লাসটি সাজাইয়া রাখা; সিঙ্গলটন পেতে, আপনাকে তখন Instanceপদ্ধতিটি ব্যবহার করতে হবে । এখানে একটি উদাহরণ:

   @Singleton
   class Foo:
       def __init__(self):
           print 'Foo created'

   f = Foo() # Error, this isn't how you get the instance of a singleton

   f = Foo.Instance() # Good. Being explicit is in line with the Python Zen
   g = Foo.Instance() # Returns already created instance

   print f is g # True

এবং এখানে কোড:

class Singleton:
    """
    A non-thread-safe helper class to ease implementing singletons.
    This should be used as a decorator -- not a metaclass -- to the
    class that should be a singleton.

    The decorated class can define one `__init__` function that
    takes only the `self` argument. Other than that, there are
    no restrictions that apply to the decorated class.

    To get the singleton instance, use the `Instance` method. Trying
    to use `__call__` will result in a `TypeError` being raised.

    Limitations: The decorated class cannot be inherited from.

    """

    def __init__(self, decorated):
        self._decorated = decorated

    def Instance(self):
        """
        Returns the singleton instance. Upon its first call, it creates a
        new instance of the decorated class and calls its `__init__` method.
        On all subsequent calls, the already created instance is returned.

        """
        try:
            return self._instance
        except AttributeError:
            self._instance = self._decorated()
            return self._instance

    def __call__(self):
        raise TypeError('Singletons must be accessed through `Instance()`.')

    def __instancecheck__(self, inst):
        return isinstance(inst, self._decorated)

2
এটা সত্য একক নয়। সত্য সিঙ্গলটনে SingletonList = Singleton(list).Instance(); print(SingletonList is type(SingletonList)())মুদ্রণ করা উচিত True; আপনার কোডের প্রিন্ট সহFalse
জিঞ্জারপ্লাসপ্লাস

@ জিঞ্জারপ্লাসপ্লাস আমি কয়েকটি সীমাবদ্ধতার বিষয়ে অবগত ছিলাম, তবে আপনি যেটির প্রতি দৃষ্টি নিবদ্ধ করেছেন তার বিষয়ে নয়। এটি উল্লেখ করার জন্য ধন্যবাদ। দুর্ভাগ্যক্রমে, আমার এই মুহুর্তে এর কোনও সমাধান সম্পর্কে পাতলা করার সময় নেই।
পল মানতা

2

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

মাইক ওয়াটকিন্সকে ধন্যবাদ: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/ । আপনি যদি প্রোগ্রামটি পাইথন 2 এবং পাইথন 3 উভয় ক্ষেত্রেই কাজ করতে চান তবে আপনার যেমন কিছু করতে হবে:

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

MC = Singleton('MC', (object), {})

class MyClass(MC):
    pass    # Code for the class implementation

আমি অনুমান করি যে অ্যাসাইনমেন্টের 'অবজেক্ট' এর 'বেসক্লাস' দিয়ে প্রতিস্থাপন করা দরকার, তবে আমি এটি চেষ্টা করি নি (চিত্রের মতো কোড চেষ্টা করেছি)।


অবশ্যই এটি কোনও মেটাক্লাস নয় - পাইথন 3 তে মাইক্লাস নির্মাণের জন্য একটি মেটাক্লাস ব্যবহার করার জন্যclass MyClass(metaclass=Singleton)
হেডহেডাব্রুম

Mikewatkins.ca লিঙ্ক (কার্যকরভাবে) নষ্ট হয়ে গেছে।
পিটার মর্টেনসেন

1

ঠিক আছে, মডিউল-স্তরের বিশ্বব্যাপী থাকার বিষয়ে সাধারণ পাইথোনিক পরামর্শের সাথে একমত হওয়া ছাড়া অন্যটি কীভাবে:

def singleton(class_):
    class class_w(class_):
        _instance = None
        def __new__(class2, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w, class2).__new__(class2, *args, **kwargs)
                class_w._instance._sealed = False
            return class_w._instance
        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True
    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(object):
    def __init__(self, text):
        print text
    @classmethod
    def name(class_):
        print class_.__name__

x = MyClass(111)
x.name()
y = MyClass(222)
print id(x) == id(y)

আউটপুট হল:

111     # the __init__ is called only on the 1st time
MyClass # the __name__ is preserved
True    # this is actually the same instance

_sealedবৈশিষ্ট্যটির বিন্দুটি কী ? যতদূর আমি দেখছি এটি কিছুই করে না? এ সম্পর্কে আমার কিছুটা অবহেলা করছে যা বলেছে এটি ভাল করা উচিত নয় ... আমি এই সপ্তাহের শেষে কিছু তুলনামূলক পরীক্ষা চালাব।
হেডহেডফাবরুম

_ বিক্রয় নিশ্চিত করে যে আপনার আরম্ভ একবার হয়েছে; নিয়মিত ফাংশনের মতো ডেকরেটারের চেয়ে খারাপ অনুষ্ঠান করার কোনও বিন্দু আমি দেখতে পাচ্ছি না - ফাংশনটি প্রতি ক্লাসে শুধুমাত্র একবার চালানো হয় এবং একটি নতুন উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাস ফিরিয়ে দেয়
গার্ড

বিটিডাব্লু, আপনার সম্পাদনায় এমন ট্যাব রয়েছে যা ইনডেন্টগুলি ভেঙে দেয় আপনি আরও বলেন যে 'আমরা 2 টি শ্রেণি তৈরি করছি' - আপনি কী বোঝাতে চাইছেন যে আমরা '1 অতিরিক্ত শ্রেণি' তৈরি করছি?
গার্ড

হ্যাঁ একটি অতিরিক্ত শ্রেণি বলতে আমি বোঝাতে চাইছি। আমি __init__যতবার স্টাফ শুরু করি ততবার কল করার জন্য অন্তর্ভুক্ত করার ইচ্ছা করি । কেবল একটি সাধারণ 'ক্লাস.মোথডিয়াল ইন ইনিশিয়ালড'। ইন্ডেন্টেশন হিসাবে - আপনি ট্যাব এবং স্পেস ব্যবহার করেছেন - আমি এটির বেশিরভাগ স্থির করে দিয়েছি তবে আপনি এটি পেতে চাইলে একটি মিস করেছেন বলে মনে হয় (কেবল সম্পাদনা লগটি পরীক্ষা করুন)
হেডহেডব্রুম

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

1

এটি সম্পর্কে:

def singleton(cls):
    instance=cls()
    cls.__new__ = cls.__call__= lambda cls: instance
    cls.__init__ = lambda self: None
    return instance

এটি একটি ক্লাসে সজ্জা হিসাবে ব্যবহার করুন যা সিঙ্গলটন হওয়া উচিত। এটার মত:

@singleton
class MySingleton:
    #....

এটি singleton = lambda c: c()অন্য উত্তরের সাজসজ্জার অনুরূপ । অন্যান্য সমাধানের মতো, একমাত্র উদাহরণে শ্রেণীর নাম ( MySingleton) রয়েছে। যাইহোক, এই সমাধানের সাহায্যে আপনি ক্লাস থেকে এখনও "তৈরি" উদাহরণ (প্রকৃতপক্ষে একমাত্র উদাহরণটি পান) করতে পারেন MySingleton()। এটি আপনাকে অতিরিক্ত উদাহরণ তৈরি থেকে বাধা দেয় type(MySingleton)()(এটি একই উদাহরণটিও দেয়)।


আপনি কোনও শ্রেণিকে এটি অবজেক্ট হিসাবে ব্যবহার করতে সংজ্ঞায়িত করেন না।
0xc0de

1
যতবার আপনি কল করবেন type(MySingleton)(), ডাকবেন MySingleton.__init__()এবং অবজেক্টটি একাধিক টাইমের সূচনা হবে; আপনি এটা লেখার ঠিক করতে পারবো cls.__init__ = lambda self: passআপনার singleton। এছাড়াও, ওভাররাইডিং cls.__call__অর্থহীন এবং এমনকি ক্ষতিকারক বলে মনে হয় - __call__এই প্রসঙ্গে সংজ্ঞায়িত হিসাবে আপনি যখন কল করবেন তখন ব্যবহৃত হবে MySingleton(any, list, of, arguments)না, যখন আপনি কল করবেন না type(MySingleton)(any, list, of, arguments)
জিঞ্জারপ্লাসপ্লাস

@ জিঞ্জারপ্লাসপ্লাস, এটি করার জন্য আপনাকে ধন্যবাদ __init__()যেটি করার সময় আবার ডাকে type(MySingleton)()। আপনার প্রস্তাবিত সমাধানটি (যোগ করা cls.__init__ = lambda self: pass) একটি বাক্য গঠন ত্রুটি দেয় কারণ ল্যাম্বডা এক্সপ্রেশনটির শেষ অংশটি একটি বিবৃতি নয়, একটি অভিব্যক্তি হওয়া দরকার। যাইহোক, cls.__init__ = lambda self: Noneকাজগুলি যুক্ত করে, তাই আমি আমার উত্তরে এটি যুক্ত করেছি।
টোলি

1
@ জিঞ্জারপ্লাসপ্লাস, ব্যবহার সম্পর্কিত __call__। আমার উদ্দেশ্য ছিল উভয় তৈরি করা type(MySingleton)()এবং MySingleton()দৃষ্টান্তটি ফিরিয়ে দেওয়া। সুতরাং এটি আমি যা চাইছিলাম তা করছে। আপনি মাইসিংটনকে সিঙ্গলটনের ধরণ বা সিঙ্গলটনের উদাহরণ (বা উভয়) হিসাবে ভাবতে পারেন।
টোলি

1

আমি আমার রিং মধ্যে টস করব। এটি একটি সাধারণ সাজসজ্জা।

from abc import ABC

def singleton(real_cls):

    class SingletonFactory(ABC):

        instance = None

        def __new__(cls, *args, **kwargs):
            if not cls.instance:
                cls.instance = real_cls(*args, **kwargs)
            return cls.instance

    SingletonFactory.register(real_cls)
    return SingletonFactory

# Usage
@singleton
class YourClass:
    ...  # Your normal implementation, no special requirements.

আমি মনে করি এটির অন্যান্য সমাধানগুলির কয়েকটিতে এর সুবিধা রয়েছে:

  • এটি পরিষ্কার এবং সংক্ষিপ্ত (আমার চোখে; ডি)।
  • এটির ক্রিয়াটি সম্পূর্ণভাবে আবদ্ধ। বাস্তবায়নের বিষয়ে আপনাকে কোনও জিনিস পরিবর্তন করার দরকার নেই YourClass। এর মধ্যে আপনার বর্গের জন্য একটি মেটাক্লাস ব্যবহার করার প্রয়োজন নেই (নোট করুন যে উপরের মেটাক্লাসটি কারখানায় রয়েছে, "প্রকৃত" শ্রেণিতে নয়)।
  • এটি বানর-প্যাচিং কোনও কিছুর উপর নির্ভর করে না।
  • এটি কলকারীদের কাছে স্বচ্ছ:
    • কলকারীরা এখনও কেবল আমদানি করে YourClass, এটি একটি শ্রেণীর মতো দেখায় (কারণ এটি) এবং তারা এটি সাধারণত ব্যবহার করে। কলকারীদের কারখানার কার্যক্রমে অভিযোজিত করার দরকার নেই।
    • যা YourClass()ইনস্ট্যান্ট করে তা এখনও YourClassআপনার বাস্তবায়নের সত্য উদাহরণ , কোনও প্রক্সির প্রক্সি নয়, ফলে এর ফলে পার্শ্ব প্রতিক্রিয়া হওয়ার কোনও সম্ভাবনা নেই।
    • isinstance(instance, YourClass) এবং অনুরূপ অপারেশনগুলি এখনও প্রত্যাশিত হিসাবে কাজ করে (যদিও এই বিটটিতে আবির প্রয়োজন হয় তাই পাইথনকে << 2.6 এড়িয়ে যায়)।

আমার একটি খারাপ দিক ঘটে: প্রকৃত শ্রেণীর শ্রেণিবদ্ধ এবং স্থিতিবিজ্ঞানগুলি কারখানার শ্রেণিটি এটি আড়াল করে স্বচ্ছভাবে কল করতে পারে না। আমি এটি খুব কমই ব্যবহার করেছি যে আমি কখনই সেই প্রয়োজনের দিকে চলে যাইনি, তবে কারখানায় একটি কাস্টম মেটাক্লাস ব্যবহার করে এটি সহজেই সংশোধন করা যেতে পারে __getattr__()যা বাস্তব বর্গের সমস্ত-ইশ বৈশিষ্ট্য অ্যাক্সেসের জন্য কার্যকর করে।

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

def unique(real_cls):

    class UniqueFactory(ABC):

        @functools.lru_cache(None)  # Handy for 3.2+, but use any memoization decorator you like
        def __new__(cls, *args, **kwargs):
            return real_cls(*args, **kwargs)

    UniqueFactory.register(real_cls)
    return UniqueFactory

যা কিছু বলেছিল, আমি সেই সাধারণ পরামর্শের সাথে একমত যে আপনি যদি মনে করেন যে এইগুলির মধ্যে একটির আপনার প্রয়োজন হয় তবে আপনার সম্ভবত একটি মুহুর্তের জন্য থামানো উচিত এবং নিজেকে সত্যিই জিজ্ঞাসা করা উচিত যদি আপনি সত্যিই এটি করেন কিনা। 99% সময়, YAGNI।


0

টোলির উত্তরের ভিত্তিতে কোড ।

#decorator, modyfies new_cls
def _singleton(new_cls):
    instance = new_cls()                                              #2
    def new(cls):
        if isinstance(instance, cls):                                 #4
            return instance
        else:
            raise TypeError("I can only return instance of {}, caller wanted {}".format(new_cls, cls))
    new_cls.__new__  = new                                            #3
    new_cls.__init__ = lambda self: None                              #5
    return new_cls


#decorator, creates new class
def singleton(cls):
    new_cls = type('singleton({})'.format(cls.__name__), (cls,), {} ) #1
    return _singleton(new_cls)


#metaclass
def meta_singleton(name, bases, attrs):
    new_cls = type(name, bases, attrs)                                #1
    return _singleton(new_cls)

ব্যাখ্যা:

  1. প্রদত্ত থেকে উত্তরাধিকারসূত্রে নতুন ক্লাস তৈরি করুন cls
    ( clsউদাহরণস্বরূপ কেউ চাইলে এটি সংশোধন করে না singleton(list))

  2. উদাহরণ তৈরি করুন। ওভাররাইড করার আগে __new__এটি এত সহজ।

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

  5. তাহলে __new__()আয় একটি দৃষ্টান্ত cls, তারপরে নতুন ইনস্ট্যান্স এর __init__()পদ্ধতি প্রার্থনা করা হবে না মত __init__(self[, ...]), যেখানে স্ব নতুন উদাহরণ নেই এবং অবশিষ্ট আর্গুমেন্ট হিসাবে গৃহীত হয় একই __new__()

    instanceইতিমধ্যে আরম্ভ করা হয়েছে, সুতরাং ফাংশন __init__কিছুই না করে ফাংশন প্রতিস্থাপন করে ।

এটি অনলাইনে কাজ করে দেখুন


0

এটি ফাবের উত্তরের সাথে সামান্য হলেও একই রকম নয়।

Singleton চুক্তি প্রয়োজন হয় না যে, আমরা কন্সট্রাকটর একাধিক বার কল করতে সক্ষম হবেন। যেহেতু একবার এবং একবারে সিঙ্গলটন তৈরি করা উচিত, এটি কি একবারে তৈরি করা দেখা উচিত নয়? "স্পুফিং" কনস্ট্রাক্টর যুক্তিযুক্তভাবে সুগম্যতাকে বাধা দেয়।

সুতরাং আমার পরামর্শটি কেবল এটি:

class Elvis():
    def __init__(self):
        if hasattr(self.__class__, 'instance'):
            raise Exception()
        self.__class__.instance = self
        # initialisation code...

    @staticmethod
    def the():
        if hasattr(Elvis, 'instance'):
            return Elvis.instance
        return Elvis()

এটি instanceব্যবহারকারীর কোড দ্বারা কনস্ট্রাক্টর বা ক্ষেত্রের ব্যবহারকে অস্বীকার করে না:

if Elvis() is King.instance:

... আপনি যদি নিশ্চিতভাবে জানেন যে Elvisএটি এখনও তৈরি করা হয়নি, এবং এটি Kingহয়েছে।

তবে এটি ব্যবহারকারীদের সর্বজনীন পদ্ধতিটি ব্যবহার করতে উত্সাহিত করে the:

Elvis.the().leave(Building.the())

এটি সম্পূর্ণ করার জন্য __delattr__()আপনি মুছে ফেলার কোনও প্রচেষ্টা করা হলে একটি ব্যতিক্রম বাড়াতেও ওভাররাইড করতে পারেন instanceএবং এটি ওভাররাইড করে __del__()যাতে এটি একটি ব্যতিক্রম উত্থাপন করে (যদি না আমরা জানি যে প্রোগ্রামটি শেষ হচ্ছে ...)

আরও উন্নতি


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

try:
    # This is jython-specific
    from synchronize import make_synchronized
except ImportError:
    # This should work across different python implementations
    def make_synchronized(func):
        import threading
        func.__lock__ = threading.Lock()

        def synced_func(*args, **kws):
            with func.__lock__:
                return func(*args, **kws)

        return synced_func

class Elvis(object): # NB must be subclass of object to use __new__
    instance = None

    @classmethod
    @make_synchronized
    def __new__(cls, *args, **kwargs):
        if cls.instance is not None:
            raise Exception()
        cls.instance = object.__new__(cls, *args, **kwargs)
        return cls.instance

    def __init__(self):
        pass
        # initialisation code...

    @classmethod
    @make_synchronized
    def the(cls):
        if cls.instance is not None:
            return cls.instance
        return cls()

নোটের পয়েন্টগুলি:

  1. আপনি যদি পাইথন 2.x এ অবজেক্ট থেকে সাবক্লাস না করেন তবে আপনি একটি পুরানো স্টাইলের ক্লাস পাবেন যা ব্যবহার করে না __new__
  2. সাজানোর সময় __new__আপনাকে অবশ্যই @ ক্লাসমেডোথের সাথে সাজাতে __new__হবে বা আনবাউন্ড উদাহরণ পদ্ধতি হবে
  3. এটি সম্ভবত একটি মেটাক্লাসের ব্যবহারের মাধ্যমে উন্নত করা যেতে পারে, কারণ এটি আপনাকে একটি শ্রেণিক theস্তরের সম্পত্তি তৈরি করতে দেয় , সম্ভবত এটির নামকরণ করেinstance

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

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

ধন্যবাদ ... আহা হ্যাঁ, ব্যতিক্রম ছোঁড়ার আগে একটি ক্ষণিকের দ্বিতীয় উদাহরণ। আমি এটি পরিবর্তন করেছি __init__যাতে আশা করা যায় এটি সাবক্লাসেবল হওয়া উচিত ...
মাইক রডেন্ট

কুল, theসম্ভবত একই কারণে একটি বর্গ পদ্ধতি হওয়া থেকে উপকৃত হতে পারে
theheadofabroom

হ্যাঁ আপনি ঠিক. তারপরে আপনার কাছে একটি সুপারইলভিস সাবক্লাস সিঙ্গলটন থাকতে পারে এবং (উদাহরণস্বরূপ) একটি কালিরিয়েলস সাবক্লাস সিঙ্গলটন ... এবং সেগুলি সহ-অস্তিত্ব থাকতে পারে। অতিরিক্ত চিন্তাভাবনা দেখুন। দয়া করে আমার কোডটি উন্নত করুন।
মাইকে রডেন্ট

0

একটি লাইনার (আমি গর্বিত নই, তবে এটি কাজটি করে):

class Myclass:
  def __init__(self):
      # do your stuff
      globals()[type(self).__name__] = lambda: self # singletonify

আপনার ক্লাসটি অন্য কোনও মডিউলগুলিতে আমদানি না করা পর্যন্ত এটি কাজ করতে পারে ...
অরণ-ফে

সত্য। আপনি যদি ক্লাসটি ইনটাইট করার জন্য মূল্য দিতে পারেন তবে এগুলি এড়াতে ক্লাস সংজ্ঞা দেওয়ার সাথে সাথেই আপনি একটি মাইক্লাস () চালাতে পারেন।
পোলোভোয়াজুল

0

যদি আপনার সিঙ্গলটনের উদাহরণটির অলস সূচনা প্রয়োজন না হয় তবে নিম্নলিখিতগুলি সহজ এবং থ্রেড-নিরাপদ হওয়া উচিত:

class A:
    instance = None
    # Methods and variables of the class/object A follow
A.instance = A()

এই Aউপায়টি মডিউল আমদানিতে সূচিত একক সিঙ্গলটন।


0
  • এক একই ক্লাসের দৃষ্টান্ত একাধিক নম্বর আছে, কিন্তু চায় শুধুমাত্র যদি args বা kwargs ভিন্ন, এক ব্যবহার করতে পারেন এই
  • যাত্রা।
    1. আপনার যদি কোনও ক্লাস পরিচালনা পরিচালনা serialকরে থাকে এবং একটি দৃষ্টান্ত তৈরি করতে আপনি সিরিয়াল বন্দরটি যুক্তি হিসাবে প্রেরণ করতে চান তবে traditionalতিহ্যবাহী পদ্ধতির সাথে কাজ করবে না
    2. উল্লিখিত সাজসজ্জার ব্যবহার করে, আরগগুলি পৃথক হলে কেউ শ্রেণীর একাধিক উদাহরণ তৈরি করতে পারে।
    3. একই অর্গগুলির জন্য, সজ্জাকারক ইতিমধ্যে তৈরি করা একই উদাহরণটি ফিরিয়ে দেবে।
>>> from decorators import singleton
>>>
>>> @singleton
... class A:
...     def __init__(self, *args, **kwargs):
...         pass
...
>>>
>>> a = A(name='Siddhesh')
>>> b = A(name='Siddhesh', lname='Sathe')
>>> c = A(name='Siddhesh', lname='Sathe')
>>> a is b  # has to be different
False
>>> b is c  # has to be same
True
>>>

0

সম্ভবত আমি সিঙ্গেলটন প্যাটার্নটি মিস করছি তবে আমার সমাধানটি হ'ল এই সহজ এবং বাস্তববাদী (পাইথোনিক?)। এই কোডটি দুটি লক্ষ্য পূর্ণ করে

  1. Fooসর্বত্র (গ্লোবাল) অ্যাক্সেসযোগ্য উদাহরণ তৈরি করুন ।
  2. কেবলমাত্র একটি উদাহরণ Fooউপস্থিত থাকতে পারে।

এই কোড।

#!/usr/bin/env python3

class Foo:
    me = None

    def __init__(self):
        if Foo.me != None:
            raise Exception('Instance of Foo still exists!')

        Foo.me = self


if __name__ == '__main__':
    Foo()
    Foo()

আউটপুট

Traceback (most recent call last):
  File "./x.py", line 15, in <module>
    Foo()
  File "./x.py", line 8, in __init__
    raise Exception('Instance of Foo still exists!')
Exception: Instance of Foo still exists!

0

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

import builtins

# -----------------------------------------------------------------------------
# So..... you would expect that a class would be "global" in scope, however
#   when different modules use this,
#   EACH ONE effectively has its own class namespace.  
#   In order to get around this, we use a metaclass to intercept
#   "new" and provide the "truly global metaclass instance" if it already exists

class MetaConfig(type):
    def __new__(cls, name, bases, dct):
        try:
            class_inst = builtins.CONFIG_singleton

        except AttributeError:
            class_inst = super().__new__(cls, name, bases, dct)
            builtins.CONFIG_singleton = class_inst
            class_inst.do_load()

        return class_inst

# -----------------------------------------------------------------------------

class Config(metaclass=MetaConfig):

    config_attr = None

    @classmethod
    def do_load(cls):
        ...<load-cfg-from-file>...

-1

আমি এই সমাধানটি কোথায় পেয়েছি তা মনে করতে পারছি না, তবে আমার অ পাইথন-বিশেষজ্ঞ দৃষ্টিকোণ থেকে এটি সবচেয়ে 'মার্জিত' বলে মনে হচ্ছে:

class SomeSingleton(dict):
    __instance__ = None
    def __new__(cls, *args,**kwargs):
        if SomeSingleton.__instance__ is None:
            SomeSingleton.__instance__ = dict.__new__(cls)
        return SomeSingleton.__instance__

    def __init__(self):
        pass

    def some_func(self,arg):
        pass

আমি কেন এটি পছন্দ করি? কোনও সাজসজ্জার নেই, কোনও মেটা ক্লাস নেই, একাধিক উত্তরাধিকার নেই ... এবং আপনি যদি সিদ্ধান্ত নেন যে আপনি এটি আর কোনও সিঙ্গেলন হিসাবে না চান, কেবল __new__পদ্ধতিটি মুছুন । আমি পাইথনে নতুন হিসাবে (এবং সাধারণভাবে ওওপি) আমি প্রত্যাশা করি যে এটি কেন একটি ভয়াবহ পদ্ধতির কারণে কেউ আমাকে সরাসরি সেট করবে?


2
কেন এটি একটি ভয়ানক পদ্ধতির? আপনি যখন অন্য একটি সিঙ্গলটন ক্লাস তৈরি করতে চান, আপনাকে অনুলিপি এবং পেস্ট করতে হবে __new__নিজেকে পুনরাবৃত্তি করবেন না
জিঞ্জারপ্লাসপ্লাস

এছাড়াও, কেন আপনার নতুন গ্রহণ করে *argsএবং **kwargs, এবং তারপর তাদের সাথে কিছুই করে না? তাদের মধ্যে পাস dict.__new__এই ভাবে: dict.__new__(cls, *args, **kwargs)
জিঞ্জারপ্লাসপ্লাস

এটি __init__ক্লাসটি যখনই ডাকবে তখনই এই পদ্ধতিটিকে কল করবে । যদি আপনার __init__পদ্ধতিটি আসলে কিছু করে থাকে তবে আপনি সমস্যাটি লক্ষ্য করবেন। আপনি যখনই করবেন SomeSingleton(), আপনার সিঙ্গলটনের রাজ্যটি __init__পদ্ধতিটি পুনরায় সেট করা হয়েছে ।
অরণ-ফে

-2

এটি সিঙ্গেলনগুলি প্রয়োগের আমার পছন্দসই উপায়:

class Test(object):
    obj = None

    def __init__(self):
        if Test.obj is not None:
            raise Exception('A Test Singleton instance already exists')
        # Initialization code here

    @classmethod
    def get_instance(cls):
        if cls.obj is None:
            cls.obj = Test()
        return cls.obj

    @classmethod
    def custom_method(cls):
        obj = cls.get_instance()
        # Custom Code here

1
এটি কঠোরভাবে একটি সিঙ্গলটন নয় কারণ এটি ক্লাসের একাধিক উদাহরণের পক্ষে উপস্থিত হতে পারে। একটি উন্নতি হবে
ক্লাসটিকে

-2

এই উত্তরটি সম্ভবত আপনি যা খুঁজছেন তা নয়। আমি একটি সিঙ্গেলটন এই অর্থে চেয়েছিলাম যে তুলনায় কেবলমাত্র সেই বস্তুরই তার পরিচয় ছিল। আমার ক্ষেত্রে এটি সেন্টিনেল মান হিসাবে ব্যবহৃত হচ্ছিল । যার উত্তর খুব সহজ, যে কোনও বস্তু তৈরি করুন mything = object()এবং অজগর প্রকৃতির দ্বারা, কেবলমাত্র সেই জিনিসটিরই তার পরিচয় থাকবে।

#!python
MyNone = object()  # The singleton

for item in my_list:
    if item is MyNone:  # An Example identity comparison
        raise StopIteration

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

আপনি কীভাবে একটি মডিউল একাধিকবার আমদানি করতে পারবেন তা বিশদ দিয়ে বলতে পারেন? আমি কেবল একবার দেখেছি যখন মডিউলটি লোড হওয়ার সময় একটি ব্যতিক্রম ঘটে, ব্যবহারকারী পরেও মডিউলটি লোড করতে পারে, তার পার্শ্ব প্রতিক্রিয়া ইতিমধ্যে ঘটেছে, তাই কিছু ক্রিয়া দ্বিতীয়বার কার্যকর করা হতে পারে।
sleblanc

কোনও মডিউল পুরোপুরি লোড হয়ে যাওয়ার পরে, অনুবাদককে এটি ব্যবহার করে evalবা করার জন্য দোভাষীকে জোর করে না করে এই মডিউলটি আবার চালানোর কোনও উপায় আমি দেখতে পাচ্ছি না importlib.reload
15-29

-3

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

আমি এই জাতীয় কিছু (অলস সূচনা) লিখতে সক্ষম হতে চাই, তবে দুর্ভাগ্যক্রমে ক্লাসগুলি তাদের নিজস্ব সংজ্ঞা অনুসারে পাওয়া যায় না।

# wouldn't it be nice if we could do this?
class Foo(object):
    instance = None

    def __new__(cls):
        if cls.instance is None:
            cls.instance = object()
            cls.instance.__class__ = Foo
        return cls.instance

যেহেতু এটি সম্ভব নয়, তাই আমরা সূচনাটি এবং স্থিতিস্থলটি বের করতে পারি

আগ্রহের সূচনা:

import random


class FooMaker(object):
    def __init__(self, *args):
        self._count = random.random()
        self._args = args


class Foo(object):
    def __new__(self):
        return foo_instance


foo_instance = FooMaker()
foo_instance.__class__ = Foo

অলস সূচনা:

আগ্রহের সূচনা:

import random


class FooMaker(object):
    def __init__(self, *args):
        self._count = random.random()
        self._args = args


class Foo(object):
    def __new__(self):
        global foo_instance
        if foo_instance is None:
            foo_instance = FooMaker()
        return foo_instance


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