পাইথনে কোনও ভেরিয়েবল একটি অভিধান কিনা তা কীভাবে পরীক্ষা করবেন?


214

অজগরটির একটি চলক একটি অভিধান কিনা তা আপনি কীভাবে পরীক্ষা করবেন?

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

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
    if ###check if v is a dictionary:
        for k, v in v.iteritems():
            print(k, ' ', v)
    else:
        print(k, ' ', v)



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

13
আমি @ বেকারানলেটকের সাথে একমত, আমি এখানে প্রশ্নের উত্তর খুঁজছিলাম "পাইথনের একটি ভেরিয়েবল কীভাবে পরীক্ষা করা যায়?" এবং আমি কখনই আমার উত্তরটি "আইসনস্ট্যান্সের মধ্যে পার্থক্য () এবং পাইথনে টাইপ () টাইপ করতে" ভেবে দেখিনি।
লোদেবাড়ি

5
কোনও ভেরিয়েবল বিশেষত অভিধান কিনা তা পরীক্ষা করার জন্য আপনার সম্ভবত ব্যবহার করা উচিত isinstance(v, collections.abc.Mapping)। অন্য কথায়, এটি "আইসনস্ট্যান্স () এবং টাইপ () এর মধ্যে পার্থক্য" এর সঠিক সদৃশ নয়।
জোশ কেলি

উত্তর:


279

আপনি ব্যবহার if type(ele) is dictবা ব্যবহার isinstance(ele, dict)করতে পারেন যা কাজ করবে যদি আপনি সাবক্ল্যাস করা থাকে dict:

d = {'abc':'abc','def':{'ghi':'ghi','jkl':'jkl'}}
for ele in d.values():
    if isinstance(ele,dict):
       for k, v in ele.items():
           print(k,' ',v)

70
আমি এই উত্তর নিচে- ভোট কারণ সাধারণ প্রশ্ন গুলোর সঠিক উত্তর হল: isinstance(ele, collections.Mapping)। এটা তোলে জন্য কাজ করে dict(), collections.OrderedDict()এবং collections.UserDict()। প্রশ্নে উদাহরণটি প্যাড্রিয়াকের কাজের উত্তরের জন্য যথেষ্ট নির্দিষ্ট, তবে সাধারণ ক্ষেত্রে এটি যথেষ্ট ভাল নয়।
আলেকজান্ডার রায়ঝভ

3
আমি এই উত্তরটিকে উঁচু করে দিয়েছি কারণ আপনি যদি অনুরোধ করতে যাচ্ছেন তবে আপনি ele.items()কেন পরীক্ষা করছেন? EAFP / হাঁস-টাইপিং এখানে কাজ করে, শুধু মোড়ানো for k,v in ele.items()মধ্যে try...except (AttributeError, TypeError)। যদি ব্যতিক্রম উত্থাপিত হয় তবে আপনারা জানেন যে এর থেকে পুনরাবৃত্তিযোগ্য ফলন পাওয়া যায় eleনা items...
কাওবার্ট

@ প্যাডেরিক কানিংহাম আপনার অনুমানের প্রান্তের ক্ষেত্রে আপনার "100% ডিক্ট নয়" কাস্টম ক্লাসের প্রয়োজন হবে। একটি items()পদ্ধতি ছিল 2. যা কেবল পুনরাবৃত্ত এবং 3 ফলন করতে ঘটেছে যেখানে সেই পুনরাবৃত্তির প্রতিটি উপাদান 2 হিসাবে উপস্থাপিত হতে পারে -tuple। এই মুহুর্তে আপনার কাস্টম অবজেক্ট ইতিমধ্যে ইতিমধ্যে অর্ধেক ডিক প্রয়োগ করেছে। তালিকাভুক্ত কোডের উদ্দেশ্যে আমরা কেবল নেস্টেড উপাদানটির শর্তাধীন সম্প্রসারণের যত্ন নিয়েছি এবং আপনার কাস্টম অবজেক্ট ইতিমধ্যে এটি প্রয়োগ করে। (আপনি কিছুটা বিদ্রূপাত্মক যে আপনি @ আলেকজান্ডার রায়ঝভের মন্তব্য খুব সাধারণ হওয়ার জন্য সমালোচনা করলেও এখন একটি সাধারণ ঘটনা উত্থাপন করুন)
কাউয়ার্ট

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

4
@ আলেকজান্ডাররেজভ এই উত্তরটি কেন উত্তর হিসাবে পোস্ট করবেন না? বিটিডাব্লু যেমন জোশ কেলির উপরে পরামর্শ হিসাবে মন্তব্য করেছেনcollections.abc.Mapping , একটি নোট উপযুক্ত হতে পারে যে সেগুলি একই রকম, তবে collections.abcপাইথন ৩.৩-এর আগে পাওয়া যায় না। collections.Mappingঅ্যালাইফটি পাইথন এখনও in.6 এ উপলব্ধ, তবে নথিভুক্ত নয়, তাই সম্ভবত কোনওটিকেই পছন্দ করা উচিত collections.abc.Maping
ইয়ুশিন ওয়াশিও

4

পাইথনের কোনও ভেরিয়েবল একটি অভিধান কিনা তা আপনি কীভাবে পরীক্ষা করবেন?

এটি একটি দুর্দান্ত প্রশ্ন, তবে এটি দুর্ভাগ্যজনক যে সর্বাধিক উত্সাহিত উত্তর একটি দুর্বল সুপারিশ নিয়ে আসে type(obj) is dict,।

(মনে রাখবেন যে আপনার dictপরিবর্তনশীল নাম হিসাবেও ব্যবহার করা উচিত নয় - এটি বিল্টিন অবজেক্টের নাম))

যদি আপনি এমন কোড লিখতে থাকেন যা অন্যরা আমদানি এবং ব্যবহার করবে, তবে মনে করবেন না যে তারা ডিক্ট বিল্টিন সরাসরি ব্যবহার করবে - এই অনুমান করা আপনার কোডটিকে আরও জটিল করে তোলে এবং এই ক্ষেত্রে সহজেই লুকানো বাগগুলি তৈরি করে যা প্রোগ্রামটিকে ত্রুটিযুক্ত করবে না create ।

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

isবস্তুর পরিচয়ের জন্য পরীক্ষা । এটি উত্তরাধিকারকে সমর্থন করে না, এটি কোনও বিমূর্ততা সমর্থন করে না এবং এটি ইন্টারফেসকে সমর্থন করে না।

তাই আমি বিভিন্ন বিকল্প প্রদান করব।

সহায়ক উত্তরাধিকার:

এই প্রথম সুপারিশ আমি করতে হবে, কারণ এটা ব্যবহারকারীদের একটি অভি তাদের নিজস্ব উপশ্রেণী, অথবা সরবরাহ জন্য করতে পারবেন OrderedDict, defaultdictঅথবা Counterথেকে সংগ্রহ মডিউল:

if isinstance(any_object, dict):

তবে আরও নমনীয় বিকল্প রয়েছে।

সমর্থন বিমূর্ততা:

from collections.abc import Mapping

if isinstance(any_object, Mapping):

এটি আপনার কোডের ব্যবহারকারীর একটি বিমূর্ত ম্যাপিংয়ের নিজস্ব কাস্টম বাস্তবায়ন ব্যবহার করতে সহায়তা করে, যার কোনও সাবক্লাসও অন্তর্ভুক্ত রয়েছে dictএবং এখনও সঠিক আচরণ পেতে পারে।

ইন্টারফেস ব্যবহার করুন

আপনি সাধারণত ওওপি পরামর্শ, "ইন্টারফেস থেকে প্রোগ্রাম" শুনতে পান।

এই কৌশলটি পাইথনের পলিমারফিজম বা হাঁস-টাইপিংয়ের সুবিধা নেয়।

সুতরাং কেবলমাত্র যুক্তিসঙ্গত ফ্যালব্যাক সহ নির্দিষ্ট প্রত্যাশিত ত্রুটিগুলি ( AttributeErrorযদি নেই .itemsএবং TypeErrorক্ষেত্রে কল itemsকরা যায় না) ধরে ইন্টারফেসটি অ্যাক্সেস করার চেষ্টা করুন - এবং এখন যে ইন্টারফেসটি প্রয়োগ করে এমন কোনও শ্রেণি আপনাকে তার আইটেম দেবে (নোটটি .iteritems()পাইথনে গেছে 3):

try:
    items = any_object.items()
except (AttributeError, TypeError):
    non_items_behavior(any_object)
else: # no exception raised
    for item in items: ...

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

উপসংহার

isপ্রমিত নিয়ন্ত্রণ প্রবাহের জন্য প্রকারগুলি পরীক্ষা করতে ব্যবহার করবেন না । ব্যবহার করুন isinstance, Mappingবা মত বিমূর্তি বিবেচনা করুন MutableMappingএবং সরাসরি ইন্টারফেস ব্যবহার করে টাইপ-চেকিং এড়ানো সম্পূর্ণ বিবেচনা করুন।


3

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

উপরের মন্তব্যে অভিধানের জন্য পরীক্ষার জন্য খাঁটি পাইথন (3.8) এর প্রস্তাবিত উপায় অনুসরণ করুন ।

from collections.abc import Mapping

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}

def parse_dict(in_dict): 
    if isinstance(in_dict, Mapping):
        for k, v in in_dict.items():
            if isinstance(v, Mapping):
                for k, v in v.items():
                    print(k, v)
            else:
                print(k, v)

parse_dict(dict)

dict.iteritems()পাইথন 3 তে বিদ্যমান নেই, তার dict.items()পরিবর্তে আপনার ব্যবহার করা উচিত ।
আরকেলিস

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