পাইথনের অন্য শ্রেণীর ভিতরে কোনও শ্রেণি সংজ্ঞায়িত করার কোনও সুবিধা আছে?


106

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

আমার কাছে এমন কোড রয়েছে যা দেখতে এমন কিছু দেখাচ্ছে:

class DownloadThread:
    def foo(self):
        pass

class DownloadManager():
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadThread())

তবে এখন আমি ভাবছি বাসা বাঁধাই ভাল n কিছুটা এইরকম:

class DownloadManager():
    class DownloadThread:
        def foo(self):
            pass
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadManager.DownloadThread())

উত্তর:


121

আপনি যখন এটি "অভ্যন্তরীণ" শ্রেণিটি এক-অফের হয়ে উঠতে পারেন, যা কখনই বাইরের শ্রেণীর সংজ্ঞার বাইরে ব্যবহৃত হয় না । উদাহরণস্বরূপ একটি মেটাক্লাস ব্যবহার করা, এটি কখনও কখনও করা সহজ y

class Foo(object):
    class __metaclass__(type):
        .... 

আলাদাভাবে কোনও মেটাক্লাস সংজ্ঞায়িত করার পরিবর্তে, যদি আপনি কেবল এটি একবার ব্যবহার করেন।

কেবলমাত্র অন্য সময় যেমন আমি নেস্টেড ক্লাস ব্যবহার করেছি, আমি বাইরের ক্লাসকে কেবলমাত্র একটি নেমস্পেস হিসাবে ব্যবহার করেছি ঘনিষ্ঠভাবে সম্পর্কিত ক্লাসগুলির একসাথে গ্রুপ করার জন্য:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

তারপরে অন্য মডিউল থেকে, আপনি গ্রুপটি আমদানি করতে পারেন এবং এগুলিকে Group.cls1, গ্রুপ.cls2 হিসাবে উল্লেখ করতে পারেন one


13
আমি-তর্ক করব যে দ্বিতীয় ক্ষেত্রে, আপনাকে অবশ্যই নির্ধারিতভাবে মডিউল বা প্যাকেজ ব্যবহার করে ভালভাবে পরিবেশন করা হবে যা নামের জায়গা হিসাবে নকশাকৃত।
ম্যাথু ট্রেভর

5
এটি একটি দুর্দান্ত উত্তর। সহজ, বিন্দুতে এবং মডিউলগুলি ব্যবহারের বিকল্প পদ্ধতির উল্লেখ করে। +1
কর্নস্মিথ

5
কেবল রেকর্ডের জন্য, যারা জেদীভাবে তাদের কোডকে শ্রেণিবদ্ধ প্যাকেজ এবং যথাযথ মডিউলগুলিতে সংগঠিত করতে পারেন না বা তাদের নাম স্থান হিসাবে ক্লাস ব্যবহার করা কখনও কখনও কিছু না ব্যবহার করার চেয়ে ভাল হতে পারে।
একিউম্যানাস

19

আমি পাইথন জানি না, তবে আপনার প্রশ্নটি খুব সাধারণ বলে মনে হচ্ছে। পাইথনের সাথে নির্দিষ্ট হলে আমাকে উপেক্ষা করুন I

ক্লাস বাসা বাঁধাই সমস্ত সুযোগ সম্পর্কে। আপনি যদি ভাবেন যে একটি শ্রেণি কেবলমাত্র অন্য একটি শ্রেণীর প্রসঙ্গে বোঝা যাবে তবে পূর্ববর্তী সম্ভবত নেস্টেড ক্লাসে পরিণত হওয়ার জন্য ভাল প্রার্থী।

হেল্পার ক্লাসগুলিকে বেসরকারী, নেস্টেড ক্লাস হিসাবে তৈরি করা একটি সাধারণ প্যাটার্ন।


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

7

নেস্টেড বর্গের জন্য আরও একটি ব্যবহার রয়েছে, যখন কেউ উত্তরাধিকার সূত্রে প্রাপ্ত বর্গ তৈরি করতে চায় যার বর্ধিত ক্রিয়াকলাপগুলি নির্দিষ্ট নেস্টেড শ্রেণিতে আবদ্ধ থাকে।

এই উদাহরণটি দেখুন:

class foo:

  class bar:
    ...  # functionalities of a specific sub-feature of foo

  def __init__(self):
    self.a = self.bar()
    ...

  ...  # other features of foo


class foo2(foo):

  class bar(foo.bar):
    ... # enhanced functionalities for this specific feature

  def __init__(self):
    foo.__init__(self)

নোট করুন যে কনস্ট্রাক্টরে fooরেখাটি self.a = self.bar()নির্মাণ করবে foo.barযখন নির্মিত বস্তুটি আসলে একটি fooবস্তু এবং afoo2.bar যখন অবজেক্ট যখন নির্মাণ করা হচ্ছে বাস্তবে একটি foo2বস্তু হয়।

পরিবর্তে barশ্রেণীর বাইরে শ্রেণি সংজ্ঞায়িত করা fooহয়, পাশাপাশি উত্তরাধিকারসূত্রে প্রাপ্ত সংস্করণটি (যা bar2উদাহরণস্বরূপ বলা হবে ), তবে নতুন শ্রেণীর সংজ্ঞা দেওয়া foo2আরও বেশি বেদনাদায়ক হবে, কারণ এর কনডাক্টরের foo2প্রথম লাইনের পরিবর্তে প্রয়োজন হবে self.a = bar2(), যা পুরো নির্মাণকারীকে পুনরায় লেখার ইঙ্গিত দেয়।


6

এটি করার সত্যিই কোনও লাভ নেই, আপনি যদি মেটাক্লাসগুলি নিয়ে কাজ করে থাকেন তবে।

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

নাম, অভিধান এবং ভিত্তিগুলি সমস্তই মেটাক্লাস ফাংশনে প্রেরণ করা হয় এবং তারপরে শ্রেণি: স্যুটটি ছিল সেই সুযোগে এটি ভেরিয়েবলের 'নাম' হিসাবে নির্ধারিত হয়।

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


3
অসম্মতি: নেস্টিং ব্যতিক্রম শ্রেণিগুলি খুব দরকারী, কারণ আপনার শ্রেণীর ব্যবহারকারীরা কোনও অগোছালো আমদানি না করেই আপনার কাস্টম ব্যতিক্রমগুলি পরীক্ষা করতে পারেন। যেমনexcept myInstanceObj.CustomError, e:
RobM

2
@ জারুব, কেন এমন খারাপ?
রবার্ট সিমার

5

আপনি ক্লাস জেনারেটর হিসাবে একটি ক্লাস ব্যবহার করা যেতে পারে। পছন্দ করুন (কিছুটা কাফ কোডের বাইরে :)

class gen(object):
    class base_1(object): pass
    ...
    class base_n(object): pass

    def __init__(self, ...):
        ...
    def mk_cls(self, ..., type):
        '''makes a class based on the type passed in, the current state of
           the class, and the other inputs to the method'''

আমার মনে হচ্ছে আপনার যখন এই কার্যকারিতাটির প্রয়োজন হবে তখন এটি আপনার কাছে খুব স্পষ্ট হবে। আপনার যদি অনুরূপ কিছু করার দরকার না হয় তবে এটি সম্ভবত ভাল ব্যবহারের ক্ষেত্রে নয়।


1

না, রচনা মানে বাসা বাঁধে না। যদি আপনি এটি বাইরের শ্রেণির নেমস্পেসে আরও লুকিয়ে রাখতে চান তবে কোনও নেস্টেড ক্লাস থাকা অর্থহীন।

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

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