python - সহজ ভাষায় পাইথন ৩ pdf download




পাইথন একটি সিঙ্গলটন তৈরি (14)

একটি Metaclass ব্যবহার করুন

আমি পদ্ধতি # 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

অথবা Python3 মধ্যে

class Logger(metaclass=Singleton):
    pass

যদি আপনি __init__ চালাতে চান প্রত্যেক সময় ক্লাস বলা হয়, যোগ করুন

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

Singleton.__call__ বিবৃতিতে Singleton.__call__

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

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

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

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

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

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

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

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

# 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) বিপরীতে, isinstance(inst, Singleton) True ফিরে আসবে।

সংশোধণী

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

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() বেস super() সাথে একই নামটির পদ্ধতি কল করে কারণ সেগুলি পুনর্বিবেচনা করবে। এর অর্থ হল আপনার ক্লাস __new__ কাস্টমাইজ করতে পারে না, এবং যে কোনও ক্লাস থেকে __init__ অর্জন করতে পারে না যাকে __init__ বলা হয়।

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

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

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

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

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

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

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

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

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

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

সেরা পদ্ধতি:

পদ্ধতি 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

পেশাদাররা

  • সজ্জা একাধিক উত্তরাধিকার চেয়ে প্রায়ই আরও স্বজ্ঞাত যে একটি উপাদানের হয়।

কনস

  • MyClass () ব্যবহার করে তৈরি বস্তুগুলি সত্যিকারের একক্টোন বস্তু হবে, তবে MyClass নিজেই AA ফাংশন, একটি বর্গ নয়, তাই আপনি এটির থেকে ক্লাস পদ্ধতিগুলিকে কল করতে পারবেন না। এছাড়াও m = MyClass(); n = MyClass(); o = type(n)(); 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

পেশাদাররা

  • এটি একটি সত্য ক্লাস

কনস

  • একাধিক উত্তরাধিকার - eugh! __new__ একটি দ্বিতীয় বেস ক্লাস থেকে উত্তরাধিকার সময় overwritten হতে পারে? এক প্রয়োজন বেশী বেশী মনে আছে।

পদ্ধতি 3: একটি metaclass

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

পেশাদাররা

  • এটি একটি সত্য ক্লাস
  • স্বতঃস্ফূর্তভাবে উত্তরাধিকার কভার

কনস

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

আপনি সম্ভবত পাইথন একটি singleton প্রয়োজন হবে না। শুধু একটি মডিউল আপনার সমস্ত তথ্য এবং ফাংশন সংজ্ঞায়িত এবং আপনার একটি de-facto এককোন আছে।

আপনি সত্যিই একটি এককন্টন ক্লাস আছে, তাহলে আমি সঙ্গে যেতে চাই:

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

my_singleton = My_Singleton()

ব্যবহার করা:

from mysingleton import my_singleton
my_singleton.foo()

যেখানে mysingleton.py আপনার ফাইলের নাম যা My_Singleton সংজ্ঞায়িত করা হয়। এটি কাজ করে কারণ প্রথমবারের মতো একটি ফাইল আমদানি করা হয়, পাইথন কোডটি পুনরায় চালনা করে না।


এখানে singletons আমার নিজস্ব বাস্তবায়ন। আপনাকে যা করতে হবে সব ক্লাস সাজাইয়া রাখা হয়; এককন্টন পেতে, আপনি তারপর 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)

এখানে আপনার জন্য একটি এক-মাছ ধরার নৌকা:

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

আপনার বস্তু আগ্রহীভাবে instantiated পায়। এই আপনি চান বা হতে পারে না।


কিভাবে এই সম্পর্কে:

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() দ্বারা, ক্লাস থেকে "তৈরি করুন" উদাহরণগুলি (আসলে কেবলমাত্র উদাহরণ পাবেন MySingleton() । এটি আপনাকে type(MySingleton)() দ্বারা অতিরিক্ত উদাহরণ তৈরি করতে বাধা দেয় (যা একই দৃষ্টান্তটিও ফেরত দেয়)।


পদ্ধতি 3টি খুব সুস্পষ্ট বলে মনে হচ্ছে, তবে আপনি যদি আপনার প্রোগ্রামটি Python 2 এবং Python 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

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


স্ট্যাক ওভারফ্লো প্রশ্ন চেক করুন Python এ এককটি সংজ্ঞায়িত করার জন্য একটি সহজ, মার্জিত উপায় আছে? বিভিন্ন সমাধান সঙ্গে।

আমি দৃঢ়ভাবে প্যাথন নকশা নকশার উপর অ্যালেক্স Martelli এর আলোচনা দেখার জন্য সুপারিশ চাই: অংশ 1 এবং অংশ 2 । বিশেষ করে, অংশ 1 তিনি singletons / শেয়ার রাষ্ট্র রাষ্ট্র বস্তু সম্পর্কে আলোচনা।


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

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__পদ্ধতিটি মুছে দিন । আমি পাইথন নতুন (এবং সাধারণভাবে OOP) হিসাবে নতুন আমি আশা করি কেউ কেন এই একটি ভয়ঙ্কর পদ্ধতির সম্পর্কে সরাসরি সেট করবে?


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

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

# 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

একটি মাছ ধরার নৌকা (আমি গর্বিত না, কিন্তু এটা কাজ করে):

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

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

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

এই ভাবে Aমডিউল আমদানি এ একটি singleton শুরু।


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

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.

উপকারিতা আমি মনে করি এটি অন্য কিছু সমাধানের উপর আছে:

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

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

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

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।


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

#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__এটা overriding আগে এত সহজ।

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

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

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

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


class Foo(object):
     pass

some_global_variable = Foo()

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





metaclass