মেটাক্লাসগুলির জন্য কিছু (কংক্রিট) ব্যবহারের ক্ষেত্রে কী কী?


118

আমার এক বন্ধু আছে যা মেটাচ্লাস ব্যবহার করতে পছন্দ করে এবং নিয়মিত সমাধান হিসাবে তাদের প্রস্তাব দেয়।

আমি মনে মনে করি যে আপনার প্রায় কখনও मेटाটগ্লাস ব্যবহার করার দরকার নেই। কেন? কারণ আমি অনুমান করি যে আপনি যদি কোনও শ্রেণীর মতো এমন কিছু করছেন তবে আপনার সম্ভবত এটি কোনও বস্তুর সাথে করা উচিত। এবং একটি ছোট পুনরায় ডিজাইন / রিফ্যাক্টর ক্রমযুক্ত।

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

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

আমি শুরু করে দিব:

কখনও কখনও তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করার সময় শ্রেণিকে নির্দিষ্ট উপায়ে রূপান্তর করতে সক্ষম হওয়া কার্যকর।

(আমি কেবলমাত্র এটির ক্ষেত্রেই ভাবতে পারি এবং এটি কংক্রিট নয়)


3
এটা একটা ভাল প্রশ্ন. নীচের উত্তরগুলি থেকে বিচার করা, এটি একেবারে স্পষ্ট যে মেটাক্লাসগুলির জন্য কংক্রিট ব্যবহারের মতো কোনও জিনিস নেই।
মার্কাস অটোসন

উত্তর:


25

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

class PlottingInteractive:
    add_slice = wrap_pylab_newplot(add_slice)

এই পদ্ধতিটি এপিআই পরিবর্তনগুলি এবং এর সাথে চালিয়ে যায় না, তবে শ্রেণীর বৈশিষ্ট্যগুলি __init__পুনরায় সেট করার আগে শ্রেণীর বৈশিষ্ট্যগুলির উপরে পুনরাবৃত্তি করা আরও কার্যকর এবং জিনিস আপ টু ডেট রাখে:

class _Interactify(type):
    def __init__(cls, name, bases, d):
        super(_Interactify, cls).__init__(name, bases, d)
        for base in bases:
            for attrname in dir(base):
                if attrname in d: continue # If overridden, don't reset
                attr = getattr(cls, attrname)
                if type(attr) == types.MethodType:
                    if attrname.startswith("add_"):
                        setattr(cls, attrname, wrap_pylab_newplot(attr))
                    elif attrname.startswith("set_"):
                        setattr(cls, attrname, wrap_pylab_show(attr))

অবশ্যই এটি করার আরও ভাল উপায় থাকতে পারে তবে আমি এটি কার্যকর বলে মনে করেছি। অবশ্যই, এটিতে __new__বা এটিও করা যেতে পারে __init__, তবে এটিই ছিল আমি সবচেয়ে সোজা solution


103

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

আমি দেখা বেশিরভাগ মেটাচ্লাস দুটি জিনিসগুলির মধ্যে একটি করে:

  1. নিবন্ধকরণ (একটি ডাটা স্ট্রাকচারে একটি ক্লাস যুক্ত করা):

    models = {}
    
    class ModelMetaclass(type):
        def __new__(meta, name, bases, attrs):
            models[name] = cls = type.__new__(meta, name, bases, attrs)
            return cls
    
    class Model(object):
        __metaclass__ = ModelMetaclass

    যখনই আপনি সাবক্লাস করবেন Model, আপনার ক্লাস modelsঅভিধানে নিবন্ধিত রয়েছে :

    >>> class A(Model):
    ...     pass
    ...
    >>> class B(A):
    ...     pass
    ...
    >>> models
    {'A': <__main__.A class at 0x...>,
     'B': <__main__.B class at 0x...>}

    এটি শ্রেণি সজ্জাকারদের দ্বারাও করা যেতে পারে:

    models = {}
    
    def model(cls):
        models[cls.__name__] = cls
        return cls
    
    @model
    class A(object):
        pass

    বা স্পষ্টভাবে নিবন্ধকরণ ফাংশন সহ:

    models = {}
    
    def register_model(cls):
        models[cls.__name__] = cls
    
    class A(object):
        pass
    
    register_model(A)

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

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

    >>> class B(A):
    ...     pass
    ...
    >>> models
    {'A': <__main__.A class at 0x...> # No B :(
  2. রিফ্যাক্টরিং (শ্রেণীর বৈশিষ্ট্যগুলি সংশোধন করা বা নতুন যুক্ত করা):

    class ModelMetaclass(type):
        def __new__(meta, name, bases, attrs):
            fields = {}
            for key, value in attrs.items():
                if isinstance(value, Field):
                    value.name = '%s.%s' % (name, key)
                    fields[key] = value
            for base in bases:
                if hasattr(base, '_fields'):
                    fields.update(base._fields)
            attrs['_fields'] = fields
            return type.__new__(meta, name, bases, attrs)
    
    class Model(object):
        __metaclass__ = ModelMetaclass

    যখনই আপনি সাবগ্লাস Modelএবং কিছু Fieldবৈশিষ্ট্য সংজ্ঞায়িত করেন , তখন তাদের নামগুলি (আরও তথ্যমূলক ত্রুটি বার্তাগুলির জন্য উদাহরণস্বরূপ) ইনজেকশন দেওয়া হয় এবং একটি _fieldsঅভিধানে গ্রুপ করা হয় (সহজ পুনরাবৃত্তির জন্য, সমস্ত শ্রেণীর বৈশিষ্ট্য এবং এর সমস্ত বেস ক্লাসগুলি সন্ধান না করেই ' বৈশিষ্ট্য প্রতিবার):

    >>> class A(Model):
    ...     foo = Integer()
    ...
    >>> class B(A):
    ...     bar = String()
    ...
    >>> B._fields
    {'foo': Integer('A.foo'), 'bar': String('B.bar')}

    আবার, শ্রেণি সজ্জাকারীর সাথে এটি করা যেতে পারে (উত্তরাধিকার ছাড়াই):

    def model(cls):
        fields = {}
        for key, value in vars(cls).items():
            if isinstance(value, Field):
                value.name = '%s.%s' % (cls.__name__, key)
                fields[key] = value
        for base in cls.__bases__:
            if hasattr(base, '_fields'):
                fields.update(base._fields)
        cls._fields = fields
        return cls
    
    @model
    class A(object):
        foo = Integer()
    
    class B(A):
        bar = String()
    
    # B.bar has no name :(
    # B._fields is {'foo': Integer('A.foo')} :(

    বা স্পষ্টত:

    class A(object):
        foo = Integer('A.foo')
        _fields = {'foo': foo} # Don't forget all the base classes' fields, too!

    যদিও, পঠনযোগ্য এবং মেইনটেইনযোগ্য নন-মেটা প্রোগ্রামিংয়ের পক্ষে আপনার পক্ষের বিপরীতে, এটি আরও বেশি জটিল, নিরর্থক এবং ত্রুটিযুক্ত প্রবণ:

    class B(A):
        bar = String()
    
    # vs.
    
    class B(A):
        bar = String('bar')
        _fields = {'B.bar': bar, 'A.foo': A.foo}

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

class Metaclass(type):
    def __new__(meta, name, bases, attrs):
        return type.__new__(meta, 'foo', (int,), attrs)

class Baseclass(object):
    __metaclass__ = Metaclass

class A(Baseclass):
    pass

class B(A):
    pass

print A.__name__ # foo
print B.__name__ # foo
print issubclass(B, A)   # False
print issubclass(B, int) # True

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

যাইহোক, পাইথন 3-এ, মেটাক্লাসগুলিরও __prepare__পদ্ধতি রয়েছে যা আপনাকে ক্লাস বডিটিকে ম্যাপিং ব্যতীত অন্য কোনও ম্যাপিংয়ে মূল্যায়ন করতে দেয় dict, এইভাবে আদেশযুক্ত বৈশিষ্ট্য, ওভারলোড হওয়া গুণাবলী এবং অন্যান্য দুষ্ট কুল স্টাফকে সমর্থন করে:

import collections

class Metaclass(type):

    @classmethod
    def __prepare__(meta, name, bases, **kwds):
        return collections.OrderedDict()

    def __new__(meta, name, bases, attrs, **kwds):
        print(list(attrs))
        # Do more stuff...

class A(metaclass=Metaclass):
    x = 1
    y = 2

# prints ['x', 'y'] rather than ['y', 'x']

 

class ListDict(dict):
    def __setitem__(self, key, value):
        self.setdefault(key, []).append(value)

class Metaclass(type):

    @classmethod
    def __prepare__(meta, name, bases, **kwds):
        return ListDict()

    def __new__(meta, name, bases, attrs, **kwds):
        print(attrs['foo'])
        # Do more stuff...

class A(metaclass=Metaclass):

    def foo(self):
        pass

    def foo(self, x):
        pass

# prints [<function foo at 0x...>, <function foo at 0x...>] rather than <function foo at 0x...>

আপনি যুক্তি দিতে পারেন ক্রম কাউন্টারগুলির সাথে অর্ডারযুক্ত বৈশিষ্ট্য অর্জন করা যেতে পারে এবং ওভারলোডিং ডিফল্ট যুক্তি দিয়ে সিমুলেটেড করা যায়:

import itertools

class Attribute(object):
    _counter = itertools.count()
    def __init__(self):
        self._count = Attribute._counter.next()

class A(object):
    x = Attribute()
    y = Attribute()

A._order = sorted([(k, v) for k, v in vars(A).items() if isinstance(v, Attribute)],
                  key = lambda (k, v): v._count)

 

class A(object):

    def _foo0(self):
        pass

    def _foo1(self, x):
        pass

    def foo(self, x=None):
        if x is None:
            return self._foo0()
        else:
            return self._foo1(x)

আরও কুরুচিপূর্ণ হওয়ার পাশাপাশি এটিও কম নমনীয়: আপনি যদি আক্ষরিক বৈশিষ্ট্যগুলি, যেমন পূর্ণসংখ্যা এবং স্ট্রিংয়ের মতো অর্ডার করতে চান তবে কি হবে? যদি Noneএকটি বৈধ মান জন্য x?

প্রথম সমস্যাটি সমাধান করার জন্য এখানে একটি সৃজনশীল উপায়:

import sys

class Builder(object):
    def __call__(self, cls):
        cls._order = self.frame.f_code.co_names
        return cls

def ordered():
    builder = Builder()
    def trace(frame, event, arg):
        builder.frame = frame
        sys.settrace(None)
    sys.settrace(trace)
    return builder

@ordered()
class A(object):
    x = 1
    y = 'foo'

print A._order # ['x', 'y']

এবং দ্বিতীয়টি সমাধানের জন্য এখানে একটি সৃজনশীল উপায়:

_undefined = object()

class A(object):

    def _foo0(self):
        pass

    def _foo1(self, x):
        pass

    def foo(self, x=_undefined):
        if x is _undefined:
            return self._foo0()
        else:
            return self._foo1(x)

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

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

class MetaMetaclass(type):
    def __new__(meta, name, bases, attrs):
        def __new__(meta, name, bases, attrs):
            cls = type.__new__(meta, name, bases, attrs)
            cls._label = 'Made in %s' % meta.__name__
            return cls 
        attrs['__new__'] = __new__
        return type.__new__(meta, name, bases, attrs)

class China(type):
    __metaclass__ = MetaMetaclass

class Taiwan(type):
    __metaclass__ = MetaMetaclass

class A(object):
    __metaclass__ = China

class B(object):
    __metaclass__ = Taiwan

print A._label # Made in China
print B._label # Made in Taiwan

সম্পাদন করা

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


5
এটি একটি দুর্দান্ত উত্তর, সময়টি লিখে এবং একাধিক উদাহরণ দেওয়ার জন্য ধন্যবাদ
চেন এ।

"... এই ক্ষেত্রে মেটাক্লাসগুলির সুবিধা হ'ল উত্তরাধিকার, যেহেতু তারা কোনও সাবক্লাসের জন্য কাজ করে" - পাইথন 3 এ নয়, আমি মনে করি? আমি মনে করি এটি পাইথন 2 এ কাজ করে কারণ কোনও শিশু শ্রেণীর __metaclass__বৈশিষ্ট্যটি উত্তরাধিকার সূত্রে পাওয়া যায় , তবে পাইথন 3-এ এই বৈশিষ্ট্যটি আর বিশেষ নয় this পাইথন 3-তে এই "শিশুদের ক্লাসগুলিও পিতামাতার মেটাগ্লাস দ্বারা নির্মিত" জিনিসটির কোনও উপায় আছে কি? ?
ফোর্সব্রু

2
পাইথন 3-তেও এটি সত্য, কারণ A এর উত্তরাধিকারসূত্রে বি শ্রেণি বি, যার মেটাক্লাস এম, এম এরও একটি ধরণের, সুতরাং যখন বি মূল্যায়ন করা হয় তখন এম এটি তৈরির জন্য অনুরোধ করা হয় এবং এটি কার্যকরভাবে আপনাকে অনুমতি দেয় "যে কোনও সাবক্লাসে কাজ করা" (এ) এর জন্য। এটি বলার পরে, পাইথন ৩.6 অনেক সহজ প্রবর্তন করেছিল init_subclass, সুতরাং এখন আপনি বেসক্লাসে সাবক্লাসগুলি পরিচালনা করতে পারেন এবং সেই উদ্দেশ্যে আর কোনও মেটাক্লাসের প্রয়োজন নেই।
ড্যান গিত্তিক

এটি উজ্জ্বল, আমি মেটাক্লাসগুলিতে অনেকগুলি ব্লগ পোস্ট পড়েছি, কেবলমাত্র এটিই মেটাক্লাসের উপকারিতা এবং কনস এবং বিকল্পগুলি জানতে পারে।
ospider

36

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

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

    class Mp3File(MusicFile):
        extensions = ['.mp3']  # Register this type as a handler for mp3 files
        ...
        # Implementation of mp3 methods go here

    এর পরে মেটাক্লাস {'.mp3' : MP3File, ... }ইত্যাদির একটি অভিধান রক্ষণাবেক্ষণ করে এবং আপনি যখন কারখানার ফাংশনের মাধ্যমে কোনও হ্যান্ডলারের অনুরোধ করেন তখন উপযুক্ত ধরণের একটি অবজেক্ট তৈরি করে।

  • আচরণ বদলাচ্ছে। আপনি নির্দিষ্ট বৈশিষ্ট্যের সাথে একটি বিশেষ অর্থ সংযুক্ত করতে চাইতে পারেন, ফলাফল উপস্থিত থাকার সময় পরিবর্তিত আচরণের ফলে। উদাহরণস্বরূপ, যদি আপনি নামের সঙ্গে পদ্ধতি জন্য চেহারা করতে পারেন _get_fooএবং _set_fooএবং transparently তাদের বৈশিষ্ট্য রূপান্তর করুন। বাস্তব-জগতের উদাহরণ হিসাবে, আরও একটি সি-কাঠামোর সংজ্ঞা দেওয়ার জন্য আমি এখানে একটি রেসিপি লিখেছি। মেটাকগ্লাস ঘোষিত আইটেমগুলিকে স্ট্রাক্ট বিন্যাসের স্ট্রিংয়ে রূপান্তর করতে, উত্তরাধিকার পরিচালনা করা ইত্যাদি ব্যবহার করে এবং এর সাথে কাজ করতে সক্ষম শ্রেণি তৈরি করতে ব্যবহৃত হয়।

    অন্যান্য বাস্তব-বিশ্বের উদাহরণগুলির জন্য, বিভিন্ন ওআরএম , যেমন স্ক্ল্যাচেমির ওআরএম বা স্ক্লোবজেক্টের দিকে একবার নজর দিন । আবার, উদ্দেশ্যটি নির্দিষ্ট অর্থ (এখানে এসকিউএল কলাম সংজ্ঞা) ব্যাখ্যা করা।


3
ঠিক আছে, হ্যাঁ, সাবক্লাসগুলি ট্র্যাকিং করা হচ্ছে। তবে কেন আপনি কখনও তা চান? আপনার উদাহরণটি কেবল রেজিস্টার_সৌধিক_ফাইলে (এমপি 3 ফাইল, ['। এমপি 3']) এর জন্য অন্তর্নিহিত এবং স্পষ্ট উপায়টি আরও পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য। আমি যে খারাপ মামলার কথা বলছি তার উদাহরণ এটি।
আলী আফশার

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

10
আমি প্রতিটি সাবক্লাসের জন্য অতিরিক্ত রেজিস্ট্রেশন পদ্ধতির চেয়ে আরও বেশি ঘোষিত শৈলীর পছন্দ পছন্দ করি - যদি সমস্ত কিছু একক স্থানে আবৃত থাকে তবে আরও ভাল।
ব্রায়ান

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

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

17

টিম পিটারের ক্লাসিক উক্তি দিয়ে শুরু করা যাক:

ব্যবহারকারীর 99% এর চেয়ে বেশি চিন্তা করা উচিত মেটাক্লাসগুলি গভীর যাদু। আপনার যদি তাদের প্রয়োজন হয় কিনা তা আপনি যদি ভাবেন তবে আপনারা (আসলে যাঁদের প্রকৃত প্রয়োজন তাদের অবশ্যই প্রয়োজন যে তাদের তাদের প্রয়োজন know টিম পিটার্স (সিএলপি পোস্ট 2002-12-22)

এটি বলার পরে, আমি (পর্যায়ক্রমে) মেটাক্লাসের সত্যিকারের ব্যবহারগুলি চালিয়ে যাচ্ছি। মনে মনে যেটি আসে তা হ'ল জ্যাঙ্গোতে যেখানে আপনার সমস্ত মডেল মডেলগুলি থেকে উত্তরাধিকারী। মডেল। মডেলস.মোডেল ঘুরেফিরে, আপনার ডিবি মডেলগুলিকে জ্যাঙ্গোর ওআরএম সদৃশতা মোড়ানোর জন্য কিছু গুরুতর যাদু করে। সেই যাদুটি মেটাক্লাসগুলির মাধ্যমে ঘটে। এটি সমস্ত ধরণের ব্যতিক্রম শ্রেণি, ব্যবস্থাপক শ্রেণী ইত্যাদি তৈরি করে

গল্পের শুরুতে জ্যাঙ্গো / ডিবি / মডেল / বেস.পি, ক্লাস মডেলবেস () দেখুন।


ঠিক আছে, হ্যাঁ, আমি বিন্দু দেখতে। আমি "কী" বা "কেন" মেটাক্লাস ব্যবহার করব তা অবাক করি না, আমি "কে" এবং "কী" তা অবাক করি। ওআরএমগুলি এখানে একটি সাধারণ ঘটনা see দুর্ভাগ্যক্রমে এসকিএএলএলচেমির তুলনায় জ্যাঙ্গোর ওআরএম বেশ দুর্বল যার জাদু কম। যাদুটি খারাপ, এবং এর জন্য মেটাক্লাসগুলি সত্যই প্রয়োজনীয় নয়।
আলী আফশার

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

6

পাইথনে ডোমেন সুনির্দিষ্ট ভাষাগুলি তৈরির জন্য মেটাক্লাসগুলি কার্যকর হতে পারে। কংক্রিটের উদাহরণ হ'ল জ্যাঙ্গো, এসকিউএলজেক্টের ডেটাবেস স্কিম্যাটার ডিক্যারেটিভ সিনট্যাক্স।

আয়ান বাইকিংয়ের একটি কনজারভেটিভ মেটাক্লাসের একটি প্রাথমিক উদাহরণ :

আমি যে মেটাচ্লাসগুলি ব্যবহার করেছি তা মূলত প্রোগ্রামিংয়ের এক ধরণের ঘোষিত স্টাইলকে সমর্থন করে। উদাহরণস্বরূপ, একটি বৈধতা স্কিমা বিবেচনা করুন:

class Registration(schema.Schema):
    first_name = validators.String(notEmpty=True)
    last_name = validators.String(notEmpty=True)
    mi = validators.MaxLength(1)
    class Numbers(foreach.ForEach):
        class Number(schema.Schema):
            type = validators.OneOf(['home', 'work'])
            phone_number = validators.PhoneNumber()

কিছু অন্যান্য কৌশল: পাইথন (পিডিএফ) এ ডিএসএল তৈরির উপকরণ

সম্পাদনা (আলি দ্বারা): সংগ্রহ এবং দৃষ্টান্ত ব্যবহার করে এটি করার একটি উদাহরণ হ'ল আমি পছন্দ করি। গুরুত্বপূর্ণ ঘটনাটি হ'ল দৃষ্টান্তগুলি, যা আপনাকে আরও শক্তি দেয় এবং মেটাক্লাসগুলি ব্যবহার করার কারণটি নির্মূল করে। আরও লক্ষণীয় যে আপনার উদাহরণে ক্লাস এবং দৃষ্টান্তগুলির মিশ্রণ ব্যবহার করা হয়েছে, এটি অবশ্যই একটি ইঙ্গিত যা আপনি কেবল मेटाটগ্লাস দিয়ে এটি করতে পারবেন না। এবং এটি করার একটি সত্যই অ-অভিন্ন পদ্ধতি তৈরি করে।

number_validator = [
    v.OneOf('type', ['home', 'work']),
    v.PhoneNumber('phone_number'),
]

validators = [
    v.String('first_name', notEmpty=True),
    v.String('last_name', notEmpty=True),
    v.MaxLength('mi', 1),
    v.ForEach([number_validator,])
]

এটি নিখুঁত নয়, তবে ইতিমধ্যে প্রায় শূন্য জাদু রয়েছে, মেটাক্লাসের প্রয়োজন নেই এবং উন্নত অভিন্নতা রয়েছে।


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

1
@ অলি এ: মেটাক্লাসের মাধ্যমে ঘোষণামূলক বাক্য গঠন এবং সাধারণ সংগ্রহের উদাহরণের ভিত্তিতে একটি পদ্ধতির মধ্যে পার্শ্ববর্তী পার্শ্ববর্তী তুলনা করার একটি দৃ concrete় উদাহরণ সরবরাহ করতে আপনাকে স্বাগতম।
jfs

@ অলি এ: সংগ্রহের শৈলীর উদাহরণ যোগ করতে আপনি আমার উত্তরটি অন্তর্ভুক্ত সম্পাদনা করতে পারেন।
jfs

ঠিক আছে যে। দুঃখিত, আমি আজ খুব তাড়াহুড়ো করে আছি, তবে পরে / কাল যেকোন প্রশ্নের উত্তর দেওয়ার চেষ্টা করব। শুভ ছুটির দিন!
আলী আফশার

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

6

মেটাক্লাস ব্যবহারের একটি যুক্তিসঙ্গত নিদর্শন একবার যখন কোনও শ্রেণিটি বারবার পরিবর্তে যখন একই শ্রেণিটি তাত্ক্ষণিক হয় ততক্ষণ সংজ্ঞায়িত করা হয়।

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

তবে এমনকি শুধুমাত্র একটি বিশেষ শ্রেণীর সাথে এবং কোন প্রত্যাশিত এক্সটেনশন না থাকলেও __new__এবং __init__একটি মেটাক্লাস ক্লাস সংজ্ঞা সংস্থায় বিশেষ উদ্দেশ্যমূলক কোড এবং স্বাভাবিক defএবং classবিবৃতিগুলিকে অন্তর্নির্মিত করার চেয়ে শ্রেণি পরিবর্তনগুলি বা অন্যান্য গ্লোবাল ডেটা শুরু করার একটি ক্লিনার উপায় ।


5

ফ্লিকার এপিআইয়ের জন্য মোড়ক লেখার সময় আমি পাইথনে কেবলমাত্র মেটাক্লাস ব্যবহার করেছি।

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

# Both the photo type and the flickr.photos.search API method 
# are generated at "run-time"
for photo in flickr.photos.search(text=balloons):
    print photo.description

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


2
আপনি মেটাক্লাস ব্যবহার না করে গতিশীলভাবে প্রকারগুলি তৈরি করতে পারেন। >>> সহায়তা (প্রকার)
আলী আফশার

8
এমনকি যদি আপনি এটা সচেতন না হন, আপনি হয় তারপর metaclasses ব্যবহার করে। টাইপ একটি মেটাক্লাস, আসলে সবচেয়ে সাধারণ one :-)
ভিকি

5

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

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

class test(baseclass_with_metaclass):
    method_maker_value = "hello"

"হ্যালো" (বিশেষত স্ট্রিংয়ের শেষে "হ্যালো" যুক্ত একটি পদ্ধতি বলুন) এর উপর ভিত্তি করে বিশেষ বৈশিষ্ট্যযুক্ত শ্রেণিতে এমন একটি পদ্ধতি তৈরি করে এমন একটি মেটাক্লাস থাকতে পারে। এটি রক্ষণাবেক্ষণের পক্ষে নিশ্চিত হওয়া ভাল যে আপনি যে প্রতি সাবক্লাস তৈরি করেছেন তার পরিবর্তে আপনার যে পদ্ধতিটি লিখতে হবে তা হ'ল পদ্ধতি_মেকার_মূল্য ue

যদিও এর প্রয়োজন এতটাই বিরল এবং কেবল টাইপিংয়ের কিছুটা বাদ দেয় যে আপনার যদি পর্যাপ্ত পরিমাণ কোডবেস না থাকে তবে এটি বিবেচনা করার মতো নয়।


5

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

এটি বলেছিল, বিদ্যমান ক্লাসটি সংশোধন করতে সক্ষম হতে এটি স্মলটালক এবং রুবিতে খুব সহজ হতে পারে, তবে পাইথন সরাসরি তা করতে পছন্দ করে না।

পাইথনে মেটাক্লাসিংয়ের বিষয়ে একটি দুর্দান্ত বিকাশকারী ওয়ার্কস নিবন্ধ রয়েছে যা সাহায্য করতে পারে। Wikipedia নিবন্ধটি বেশ ভাল।


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

1
প্রশ্ন ফিরে দেখুন।
চার্লি মার্টিন

4

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

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

এর একটি ঝরঝরে দিক threadboxহ'ল এটি কোন ক্লাসটি ক্লোন করে তা যত্ন করে না। এটি যদি প্রয়োজন হয় তবে সমস্ত বেস ক্লাস কীভাবে একটি মেটাক্লাস দ্বারা স্পর্শ করা যায় তার একটি উদাহরণ সরবরাহ করে। আরও একটি সুবিধা যা মেটাক্লাসগুলির সাথে আসে তা হ'ল তারা উত্তরাধিকার সূত্রেও ক্লাস চালায়। যে প্রোগ্রামগুলি নিজেরাই লেখেন - কেন নয়?


4

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

(গালে লিখিত জিহ্বা, তবে আমি এই ধরণের উদ্বিগ্নতা দেখেছি D জ্যাঙ্গো একটি নিখুঁত উদাহরণ)


7
আমি নিশ্চিত না জাজানোতে প্রেরণাটি একই রকম ছিল।
আলী আফশার

3

মেটাক্লাসগুলি প্রোগ্রামিং প্রতিস্থাপন করছে না! এগুলি কেবল একটি কৌশল যা স্বয়ংক্রিয়ভাবে বা কিছু মার্জিত কিছু কাজ করতে পারে। এর একটি ভাল উদাহরণ পাইগমেন্টস সিনট্যাক্স হাইলাইটিং লাইব্রেরি। এটির একটি ক্লাস রয়েছে RegexLexerযা ব্যবহারকারীকে ক্লাসে নিয়মিত প্রকাশ হিসাবে লেক্সিং নিয়মের একটি সেটকে সংজ্ঞায়িত করতে দেয়। সংজ্ঞাগুলি একটি কার্যকর পার্সারে পরিণত করতে একটি মেটাক্লাস ব্যবহার করা হয়।

তারা লবণের মতো; এটি খুব বেশি ব্যবহার করা সহজ।


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

4
কারণ একটি শ্রেণি চমৎকার লেক্সারের ধারণাটিকে ধারণ করে এবং অন্যান্য উপকারী পদ্ধতি যেমন অনুমান_তীত ফাইল () ইত্যাদি রয়েছে
পিটারসন

3

ক্লাসে কিছু বৈশিষ্ট্য সরবরাহ করার জন্য আমি যেভাবে মেটাক্লাস ব্যবহার করেছি। উদাহরণস্বরূপ নিন:

class NameClass(type):
    def __init__(cls, *args, **kwargs):
       type.__init__(cls, *args, **kwargs)
       cls.name = cls.__name__

করা হবে নাম যে বর্গ যে NameClass দিকে নির্দেশ ক্লাসের অধীনে একটি ক্লাস সেট আছে হবে অ্যাট্রিবিউট।


5
হ্যাঁ, এটি কাজ করে। আপনি একটি সুপারক্লাসও ব্যবহার করতে পারেন যা কমপক্ষে স্পষ্ট এবং কোড অনুসারে অনুসরণযোগ্য। আগ্রহের বাইরে, আপনি কীসের জন্য এটি ব্যবহার করেছেন?
আলী আফশার

2

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

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


1

আমাকে সম্প্রতি http://census.ire.org/data/bulkdata.html থেকে মার্কিন আদমশুমারির তথ্য দিয়ে জনবহুল একটি ডাটাবেস টেবিলের আশেপাশে একটি এসকিউএএলএলকেমি মডেলটিকে ঘোষিতভাবে সংজ্ঞায়িত করতে সহায়তা করার জন্য একটি মেটাক্লাস ব্যবহার করতে হয়েছিল

আইআরই আদমশুমারি ডাটা টেবিলগুলির জন্য ডেটাবেস শেল সরবরাহ করে , যা p012015, p012016, p012017 ইত্যাদির আদমশুমারি ব্যুরো থেকে নামকরণের সম্মেলনের পরে পূর্ণসংখ্যা কলাম তৈরি করে etc.

আমি model_instance.p012017ক) একটি সিনট্যাক্স ব্যবহার করে এই কলামগুলি অ্যাক্সেস করতে সক্ষম হতে চেয়েছিলাম , খ) আমি কী করছি তা সম্পর্কে মোটামুটি স্পষ্ট হওয়া এবং গ) মডেলটির কয়েক ডজন ক্ষেত্র স্পষ্টভাবে সংজ্ঞায়িত করতে হবে না, তাই আমি এসকিউএলএলচেমির DeclarativeMetaবিস্তৃত অংশটি পুনরাবৃত্তি করতে সাবক্লাস করেছি কলামগুলি এবং স্বয়ংক্রিয়ভাবে কলামগুলির সাথে সম্পর্কিত মডেল ক্ষেত্রগুলি তৈরি করে:

from sqlalchemy.ext.declarative.api import DeclarativeMeta

class CensusTableMeta(DeclarativeMeta):
    def __init__(cls, classname, bases, dict_):
        table = 'p012'
        for i in range(1, 49):
            fname = "%s%03d" % (table, i)
            dict_[fname] = Column(Integer)
            setattr(cls, fname, dict_[fname])

        super(CensusTableMeta, cls).__init__(classname, bases, dict_)

তারপরে আমি এই মডেল সংজ্ঞাটি আমার মডেল সংজ্ঞার জন্য ব্যবহার করতে এবং মডেলটিতে স্বয়ংক্রিয়ভাবে গণিত ক্ষেত্রগুলি অ্যাক্সেস করতে পারি:

CensusTableBase = declarative_base(metaclass=CensusTableMeta)

class P12Tract(CensusTableBase):
    __tablename__ = 'ire_p12'

    geoid = Column(String(12), primary_key=True)

    @property
    def male_under_5(self):
        return self.p012003

    ...

1

একটা বৈধ ব্যবহারের বর্ণনা মনে করা হয় এখানে একটি ক্লাসের অধীনে একটি ক্লাস সঙ্গে rewriting পাইথন Docstrings -।


0

বাইনারি পার্সারের জন্য এটি ব্যবহার সহজ করে তুলতে আমাকে একবার ব্যবহার করতে হয়েছিল। আপনি তারে উপস্থিত ক্ষেত্রের বৈশিষ্ট্য সহ একটি বার্তা শ্রেণি সংজ্ঞায়িত করেন। এগুলি থেকে চূড়ান্ত তারের ফর্ম্যাটটি নির্মাণের জন্য তাদের যেভাবে ঘোষণা করা হয়েছিল সেগুলি তাদের অর্ডার করার প্রয়োজন ছিল। আপনি যদি অর্ডারযুক্ত নেমস্পেস ডিক ব্যবহার করেন তবে আপনি मेटाটাগ্লাসের সাহায্যে এটি করতে পারেন। প্রকৃতপক্ষে, এটি মেটাক্লাসগুলির উদাহরণগুলিতে:

https://docs.python.org/3/reference/datamodel.html#metaclass-example

তবে সাধারণভাবে: খুব সাবধানতার সাথে মূল্যায়ন করুন, যদি আপনার সত্যিই মেটাচ্লাসগুলির যুক্ত জটিলতার প্রয়োজন হয়।


0

@ ড্যান গিত্তিকের উত্তরটি দুর্দান্ত

শেষের উদাহরণগুলি অনেকগুলি বিষয় পরিষ্কার করতে পারে, আমি এটিকে অজগর 3 এ পরিবর্তন করে কিছু ব্যাখ্যা দিয়েছি:

class MetaMetaclass(type):
    def __new__(meta, name, bases, attrs):
        def __new__(meta, name, bases, attrs):
            cls = type.__new__(meta, name, bases, attrs)
            cls._label = 'Made in %s' % meta.__name__
            return cls

        attrs['__new__'] = __new__
        return type.__new__(meta, name, bases, attrs)

#China is metaclass and it's __new__ method would be changed by MetaMetaclass(metaclass)
class China(MetaMetaclass, metaclass=MetaMetaclass):
    __metaclass__ = MetaMetaclass

#Taiwan is metaclass and it's __new__ method would be changed by MetaMetaclass(metaclass)
class Taiwan(MetaMetaclass, metaclass=MetaMetaclass):
    __metaclass__ = MetaMetaclass

#A is a normal class and it's __new__ method would be changed by China(metaclass)
class A(metaclass=China):
    __metaclass__ = China

#B is a normal class and it's __new__ method would be changed by Taiwan(metaclass)
class B(metaclass=Taiwan):
    __metaclass__ = Taiwan


print(A._label)  # Made in China
print(B._label)  # Made in Taiwan
  • সবকিছু বস্তু, সুতরাং শ্রেণি অবজেক্ট
  • ক্লাস অবজেক্টটি মেটাক্লাস দ্বারা তৈরি করা হয়
  • টাইপ থেকে প্রাপ্ত সমস্ত শ্রেণীর নাম মেটাক্লাস
  • মেটাক্লাস ক্লাস তৈরি নিয়ন্ত্রণ করতে পারে
  • মেটাক্লাস মেটাক্লাস তৈরি করাও নিয়ন্ত্রণ করতে পারে (যাতে এটি চিরতরে লুপ হয়ে যায়)
  • এটি রূপান্তরকামী ... আপনি চলমান সময়ে টাইপ সিস্টেমটি নিয়ন্ত্রণ করতে পারেন
  • আবার, সবকিছু বস্তু, এটি একটি অভিন্ন সিস্টেম, টাইপ তৈরির ধরন এবং টাইপ তৈরির উদাহরণ

0

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

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

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