সুপার () নতুন ধরণের ক্লাসের জন্য "টাইপএরআর: অবশ্যই টাইপ হওয়া উচিত, ক্লাসোবজ নয়" উত্থাপন করে


335

নিম্নলিখিত ব্যবহারের super()ফলে একটি টাইপআরার উত্থাপিত হয়: কেন?

>>> from  HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
...     def __init__(self):
...         super(TextParser, self).__init__()
...         self.all_data = []
...         
>>> TextParser()
(...)
TypeError: must be type, not classobj

স্ট্যাকওভারফ্লোতে একই ধরণের প্রশ্ন রয়েছে: পাইথন সুপার () টাইপ ইরার উত্থাপন করে , যেখানে ত্রুটিটি ব্যাখ্যা করা হয়েছে যে ব্যবহারকারী শ্রেণিটি কোনও নতুন-শৈল শ্রেণি নয়। তবে উপরের ক্লাসটি একটি নতুন ধাঁচের শ্রেণি, এটি উত্তরাধিকার সূত্রে প্রাপ্ত object:

>>> isinstance(HTMLParser(), object)
True

আমি কী মিস করছি? আমি super()এখানে কীভাবে ব্যবহার করতে পারি ?

এর HTMLParser.__init__(self)পরিবর্তে ব্যবহার করা কার্যকর super(TextParser, self).__init__()হবে তবে আমি টাইপরর বুঝতে চাই।

পিএস: জোয়াকিম উল্লেখ করেছেন যে একটি নতুন-স্টাইলের-শ্রেণীর উদাহরণ হওয়া সমান নয় object। আমি বিপরীতে বহুবার পড়েছি, সুতরাং আমার বিভ্রান্তি (উদাহরণ পরীক্ষার উপর ভিত্তি করে নতুন ধাঁচের শ্রেণির উদাহরণ পরীক্ষার objectউদাহরণ: https://stackoverflow.com/revisions/2655651/3 )।


3
আপনার প্রশ্ন এবং উত্তরের জন্য ধন্যবাদ। আমি ভাবছি কেন 2.7 এর super.__doc__পুরানো বনাম নতুন স্টাইল সম্পর্কে কিছু উল্লেখ করা হয়নি!
কেলভিন

ধন্যবাদ। :) ডকাস্ট্রিংগুলিতে ডকুমেন্টেশনের সম্পূর্ণ, এইচটিএমএল সংস্করণের চেয়ে কম তথ্য থাকে। সত্য যে super()শুধুমাত্র নতুন স্টাইলের শ্রেণীর (এবং বস্তু) জন্য কাজ করে এইচটিএমএল ডক (উল্লেখ করা হয় docs.python.org/library/functions.html#super )।
এরিক হে লেবিগোট


এটি কোনও সদৃশ নয় (আপডেট হওয়া প্রশ্ন এবং স্বীকৃত উত্তর দেখুন)।
এরিক হে লেবিগোট

উত্তর:


246

ঠিক আছে, এটি স্বাভাবিক " super()পুরানো শৈলীর শ্রেণীর সাথে ব্যবহার করা যায় না"।

তবে, গুরুত্বপূর্ণ বিষয়টি হ'ল "এর জন্য সঠিক পরীক্ষাটি কি এটি একটি নতুন-স্টাইলের উদাহরণ (অর্থাত্ বস্তু)?" হয়

>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False

এবং না (প্রশ্ন হিসাবে):

>>> isinstance(instance, object)
True

জন্য ক্লাস , সঠিক পরীক্ষা "এই একটি নতুন স্টাইলের ক্লাস হয়":

>>> issubclass(OldStyle, object)  # OldStyle is not a new-style class
False
>>> issubclass(int, object)  # int is a new-style class
True

গুরুত্বপূর্ণ পয়েন্ট পুরানো ধাঁচের শ্রেণীর সঙ্গে, হয় বর্গ একটি দৃষ্টান্ত এবং উহার টাইপ স্বতন্ত্র হয়। এখানে, OldStyle().__class__হয় OldStyle, যা থেকে উত্তরাধিকারী নেই object, যখন type(OldStyle())হয় instanceধরন, যা নেই থেকে উত্তরাধিকারী object। মূলত, একটি পুরানো শৈলীর শ্রেণি কেবল প্রকারের বস্তু তৈরি করে instance(যেখানে একটি নতুন-শৈলিক শ্রেণি এমন বস্তু তৈরি করে যার প্রকারটি তার নিজস্ব itself এটি সম্ভবত কেন উদাহরণস্বরূপ হয় OldStyle()একটি হল object: তার type()থেকে উত্তরাধিকারী object(সত্য যে তার বর্গ নেই না থেকে উত্তরাধিকারী objectগণনা করা হয় না: পুরানো ধাঁচের শ্রেণীর নিছক ধরনের নতুন বস্তু গঠন করা instance)। আংশিক উল্লেখ:https://stackoverflow.com/a/9699961/42973

PS: একটি নতুন-শৈলীর ক্লাস এবং একটি পুরানো শৈলীর মধ্যে পার্থক্য এছাড়াও দেখা যেতে পারে:

>>> type(OldStyle)  # OldStyle creates objects but is not itself a type
classobj
>>> isinstance(OldStyle, type)
False
>>> type(int)  # A new-style class is a type
type

(পুরানো স্টাইলের ক্লাসগুলি ধরণের নয় , তাই তারা তাদের উদাহরণগুলির ধরণ হতে পারে না)।


11
এবং এটি এখন আমাদের পাইথন 3 হওয়ার একটি কারণ
স্টিভেন রাম্বালস্কি

2
BTW: (Oldstyle().__class__ is Oldstyle)হয়True
টিনো

2
@ টিনো: প্রকৃতপক্ষে, তবে মূল বিষয়টি OldStyle().__class__হ'ল কোনও বস্তু ( OldStyle()) কোনও পুরানো শৈলীর শ্রেণীর থেকে আসে কিনা তা পরীক্ষা করে দেখানো হয় । শুধুমাত্র নতুন-স্টাইলের ক্লাসগুলি মাথায় রেখেই কেউ এর isinstance(OldStyle(), object)পরিবর্তে পরীক্ষা দিতে প্রলুব্ধ হতে পারে ।
এরিক হে লেবিগোট

27
2.7.x তে এখনও পাইথন স্ট্যান্ডার্ড লাইব্রেরি কতটা উত্তরাধিকার সূত্রে পায় না তা বিদ্রূপমূলক object, এভাবে আপনাকে প্রক্সি দিয়ে স্ক্রু করে।
নিক বেস্টিন

2
@ নিকবাস্টিন - এটি কোনও কাকতালীয় ঘটনা নয়। সবাইকে পাইথন 3-এ ধাক্কা দেওয়ার জন্য এটি সমস্ত কিছু যেখানে "ইতিমধ্যে সবকিছু ঠিক আছে"। তবে - সাবধানী ইমোটার - এটি কেবল টোপ এবং স্যুইচ।
টমাসজ গ্যান্ডোর

204

সুপার () কেবলমাত্র নতুন-স্টাইলের ক্লাসে ব্যবহার করা যেতে পারে যার অর্থ রুট ক্লাসটি 'অবজেক্ট' শ্রেণি থেকে উত্তরাধিকারী হওয়া দরকার।

উদাহরণস্বরূপ, শীর্ষ শ্রেণীর এইরকম হওয়া দরকার:

class SomeClass(object):
    def __init__(self):
        ....

না

class SomeClass():
    def __init__(self):
        ....

সুতরাং, সমাধানটি হ'ল এইভাবে পিতামাতার আরম্ভ পদ্ধতিটি সরাসরি কল করুন :

class TextParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.all_data = []

8
আমার জন্য, আমাকে এটি করতে হয়েছিল: এইচটিএমএল পার্সার .__ init __ (স্ব) আপনার শেষ উদাহরণটি কাজ করেছে কিনা তা সম্পর্কে আমি আগ্রহী?
চ্যাম্পে

1
@ ইওল ​​মানে কি? জেএফপি কেবলমাত্র উল্লেখ করেছে যে কলটিতে selfপ্যারামিটারের অভাবে এই উত্তরে প্রদত্ত কোডটি ভুল HTMLParser.__init__()
পাইটার ডব্রোগোস্ট

1
@ পাইওটারডব্রোগস্ট: দুঃখিত, আমার মন্তব্যটি লিটলকিউর উত্তর সম্পর্কে ছিল, জেফ্পের (ভাল) বিষয় সম্পর্কে নয়।
এরিক হে লেবিগোট

1
@ জেফ্প দুঃখিত, এটি একটি টাইপো, আমি কেবল এসও-তে টাইপ করেছি তবে এটি আমার পরীক্ষা না করে পরীক্ষা করে নি। সংশোধন করার জন্য ধন্যবাদ
কলিন সু

1
একটি ফিক্স যে python2.6 এ ধরনের logging.Formatter যেমন বিদ্যমান কোড, সাথে কাজ করে জন্য ভোট দিন
ডেভিড রেনল্ডস

28

আপনি ব্যবহার করতে পারেন class TextParser(HTMLParser, object):। এটি TextParserএকটি নতুন ধাঁচের শ্রেণি তৈরি করে এবং super()এটি ব্যবহার করা যায়।


আমার পক্ষ থেকে উত্সাহ, কারণ বস্তু থেকে উত্তরাধিকার যুক্ত করা ভাল ধারণা। (এটি বলেছিল যে, এই উত্তরটি প্রশ্নের
ধরণটি

23

পূর্বপুরুষ হিসাবে সমস্যাটির superপ্রয়োজন object:

>>> class oldstyle:
...     def __init__(self): self.os = True

>>> class myclass(oldstyle):
...     def __init__(self): super(myclass, self).__init__()

>>> myclass()
TypeError: must be type, not classobj

কাছাকাছি পরীক্ষায় একজনকে পাওয়া যায়:

>>> type(myclass)
classobj

কিন্তু:

>>> class newstyle(object): pass

>>> type(newstyle)
type    

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

>>> class myclass(oldstyle, object):
...     def __init__(self): super(myclass, self).__init__()

>>> myclass().os
True

বৈধ পয়েন্ট, তবে তারা ইতিমধ্যে পূর্ববর্তী উত্তরে রয়েছে। এছাড়াও, যাচাইয়ের পরিবর্তে type(myclass)কোন বিষয়টি myclassবস্তু থেকে উত্তরাধিকারী কিনা (যেমন isinstance(myclass, object)সত্য কিনা - এটি মিথ্যা) matters
এরিক হে লেবিগোট

17

আপনি উত্তরাধিকার গাছ (সংস্করণ 2.6 মধ্যে) তাকান, HTMLParserথেকে উত্তরাধিকারী SGMLParserযা থেকে উত্তরাধিকারী ParserBaseযা না থেকে উত্তরাধিকারী object। অর্থাৎ এইচটিএমএল পার্সার একটি পুরানো শৈলীর শ্রেণি class

আপনার চেকিং সম্পর্কে isinstance, আমি আইপথনে একটি দ্রুত পরীক্ষা করেছি:

[1] এ: শ্রেণি এ:
   ...: পাস
   ...: 

[২] ইন: আইসিনস্ট্যান্স (এ, অবজেক্ট)
আউট [2]: সত্য

এমনকি যদি কোনও শ্রেণি পুরানো শৈলীর শ্রেণীর হয় তবে এটি এখনও একটি উদাহরণ object


2
আমি বিশ্বাস করি যে সঠিক পরীক্ষাটি হওয়া উচিত isinstance(A(), object), না isinstance(A, object), না? পরেরটির সঙ্গে, আপনি পরীক্ষা হবে কিনা তা বর্গ A একটি হল object, যেহেতু প্রশ্ন হল কিনা দৃষ্টান্ত এর Aএকটি হয় objectঠিক আছে,?
এরিক হে লেবিগোট

5
PS: সেরা পরীক্ষা বলে মনে হচ্ছে issubclass(HTMLParser, object), যা মিথ্যা ফিরিয়ে দেয়।
এরিক হে লেবিগোট

5

করার সঠিক উপায়টি পুরানো স্টাইলের ক্লাসগুলিতে নিম্নলিখিত হিসাবে থাকবে যা 'অবজেক্ট' থেকে উত্তরাধিকারসূত্রে আসে না

class A:
    def foo(self):
        return "Hi there"

class B(A):
    def foo(self, name):
        return A.foo(self) + name

1
প্রশ্ন, এই পদ্ধতি ইতিমধ্যে উল্লেখ করা হয়: সমস্যা হয় বুঝতে কেন একটি ত্রুটির বার্তা উত্পাদিত হয়, না এটা দূরে (বিশেষ করে এই ভাবে) যেতে হবে।
এরিক হে লেবিগোট

তদ্ব্যতীত, এই সমাধানটি সেই ক্ষেত্রে কার্যকর হবে না যে আমরা একটি ক্লাস Aএকটি রাজ্য সংরক্ষণ করে এমন শ্রেণীর উদাহরণ চাই ।
tashuhka

0

এফডাব্লুআইডাব্লু এবং যদিও আমি পাইথন গুরু নই তবে আমি এটিকে পেলাম

>>> class TextParser(HTMLParser):
...    def handle_starttag(self, tag, attrs):
...        if tag == "b":
...            self.all_data.append("bold")
...        else:
...            self.all_data.append("other")
...     
...         
>>> p = TextParser()
>>> p.all_data = []
>>> p.feed(text)
>>> print p.all_data
(...)

প্রয়োজন অনুসারে কেবল পার্সের ফলাফলগুলি পেয়েছি।

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