টাইপ () এবং ইসিনস্ট্যান্স () এর মধ্যে পার্থক্য কী?


1247

এই দুটি কোড টুকরা মধ্যে পার্থক্য কি?

ব্যবহার type():

import types

if type(a) is types.DictType:
    do_something()
if type(b) in types.StringTypes:
    do_something_else()

ব্যবহার isinstance():

if isinstance(a, dict):
    do_something()
if isinstance(b, str) or isinstance(b, unicode):
    do_something_else()

দ্রষ্টব্য: যদি এটি না হয় strএবং unicode(যেখানে আপনি কেবল পরীক্ষা basestringকরতে পারেন), আপনি একাধিক ধরণের বিরুদ্ধে পরীক্ষা করার জন্য একটি টিপল ব্যবহার করতে পারেন। কিনা তা চেক করতে somethingহয় intবা strব্যবহার isinstance(something, (int, str))
xuiqzy

উত্তর:


1270

অন্যান্য (ইতিমধ্যে ভাল!) উত্তর বিষয়বস্তু সংক্ষেপ করতে, isinstanceউত্তরাধিকার জন্য সরবরাহ (ক উদ্ভূত ক্লাসের একটা নিদর্শন একটি হল একটি বেস ক্লাসের নিদর্শনের সঙ্গে খুব), এবং এর সমতার জন্য চেক typeনা (এটা ধরনের এবং প্রত্যাখ্যান দৃষ্টান্ত পরিচয় দাবী উপপ্রকারের, একেএ সাবক্লাস)।

সাধারণত পাইথনে, আপনি নিজের কোডটি উত্তরাধিকারের পক্ষে সমর্থন করতে চান, অবশ্যই (যেহেতু উত্তরাধিকারটি খুব সহজ, তাই কোডটি আপনার ব্যবহার করা বন্ধ করা খারাপ হবে!) সুতরাং এটির isinstanceপরিচয় যাচাইয়ের চেয়ে কম খারাপ typeকারণ এটি নির্বিঘ্নে সমর্থন করে উত্তরাধিকার।

এটা যে isinstanceহয় ভাল , আপনি এটা মনে শুধু কম খারাপ ধরনের সমতা পরীক্ষণ করে। পাইথোনিক, পছন্দসই সমাধানটি প্রায় অলসভাবে "হাঁসের টাইপিং": যুক্তিটি ব্যবহার করার চেষ্টা করুন যেন এটি একটি নির্দিষ্ট কাঙ্ক্ষিত ধরণের ছিল, এটি একটি try/ exceptবিবৃতিতে করুন যে সমস্ত ব্যতিক্রম ঘটতে পারে যেটি যদি যুক্তিটি বাস্তবে না থাকে তবে টাইপ (বা অন্য কোনও ধরণের সুন্দরভাবে হাঁস-নকল করে ;-), এবং ধারাটিতে exceptঅন্য কিছু চেষ্টা করুন ("যদি" এটি অন্য কোনও ধরণের ছিল "তর্কটি ব্যবহার করে)।

basestring হয় , তবে, বেশ একটি বিশেষ কেস-একটি builtin যে ধরনের বিদ্যমান শুধুমাত্র আপনি ব্যবহার করতে দিতে isinstance(উভয় strএবং unicodeউপশ্রেণী basestring)। স্ট্রিংগুলি সিকোয়েন্সগুলি হয় (আপনি তাদের উপর লুপ করতে পারেন, সেগুলি সূচক করতে পারেন, তাদের টুকরো টুকরো করতে পারেন, ...) তবে আপনি সাধারণত তাদের "স্কেলার" প্রকার হিসাবে বিবেচনা করতে চান - এটি কিছুটা অসুবিধাজনক (তবে যুক্তিসঙ্গতভাবে ঘন ঘন ব্যবহারের ক্ষেত্রে) সমস্ত ধরণের চিকিত্সার জন্য স্ট্রিং (এবং সম্ভবত অন্যান্য স্কেলারের ধরণ, যেমন, আপনি লুপ করতে পারবেন না), সমস্ত পাত্রে (তালিকাগুলি, সেটগুলি, ডিক্টস, ...) অন্য উপায়ে এবং basestringপ্লাস isinstanceআপনাকে এটি করতে সহায়তা করে this এর সামগ্রিক কাঠামো মূর্খতা এইরকম কিছু:

if isinstance(x, basestring)
  return treatasscalar(x)
try:
  return treatasiter(iter(x))
except TypeError:
  return treatasscalar(x)

আপনি বলতে পারেন যে basestringএটি একটি অ্যাবস্ট্রাক্ট বেস ক্লাস ("এবিসি") - এটি সাবক্লাসগুলিতে কোনও কংক্রিট কার্যকারিতা সরবরাহ করে না, বরং মূলত "ব্যবহারকারীর জন্য" চিহ্নিতকারী হিসাবে উপস্থিত রয়েছে isinstance। স্পষ্টতই ধারণাটি পাইথনের ক্রমবর্ধমান একটি, যেহেতু পিইপি 3119 , এটির একটি সাধারণীকরণ প্রবর্তন করেছে, এটি গৃহীত হয়েছিল এবং পাইথন ২.6 এবং with.০ দিয়ে শুরু করা হয়েছে।

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

পাইথন ২.6 এ সরবরাহিত হিসাবে এবিসি সমর্থনের অন্তর্নিহিত যান্ত্রিকগুলির জন্য, এখানে দেখুন ; তাদের 3.1 সংস্করণের জন্য, খুব অনুরূপ, এখানে দেখুন । উভয় সংস্করণে, স্ট্যান্ডার্ড লাইব্রেরি মডিউল সংগ্রহ (এটি খুব সামান্য 2.6 সংস্করণের জন্য 3.1 সংস্করণ here এখানে দেখুন ) বেশ কয়েকটি দরকারী এবিসি সরবরাহ করে।

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


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

2
বেসস্ট্রিং পাইথন 3 এ উপলভ্য নয়
ইরোবার্টক

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

পাইথন 3.0.০-এ হোয়াট নিউ অনুসারে @ অরবার্টক, "বিল্ট-ইন বেসস্ট্রিং অ্যাবস্ট্রাক্ট প্রকারটি সরানো হয়েছিল instead পরিবর্তে আরআরটি ব্যবহার করুন" "
নিউরাইট

344

এখানে এমন একটি উদাহরণ রয়েছে যেখানে isinstanceএমন কিছু অর্জন করা যায় যা typeনা পারে:

class Vehicle:
    pass

class Truck(Vehicle):
    pass

এই ক্ষেত্রে, একটি ট্রাক বস্তু একটি যানবাহন, তবে আপনি এটি পাবেন:

isinstance(Vehicle(), Vehicle)  # returns True
type(Vehicle()) == Vehicle      # returns True
isinstance(Truck(), Vehicle)    # returns True
type(Truck()) == Vehicle        # returns False, and this probably won't be what you want.

অন্য কথায়, isinstanceসাবক্লাসের ক্ষেত্রেও এটি সত্য।

আরও দেখুন: পাইথনে কোনও বস্তুর প্রকারের তুলনা কীভাবে করা যায়?


143
কারণ এমন ঘটনা আছে যেখানে আপনি আইসনস্ট্যান্স আচরণ চান না আমি যুক্তি দেব যে এর চেয়ে ভাল আর কিছু নেই। তারা কেবল আলাদা কিছু করে।
ফিলগো 20

27
-1, কারণ "আইসনস্ট্যান্স টাইপের চেয়ে ভাল" একটি বিভ্রান্তিমূলক মন্তব্য। এটি প্রথম নজরে " typeঅবচয়, isinstanceপরিবর্তে ব্যবহার করুন" এর মতো বোঝা যাচ্ছে। উদাহরণস্বরূপ, আমি যা চেয়েছিলাম তা হুবহু type()যাচাই করা হয়েছিল , তবে সেই কারণে আমাকে অল্প সময়ের জন্য (এবং কিছুটা ডিবাগ করতে হয়েছিল) বিপথগামী হয়েছিল।
আনুষ্ঠানিকভাবে

8
তারা কীভাবে আলাদাভাবে কাজ করে এটি এটির একটি উত্তম উদাহরণ, তবে আমি কেবল এমন একটি মামলায় চলে এসেছি যেখানে আমার বিশেষভাবে প্রয়োজন ছিল type()এবং না isinstance()। একটি ভাল না; তারা বিভিন্ন জিনিস জন্য।
EL_DON

103

পাইথন isinstance()এবং type()মধ্যে পার্থক্য ?

সাথে টাইপ-চেকিং

isinstance(obj, Base)

সাবক্ল্যাস এবং একাধিক সম্ভাব্য ঘাঁটির উদাহরণগুলির জন্য অনুমতি দেয়:

isinstance(obj, (Base1, Base2))

যেখানে টাইপ-চেকিং

type(obj) is Base

শুধুমাত্র রেফারেন্স করা প্রকারটি সমর্থন করে।


সাইডেনোট হিসাবে, isসম্ভবত তুলনায় সম্ভবত আরও উপযুক্ত

type(obj) == Base

কারণ ক্লাসগুলি সিলেটলেটস।

টাইপ-চেকিং এড়ান - পলিমারফিজম (হাঁস-টাইপিং) ব্যবহার করুন

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

def function_of_duck(duck):
    duck.quack()
    duck.swim()

উপরের কোডটি যদি কাজ করে তবে আমরা অনুমান করতে পারি যে আমাদের যুক্তিটি একটি হাঁস। সুতরাং আমরা অন্যান্য জিনিসগুলিতে হ'ল আসল উপ-ধরণের হাঁস:

function_of_duck(mallard)

বা সেই হাঁসের মতো কাজ:

function_of_duck(object_that_quacks_and_swims_like_a_duck)

এবং আমাদের কোড এখনও কাজ করে।

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

সুতরাং, প্রশ্নের উত্তর দিতে:

পাইথন isinstance()এবং type()মধ্যে পার্থক্য ?

পার্থক্যটি প্রদর্শনের জন্য আমাকে অনুমতি দিন:

type

বলুন যে আপনার ক্রিয়াকলাপটি নির্দিষ্ট ধরণের আর্গুমেন্ট (নির্মাতাদের জন্য একটি সাধারণ ব্যবহারের ক্ষেত্রে) পেলে আপনাকে একটি নির্দিষ্ট আচরণ নিশ্চিত করতে হবে। আপনি যদি এই জাতীয় প্রকারের জন্য পরীক্ষা করেন:

def foo(data):
    '''accepts a dict to construct something, string support in future'''
    if type(data) is not dict:
        # we're only going to test for dicts for now
        raise ValueError('only dicts are supported for now')

যদি আমরা একটি ডিক যা একটি উপশ্রেণীতে পাস করার চেষ্টা করি dict(যেমন আমাদের সক্ষম হওয়া উচিত, যদি আমরা আমাদের কোডটি লিসকভ সাবস্টিটিউশনের নীতি অনুসরণ করার প্রত্যাশা করি, তবে সেই সাব - টাইপগুলি ধরণের পরিবর্তে প্রতিস্থাপন করা যেতে পারে) আমাদের কোড ব্রেক!

from collections import OrderedDict

foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))

একটি ত্রুটি উত্থাপন!

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in foo
ValueError: argument must be a dict

isinstance

তবে আমরা যদি ব্যবহার করি তবে আমরা isinstanceলিসকভ সাবস্টিটিউশন সমর্থন করতে পারি!

def foo(a_dict):
    if not isinstance(a_dict, dict):
        raise ValueError('argument must be a dict')
    return a_dict

foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))

আয় OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])

বিমূর্ত বেস ক্লাস

আসলে, আমরা আরও ভাল করতে পারি। collectionsবিমূর্ত বেস ক্লাসগুলি সরবরাহ করে যা বিভিন্ন ধরণের ন্যূনতম প্রোটোকল প্রয়োগ করে। আমাদের ক্ষেত্রে, আমরা যদি কেবল Mappingপ্রোটোকলটি আশা করি তবে আমরা নিম্নলিখিতগুলি করতে পারি এবং আমাদের কোডটি আরও নমনীয় হয়ে উঠেছে:

from collections import Mapping

def foo(a_dict):
    if not isinstance(a_dict, Mapping):
        raise ValueError('argument must be a dict')
    return a_dict

মন্তব্য প্রতিক্রিয়া:

এটি লক্ষ করা উচিত যে প্রকারটি একাধিক ক্লাস ব্যবহার করে চেক করতে ব্যবহার করা যেতে পারে type(obj) in (A, B, C)

হ্যাঁ, আপনি ধরণের সাম্যের জন্য পরীক্ষা করতে পারেন, তবে উপরের পরিবর্তে নিয়ন্ত্রণ প্রবাহের জন্য একাধিক ঘাঁটি ব্যবহার করুন, যদি না আপনি নির্দিষ্টভাবে কেবল এই ধরণের অনুমতি দিচ্ছেন:

isinstance(obj, (A, B, C))

পার্থক্যটি আবার এটি হ'ল isinstanceউপক্লাসগুলিকে সমর্থন করে যা পিতামাতার পক্ষে অন্যথায় প্রোগ্রামটি ভাঙ্গা ছাড়াই প্রতিস্থাপিত করা যেতে পারে, এটি সম্পত্তি লিসকভের বিকল্প হিসাবে পরিচিত।

আরও ভাল, যদিও, আপনার নির্ভরতা উল্টে দিন এবং নির্দিষ্ট ধরণের জন্য মোটেও পরীক্ষা করবেন না।

উপসংহার

সুতরাং যেহেতু আমরা সাব- ক্লাসের বিকল্পগুলি সমর্থন করতে চাই, বেশিরভাগ ক্ষেত্রেই, আমরা টাইপ-চেকিং এড়াতে typeএবং এর সাথে টাইপ-চেকিং পছন্দ isinstanceকরতে চাই - যদি না আপনি সত্যিই কোনও উদাহরণের সঠিক শ্রেণিটি জানতে না চান।


আপনার যদি আপনার_মডিউল.পি থাকে এবং যেখানে আপনি যাচাই করেন isinstance(instance, y)এবং ব্যবহার করেন from v.w.x import yএবং আপনি সেই চেকটি আমদানি করেন তবে আপনি যখন আপনার_মডিউল.পিতে y কীভাবে আমদানি করা হয়েছিল তার পরিবর্তে instanceআপনি ব্যবহার from x import yকরেন, আইসনস্ট্যান্স চেকটি একই শ্রেণীর সত্ত্বেও ব্যর্থ হবে।
toonarmycaptain

64

পরেরটি পছন্দ করা হয়, কারণ এটি সাবক্লাসগুলি সঠিকভাবে পরিচালনা করবে। আসলে, আপনার উদাহরণটি আরও সহজেই লেখা যেতে পারে কারণ isinstance()দ্বিতীয় প্যারামিটারটি একটি টিপল হতে পারে:

if isinstance(b, (str, unicode)):
    do_something_else()

বা, basestringবিমূর্ত শ্রেণি ব্যবহার করে :

if isinstance(b, basestring):
    do_something_else()

15

পাইথন ডকুমেন্টেশন অনুসারে এখানে একটি বিবৃতি দেওয়া হয়েছে:

8.15। প্রকারভেদ - অন্তর্নির্মিত প্রকারের নাম

পাইথন ২.২ থেকে শুরু করে বিল্ট-ইন ফ্যাক্টরি ফাংশন যেমন সম্পর্কিত হয় int()এবং str()এটিও সম্পর্কিত ধরণের নাম।

তাই isinstance()পছন্দ করা উচিত type()


9

ব্যবহারিক ব্যবহারের পার্থক্য হ'ল তারা কীভাবে পরিচালনা করে booleans:

Trueএবং Falseকেবল কীওয়ার্ডগুলি যার অর্থ 1এবং 0পাইথন। সুতরাং,

isinstance(True, int)

এবং

isinstance(False, int)

উভয় ফিরে True। উভয় বুলিয়ান একটি পূর্ণসংখ্যার উদাহরণ। type()তবে, আরও চালাক:

type(True) == int

আয় False


0

আসল পার্থক্যের জন্য, আমরা এটি সন্ধান codeকরতে পারি তবে আমি এর ডিফল্ট আচরণের প্রয়োগ খুঁজে পাই না isinstance()

তবে আমরা __instancecheck__ অনুসারে অনুরূপ একটি abc .__ উদাহরণস্বরূপ__ পেতে পারি

উপরে থেকে abc.__instancecheck__, নীচের পরীক্ষাটি ব্যবহার করার পরে:

# file tree
# /test/__init__.py
# /test/aaa/__init__.py
# /test/aaa/aa.py
class b():
pass

# /test/aaa/a.py
import sys
sys.path.append('/test')

from aaa.aa import b
from aa import b as c

d = b()

print(b, c, d.__class__)
for i in [b, c, object]:
    print(i, '__subclasses__',  i.__subclasses__())
    print(i, '__mro__', i.__mro__)
    print(i, '__subclasshook__', i.__subclasshook__(d.__class__))
    print(i, '__subclasshook__', i.__subclasshook__(type(d)))
print(isinstance(d, b))
print(isinstance(d, c))

<class 'aaa.aa.b'> <class 'aa.b'> <class 'aaa.aa.b'>
<class 'aaa.aa.b'> __subclasses__ []
<class 'aaa.aa.b'> __mro__ (<class 'aaa.aa.b'>, <class 'object'>)
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasses__ []
<class 'aa.b'> __mro__ (<class 'aa.b'>, <class 'object'>)
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'object'> __subclasses__ [..., <class 'aaa.aa.b'>, <class 'aa.b'>]
<class 'object'> __mro__ (<class 'object'>,)
<class 'object'> __subclasshook__ NotImplemented
<class 'object'> __subclasshook__ NotImplemented
True
False

আমি এই উপসংহারটি পেয়েছি, এর জন্য type:

# according to `abc.__instancecheck__`, they are maybe different! I have not found negative one 
type(INSTANCE) ~= INSTANCE.__class__
type(CLASS) ~= CLASS.__class__

এর জন্য isinstance:

# guess from `abc.__instancecheck__`
return any(c in cls.__mro__ or c in cls.__subclasses__ or cls.__subclasshook__(c) for c in {INSTANCE.__class__, type(INSTANCE)})

বিটিডাব্লু: relative and absolutely importব্যবহারের মিশ্রণ না absolutely importকরাই ভাল , প্রজেক্ট_ডির থেকে ব্যবহার করুন (যুক্ত করেছেন sys.path)

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