পাইথনে পুরাতন স্টাইল এবং নতুন স্টাইলের ক্লাসগুলির মধ্যে পার্থক্য কী?


উত্তর:


559

থেকে নতুন স্টাইলের এবং ক্লাসিক শ্রেণীর :

পাইথন ২.১ অবধি, পুরানো স্টাইলের ক্লাসগুলি কেবলমাত্র ব্যবহারকারীর জন্য উপলব্ধ স্বাদ ছিল।

(পুরোনো শৈলী) ক্লাসের ধারণা ধরনের ধারণা থেকে সম্পর্কহীন: যদি xএকটি পুরানো ধাঁচের ক্লাসের একটা নিদর্শন হয়, তাহলে x.__class__ বর্গ designates xকিন্তু type(x)সর্বদা <type 'instance'>

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

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

যদি এক্স কোনও নতুন-স্টাইলের শ্রেণীর উদাহরণ, তবে type(x)সাধারণত এটি একই রকম হয় x.__class__(যদিও এটির নিশ্চয়তা নেই - একটি নতুন-শৈলিক শ্রেণীর উদাহরণটি এর জন্য ফেরত মানকে ওভাররাইড করার অনুমতি দেয় x.__class__)।

নতুন-স্টাইলের ক্লাস চালু করার জন্য প্রধান প্রেরণা হল একটি সম্পূর্ণ মেটা-মডেল সহ ইউনিফাইড অবজেক্ট মডেল সরবরাহ করা

এটিতে বেশ কয়েকটি তাত্ক্ষণিক সুবিধাও রয়েছে যেমন সর্বাধিক অন্তর্নির্মিত ধরণের সাবক্লাস করার ক্ষমতা বা "বর্ণনাকারী" প্রবর্তন যেমন গণিত বৈশিষ্ট্য সক্ষম করে।

উপযুক্ততা কারণে, ক্লাস এখনো ডিফল্টরূপে পুরোনো শৈলী হয়

নতুন স্টাইলের ক্লাসগুলি অন্য নতুন-স্টাইলের ক্লাসকে (অর্থাত্ একটি টাইপ) প্যারেন্ট ক্লাস হিসাবে নির্দিষ্ট করে তৈরি করা হয় বা অন্য কোনও পিতামাতার প্রয়োজন না হলে "শীর্ষ-স্তরের প্রকার" অবজেক্টটি তৈরি করা হয়।

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

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

পাইথন 3-এ কেবল নতুন-স্টাইলের ক্লাস রয়েছে

আপনি সাবক্লাস থেকে সাবক্লাস করেছেন কিনা তা বিবেচনাধীন objectনয়, ক্লাসগুলি পাইথন 3-এ নতুন-স্টাইল।


41
এই পার্থক্যের কোনওটিই নতুন-স্টাইলের ক্লাসগুলি ব্যবহার করার বাধ্যতামূলক কারণগুলির মতো শোনাচ্ছে না, তবুও সবাই বলেছে আপনার সর্বদা নতুন শৈলী ব্যবহার করা উচিত। আমি যদি হাঁসের টাইপিংয়ের মতো ব্যবহার করি তবে আমার কখনই ব্যবহারের দরকার নেই type(x)। যদি আমি কোনও বিল্ট ইন টাইপ সাবক্লাসিং না করে থাকি তবে নতুন স্টাইলের ক্লাসগুলির মধ্যে আমি দেখতে পাচ্ছি এমন কোনও সুবিধা হবে বলে মনে হয় না। এর অসুবিধাও রয়েছে, যা অতিরিক্ত টাইপ করা (object)
পুনরাবৃত্ত

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

21
@ ব্যবহারকারীর: পুরানো স্টাইলের ক্লাসগুলি ২.7-তে যেমন ছিল ২.১% তে একই রকম আচরণ করেছে এবং, কারণ খুব কম লোক এমনকি কোরিকগুলি মনে রাখে, এবং ডকুমেন্টেশনগুলি তাদের বেশিরভাগ নিয়ে আর আলোচনা করে না, তারা আরও খারাপ। উপরের ডকুমেন্টেশনের উদ্ধৃতিটিতে সরাসরি এটি বলা হয়েছে: "ফিক্স" রয়েছে যা পুরানো-শৈলিক শ্রেণিতে প্রয়োগ করা যায়নি। পাইথন ২.১-এর পর থেকে অন্য কারও সাথে কারও মোকাবেলা করা হয়নি এবং আপনি যদি ডকুমেন্টেশনটি আরও ব্যাখ্যা না করেন তবে পুরানো-শৈলীর ক্লাস ব্যবহার করবেন না Un


5
যে কেউ ভাবছেন, পাইথন 3-তে অবজেক্টের থেকে স্পষ্টত উত্তরাধিকার লাভ করার একটি ভাল কারণ হ'ল এটি পাইথনের একাধিক সংস্করণকে সমর্থন করে।
jpmc26

307

ঘোষণা-অনুযায়ী:

নতুন স্টাইলের ক্লাসগুলি অবজেক্ট থেকে বা অন্য নতুন স্টাইলের ক্লাস থেকে উত্তরাধিকারী ।

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

পুরাতন স্টাইলের ক্লাস হয় না।

class OldStyleClass():
    pass

পাইথন 3 দ্রষ্টব্য:

পাইথন 3 পুরানো শৈলীর ক্লাস সমর্থন করে না, সুতরাং উপরের ফলাফলগুলি একটি নতুন-শৈলীর শ্রেণিতে উল্লিখিত হয়।


24
যদি কোনও নতুন-শৈলীর শ্রেণি অন্য নতুন শৈলীর শ্রেণীর থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়, তবে প্রসারিত হয়ে তা উত্তরাধিকার সূত্রে প্রাপ্ত হয় object
অ্যারোনস্টার্লিং

2
এটি কি পুরানো স্টাইলের পাইথন ক্লাসের একটি ভুল উদাহরণ? class AnotherOldStyleClass: pass
অঙ্কুর আগরওয়াল

11
@ অবসি আমি বিশ্বাস করি class A: passএবং class A(): passএটি কঠোর সমতুল্য। প্রথম মানে "একজন কোনো পিতা বা মাতা ক্লাসের উত্তরাধিকারী নেই" এবং দ্বিতীয় উপায়ে "কোন পিতা বা মাতা শ্রেণীর উত্তরাধিকারী" । এটি বেশ একইরকম not isএবংis not
আইকাম

5
পার্শ্ব নোট হিসাবে, 3. এক্স এর জন্য, "অবজেক্ট" এর উত্তরাধিকার স্বয়ংক্রিয়ভাবে ধরে নেওয়া হয় (যার অর্থ আমরা 3.X এ "অবজেক্ট" উত্তরাধিকারী না হওয়ার কোনও উপায় পাইনি)। পশ্চাদপদ সামঞ্জস্যতার কারণে, যদিও "(অবজেক্ট)" রাখা এখানে খারাপ নয়।
ইয়ো হিশিয়াও

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

224

পুরানো এবং নতুন স্টাইলের ক্লাসগুলির মধ্যে গুরুত্বপূর্ণ আচরণের পরিবর্তন

  • সুপার যোগ
  • এমআরও পরিবর্তন হয়েছে (নীচে বর্ণিত)
  • বর্ণনাকারী যুক্ত
  • নতুন স্টাইলের শ্রেণীর অবজেক্টগুলি উত্পন্ন করা যাবে না যদি না প্রাপ্ত হয় Exception(নীচে উদাহরণস্বরূপ)
  • __slots__ যোগ

এমআরও (পদ্ধতি সমাধানের আদেশ) পরিবর্তন হয়েছে

এটি অন্যান্য উত্তরে উল্লিখিত ছিল, তবে এখানে ক্লাসিক এমআরও এবং সি 3 এমআরও (নতুন স্টাইলের ক্লাসে ব্যবহৃত) এর মধ্যে পার্থক্যের একটি দৃ .় উদাহরণ পাওয়া যায়।

প্রশ্নটি এমন ক্রম যা ক্রমযুক্ত বৈশিষ্ট্যগুলিতে (যার মধ্যে পদ্ধতি এবং সদস্য ভেরিয়েবলগুলি অন্তর্ভুক্ত) একাধিক উত্তরাধিকারে অনুসন্ধান করা হয়।

ক্লাসিক ক্লাসগুলি বাম থেকে ডানে গভীরতার প্রথম অনুসন্ধান করে। প্রথম ম্যাচে থামুন। তাদের __mro__বৈশিষ্ট্য নেই।

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

নতুন স্টাইলের ক্লাস এমআরও একক ইংরেজী বাক্যে সংশ্লেষ করা আরও জটিল। এটি বিস্তারিতভাবে এখানে ব্যাখ্যা করা হয় । এর বৈশিষ্ট্যগুলির মধ্যে একটি হ'ল একটি বেস ক্লাস কেবল তার সমস্ত উত্পন্ন ক্লাস হয়ে গেলেই অনুসন্ধান করা হয়। তাদের __mro__বৈশিষ্ট্য রয়েছে যা অনুসন্ধানের ক্রমটি দেখায়।

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

নতুন স্টাইলের শ্রেণীর অবজেক্টগুলি উত্পন্ন করা যায় না যদি না থেকে প্রাপ্ত হয় Exception

পাইথনের আশেপাশে 2.5 টি অনেক ক্লাস করা যায় এবং পাইথন ২.6 এর আশেপাশে এটি সরানো হয়েছিল। পাইথন ২.7.৩ এ:

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False

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

40

পুরানো শৈলীর শ্রেণীর বৈশিষ্ট্যগুলি অনুসন্ধানের জন্য এখনও সামান্য দ্রুত faster এটি সাধারণত গুরুত্বপূর্ণ নয়, তবে এটি পারফরম্যান্স-সংবেদনশীল পাইথন ২.x কোডে কার্যকর হতে পারে:

[3] এ: ক্লাস এ:
   ...: Def __init __ (স্ব):
   ...: self.a = 'হাই সেখানে'
   ...:

[4] এ: শ্রেণি বি (অবজেক্ট):
   ...: Def __init __ (স্ব):
   ...: self.a = 'হাই সেখানে'
   ...:

[]] এ: অওবজ = এ ()
[7] এ: ববজ = বি ()

[8] এ:% সময়কাল aobj.a
10000000 লুপ, লুপ প্রতি 3: 78.7 এনএস এর মধ্যে সেরা

[10] এ:% টাইমাইট ববজ.এ
10000000 লুপ, প্রতি লুপে 3: 86.9 এনএসের মধ্যে সেরা

5
আপনি যে অনুশীলন করে দেখেছেন তা আকর্ষণীয়, আমি কেবল এটি পড়েছি কারণ নতুন স্টাইলের ক্লাসগুলি, যখন তারা উদাহরণস্বরূপ ডিকের মধ্যে এটি বৈশিষ্ট্যটি খুঁজে পেয়েছে, একটি বিবরণ আছে কিনা তা কাজ করার জন্য একটি অতিরিক্ত অনুসন্ধান করতে হবে, অর্থাত্, এটির একটি রয়েছে মানটি ফেরত পাওয়ার জন্য অনুরোধ করা দরকার এমন পদ্ধতিটি পান। পুরানো স্টাইলের ক্লাসগুলি সহজভাবে কোনও অতিরিক্ত গণনা ছাড়াই পাওয়া বস্তুকে ফেরত দেয় (তবে তারপরে বর্ণনাকারীদের সমর্থন করে না)। আপনি গুয়েডো পাইথন-হিস্টোরি.ব্লগস্পট.কম.২০ / ২০১০ / 06/… দ্বারা এই দুর্দান্ত পোস্টে আরও পড়তে পারেন , বিশেষ করে স্লটগুলির বিভাগ
xulo শেভেজ

1
সিপিথন ২.7.২-এর সাথে সত্য বলে মনে হচ্ছে না:%timeit aobj.a 10000000 loops, best of 3: 66.1 ns per loop %timeit bobj.a 10000000 loops, best of 3: 53.9 ns per loop
বেনিডিক্ট ওয়াল্ডভোভেল

1
আমার জন্য x86-64 লিনাক্সের সিপিথন ২.7.২ এ আওবজের জন্য এখনও দ্রুত।
xioxox

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

আইপিথন ২.7..6 এও এটি সত্য নয়। '' '' 477 এনএস বনাম 456 এনএস প্রতি লুপ '' ''
কুমসুর

37

গাইডো ইনসাইট স্টোরি অন নিউ-স্টাইল ক্লাস লিখেছেন , এটি পাইথনের নতুন স্টাইল এবং পুরানো স্টাইলের ক্লাস সম্পর্কে সত্যই দুর্দান্ত একটি নিবন্ধ।

পাইথন 3-এ কেবল নতুন-স্টাইলের ক্লাস রয়েছে। এমনকি যদি আপনি একটি 'পুরানো-শৈলীর ক্লাস' লিখেন তবে তা স্পষ্টতই উত্পন্ন object

নতুন স্টাইলের ক্লাসগুলিতে কিছু উন্নত বৈশিষ্ট্য রয়েছে পুরানো-শৈলীর ক্লাসগুলির অভাবে, যেমন super, নতুন সি 3 এমআরও , কিছু জাদুকরী পদ্ধতি ইত্যাদি have


24

এখানে একটি খুব ব্যবহারিক, সত্য / মিথ্যা পার্থক্য। নিম্নলিখিত কোডের দুটি সংস্করণের মধ্যে একমাত্র পার্থক্য হ'ল দ্বিতীয় সংস্করণে ব্যক্তি বস্তু থেকে উত্তরাধিকার সূত্রে আসে । তা ছাড়া, দুটি সংস্করণ অভিন্ন, তবে বিভিন্ন ফলাফল সহ:

  1. পুরানো শৈলী ক্লাস

    class Person():
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed1 is ahmed2
    print ahmed1
    print ahmed2
    
    
    >>> False
    <__main__.Person instance at 0xb74acf8c>
    <__main__.Person instance at 0xb74ac6cc>
    >>>
    
  2. নতুন ধাঁচের ক্লাস

    class Person(object):
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed2 is ahmed1
    print ahmed1
    print ahmed2
    
    >>> True
    <__main__.Person object at 0xb74ac66c>
    <__main__.Person object at 0xb74ac66c>
    >>>

2
'_নাম_ক্যাচ' কী করে? আপনি একটি রেফারেন্স ভাগ করতে পারেন?
মুয়াটিক

4
_names_cacheএমন একটি অভিধান যা আপনার প্রতিটি নামকে ক্যাশে করে (ভবিষ্যতের পুনরুদ্ধারের জন্য স্টোর) Person.__new__। সেটডিফল্ট পদ্ধতি (যে কোনও অভিধানে সংজ্ঞায়িত) দুটি আর্গুমেন্ট নেয়: একটি কী এবং একটি মান। কীটি ডিকটিতে থাকলে, এটির মান ফিরে আসবে। যদি এটি ডিকের মধ্যে না থাকে তবে এটি প্রথমে দ্বিতীয় আর্গুমেন্ট হিসাবে পাস হওয়া মানকে সেট করবে এবং তারপরে এটি ফিরিয়ে দেবে।
ychaouche

4
ব্যবহারটি ভুল। ধারণাটি হ'ল কোনও নতুন অবজেক্টটি ইতিমধ্যে উপস্থিত থাকলে এটি নির্মাণ করা নয়, তবে আপনার ক্ষেত্রে __new__()সর্বদা ডাকা হয় এবং এটি সর্বদা একটি নতুন অবজেক্ট তৈরি করে এবং তারপরে নিক্ষেপ করে। ifএক্ষেত্রে একটি ভাল হয় .setdefault()
অমিত উপাধ্যায়

তবে, কেন পাইনি কেন আউটপুটটির মধ্যে পার্থক্য হয় অর্থাত পুরানো শৈলীর শ্রেণিতে দুটি উদাহরণ দুটি পৃথক ছিল যেমন প্রত্যাবর্তিত ফালস, তবে নতুন স্টাইলের ক্লাসে উভয় উদাহরণ একই। কীভাবে? নতুন স্টাইলের ক্লাসে কী পরিবর্তন ঘটেছে, যা দুটি উদাহরণকেই এক করে ফেলল, যা পুরানো স্টাইলের ক্লাসে ছিল না?
পবিত্র পাতি

1
@ পবিত্রপতি: এটি এখানে সস্তা ধরণের প্রদর্শন ration __new__পুরানো স্টাইলের ক্লাসগুলির পক্ষে আসলে জিনিস নয়, এটি উদাহরণস্বরূপ নির্মাণে ব্যবহৃত হয় না (এটি কেবল একটি র্যান্ডম নাম যা বিশেষ দেখতে যেমন সংজ্ঞাযুক্ত __spam__)। সুতরাং পুরানো-শৈলীর শ্রেণিটি তৈরি করা কেবলমাত্র আহ্বান জানায় __init__, যখন নতুন শৈলীর নির্মাণগুলি __new__(নাম অনুসারে সিঙ্গলটন উদাহরণে কোয়েলসেসিং) নির্মাণ এবং __init__এটি আরম্ভ করার আহ্বান জানায় ।
শ্যাডোর্যাঞ্জার

10

নতুন-স্টাইলের ক্লাসগুলি উত্তরাধিকার সূত্রে প্রাপ্ত objectএবং পাইথন ২.২ এর পরে অবশ্যই (যেমনটি class Classname(object):পরিবর্তে class Classname:) লেখা উচিত । মূল পরিবর্তনটি হ'ল ধরণ এবং শ্রেণী একত্রিত করা এবং এর দুর্দান্ত পার্শ্ব-প্রতিক্রিয়া হ'ল এটি আপনাকে বিল্ট-ইন টাইপগুলি থেকে উত্তরাধিকারী করার অনুমতি দেয়।

আরও তথ্যের জন্য ডেস্ক্রিন্ট্রো পড়ুন ।


8

নতুন স্টাইলের ক্লাসগুলি super(Foo, self)যেখানে Fooক্লাস এবং selfএটি উদাহরণ হিসাবে ব্যবহার করতে পারে ।

super(type[, object-or-type])

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

এবং পাইথন 3.x এ আপনি কেবল super()কোনও প্যারামিটার ছাড়াই ক্লাসের অভ্যন্তরে ব্যবহার করতে পারেন ।

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