অস্তিত্বহীন বৈশিষ্ট্যগুলি মোকাবেলায় hasattr () বনাম চেষ্টা-বাদে ব্লক করুন


85
if hasattr(obj, 'attribute'):
    # do somthing

বনাম

try:
    # access obj.attribute
except AttributeError, e:
    # deal with AttributeError

কোনটি পছন্দ করা উচিত এবং কেন?


উত্তর:


82

hasattrঅভ্যন্তরীণভাবে এবং দ্রুত try/exceptব্লকের মতো একই কাজটি সম্পাদন করে : এটি একটি খুব নির্দিষ্ট, অনুকূলিত, এক-টাস্ক টুল এবং সুতরাং প্রযোজ্য ক্ষেত্রে খুব সাধারণ-উদ্দেশ্য বিকল্প হিসাবে পছন্দ করা উচিত।


8
জাতি শর্তগুলি পরিচালনা করতে আপনার এখনও চেষ্টা / ক্যাপ ব্লক প্রয়োজন (যদি আপনি থ্রেড ব্যবহার করছেন)।
ডগলাস লিডার

4
বা, আমি সবেমাত্র বিশেষ কেসটি দেখতে পেলাম: একটি জ্যাঙ্গো ওয়ানটোওফিল্ডের কোনও মূল্য নেই: হ্যাশট্র (ওজেক্ট, ফিল্ড_নাম) মিথ্যা ফিরিয়ে দেয়, তবে ক্ষেত্রের নামের সাথে একটি বৈশিষ্ট্য রয়েছে: এটি কেবল একটি ডোনটেক্সিস্ট ত্রুটি উত্থাপন করে।
ম্যাথু শিনকেল

4
মনে রাখবেন যে, hasattrহবে সব ব্যতিক্রম ধরা পাইথন 2.x. মধ্যে দেখুন আমার উত্তর একটি উদাহরণ এবং তুচ্ছ কার্যসংক্রান্ত জন্য।
মার্টিন গিসলার

4
একটি আকর্ষণীয় মন্তব্য : tryঅভিব্যক্তিটি কাজ করা উচিত যে জানাতে পারেন । যদিও tryঅভিপ্রায়টি সর্বদা এ জাতীয় নয় তবে এটি সাধারণ, তাই এটি আরও পাঠযোগ্য বলে বিবেচিত হতে পারে।
আইওনিস ফিলিপিসিস

88

পারফরম্যান্সের পার্থক্যের চিত্রিত কোন বেঞ্চ?

সময়মত এটি আপনার বন্ধু

$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "nonexistent")'
1000000 loops, best of 3: 1.87 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "a")'
1000000 loops, best of 3: 0.446 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.a
except:
 pass'
1000000 loops, best of 3: 0.247 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.nonexistent
except:
 pass'
100000 loops, best of 3: 3.13 usec per loop
$

       |positive|negative
hasattr|  0.446 |  1.87 
try    |  0.247 |  3.13

16
আকর্ষণীয়, বাস্তব সংখ্যা সরবরাহের জন্য +1। আসলে, "ট্রাই" দক্ষ হয় যখন এটি সাধারণ ক্ষেত্রে থাকে (যেমন যখন পাইথনের ব্যতিক্রম সত্যিই ব্যতিক্রমী হয়)।
এরিক হে লেবিগোট

এই ফলাফলগুলি কীভাবে ব্যাখ্যা করা যায় তা আমি নিশ্চিত নই। এখানে কোনটি দ্রুত এবং কতটা?
স্টিভয়েসিয়াক

4
@ StevenM.Vascellaro: অ্যাট্রিবিউট যদি থেকেই থাকে, tryযত দ্রুত প্রায় দ্বিগুন হয় hasattr()। যদি এটি না tryহয় তবে 1.5x এর চেয়ে ধীর গতিতে hasattr()(এবং উভয়ই বৈশিষ্ট্যের অস্তিত্বের তুলনায় যথেষ্ট ধীর হয়)। এটি সম্ভবত কারণ, সুখী পথে, tryখুব কমই কিছু করে (পাইথন ইতিমধ্যে ব্যতিক্রমগুলির ওভারহেডের জন্য অর্থ প্রদান করছে আপনি সেগুলি ব্যবহার না করেই), তবে hasattr()নাম অনুসন্ধান এবং ফাংশন কল প্রয়োজন। অসুখী পথে, তাদের দুজনকে কিছু ব্যতিক্রম হ্যান্ডলিং এবং একটি করতে হবে gotoতবে hasattr()এটি পাইথন বাইটকোডের চেয়ে সি-তে করে।
কেভিন

24

একটি তৃতীয় এবং প্রায়শই ভাল বিকল্প রয়েছে:

attr = getattr(obj, 'attribute', None)
if attr is not None:
     print attr

সুবিধাদি:

  1. getattrমার্টিন গিজার নির্দেশিত খারাপ ব্যতিক্রম-গিলে ফেলার আচরণ নেই - পুরানো পাইথনসে, hasattrএমনকি একটি গিলে ফেলবে KeyboardInterrupt

  2. অবজেক্টটির কোনও বৈশিষ্ট্য রয়েছে কিনা তা আপনি যাচাই করছেন তার কারণ হ'ল আপনি বৈশিষ্ট্যটি ব্যবহার করতে পারেন এবং এটি স্বাভাবিকভাবেই এটির দিকে নিয়ে যায়।

  3. অ্যাট্রিবিউটটি পরমাণুভাবে পড়া হয়, এবং অন্য থ্রেড থেকে অবজেক্ট পরিবর্তন করা নিরাপদ। (যদিও এটি যদি প্রধান উদ্বেগ হয় তবে আপনি অ্যাক্সেসের আগে লক করা বিবেচনা করতে পারেন))

  4. এটা তোলে চেয়ে খাটো এর try/finallyএবং প্রায়ই চেয়ে খাটো hasattr

  5. আপনি যেটা আশা করছেন তা ব্যতীত একটি বিস্তৃত except AttributeErrorব্লক ধরতে পারে AttributeErrors, যা বিভ্রান্তিমূলক আচরণের দিকে নিয়ে যেতে পারে।

  6. স্থানীয় ভেরিয়েবল অ্যাক্সেস করার চেয়ে কোনও অ্যাট্রিবিউট অ্যাক্সেস করা ধীর হয় (বিশেষত যদি এটি সরল উদাহরণ বৈশিষ্ট্য নয়)। (যদিও সত্য কথা বলতে গেলে পাইথনে মাইক্রো অপ্টিমাইজেশন প্রায়শই একটি বোকামির কাজ)

একটি বিষয় সাবধান হওয়া উচিত যদি আপনি কেইস obj.attributeকে সেট করেন না সে ক্ষেত্রে যত্নশীল হন , আপনাকে আলাদা আলাদা সেন্ডিনেল মান ব্যবহার করতে হবে।


4
+1 টি - এই dict.get সঙ্গে লিগ হয় ( 'my_key', 'DEFAULT_VALUE') এবং আরো ব্যাপকভাবে সম্পর্কে পরিচিত করা উচিত

4
সাধারণ ব্যবহারের ক্ষেত্রে দুর্দান্ত আপনি যেখানে অস্তিত্ব পরীক্ষা করতে এবং ডিফল্ট মান সহ বৈশিষ্ট্যটি ব্যবহার করতে চান।
dsalaj

18

আমি প্রায় সর্বদা ব্যবহার করি hasattr: বেশিরভাগ ক্ষেত্রে এটি সঠিক পছন্দ।

সমস্যাযুক্ত ক্ষেত্রে যখন একটি বর্গ অগ্রাহ্য হয় __getattr__: hasattrহবে সব ব্যতিক্রম ধরা পরিবর্তে সংক্রামক শুধু AttributeErrorমনে হচ্ছে আপনি আশা। অন্য কথায়, নীচের কোডটি মুদ্রণ করবে b: Falseযদিও এটি ValueErrorব্যতিক্রম দেখতে আরও উপযুক্ত হবে :

class X(object):
    def __getattr__(self, attr):
        if attr == 'a':
            return 123
        if attr == 'b':
            raise ValueError('important error from your database')
        raise AttributeError

x = X()
print 'a:', hasattr(x, 'a')
print 'b:', hasattr(x, 'b')
print 'c:', hasattr(x, 'c')

গুরুত্বপূর্ণ ত্রুটি এইভাবে অদৃশ্য হয়ে গেছে। এটি পাইথন 3.2 ( ইস্যু 9666 ) এ স্থির করা হয়েছে যেখানে hasattrএখন কেবল ক্যাচ AttributeError

একটি সহজ কাজ হ'ল এইভাবে একটি ইউটিলিটি ফাংশন লিখুন:

_notset = object()

def safehasattr(thing, attr):
    return getattr(thing, attr, _notset) is not _notset

এটি getattrপরিস্থিতি মোকাবেলা করা যাক এবং এরপরে উপযুক্ত ব্যতিক্রমটি বাড়িয়ে তুলতে পারে।


4
পাইথন ২..6 এ এটিও কিছুটা উন্নত হয়েছিল যাতে hasattrকমপক্ষে KeyboardInterruptইত্যাদি ধরা পড়বে না
পুলি

অথবা, পরিবর্তে safehasattr, কেবলমাত্র getattrস্থানীয় ভেরিয়েবলে মানটি অনুলিপি করতে ব্যবহার করুন যদি আপনি এটি ব্যবহার করতে চলেছেন যা আপনি প্রায় সর্বদা হন।
পুলি

@ পুলি এটি দুর্দান্ত, আমি জানতাম না যে hasattrএরকম উন্নতি হয়েছে।
মার্টিন গিজলার

হ্যা এটি ভাল. আমি জানি না যে আজ অবধি যখন আমি কাউকে এড়াতে বলব hasattr, এবং যাচাই করতে গেলাম। আমাদের কাছে কিছু মজার bzr বাগ রয়েছে যেখানে hasattr সবেমাত্র ডিগ্রি সেলসিয়াস গ্রাস করেছে।
পুলি

2.7 থেকে 3.6 আপগ্রেড করার সময় সমস্যার মুখোমুখি হয়েছিল। এই উত্তরটি আমাকে সমস্যা বুঝতে এবং সমাধান করতে সহায়তা করে।
কামেশ জঙ্গি

13

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

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

নীচের লাইন: আমি মনে করি এটি দক্ষতার সমস্যাটির চেয়ে একটি নকশা এবং পঠনযোগ্যতার সমস্যা।


4
কোডটি পড়ে এমন লোকদের জন্য কেন "চেষ্টা" এর অর্থ রয়েছে তা জোর দেওয়ার জন্য +1। :)
এরিক হে লেবিগোট

5

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


এটি একটি বড় সমস্যা যা আমার মতে মূলত উপেক্ষা করা হয়েছে।
রিক মনিকা

5

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

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

3 পারমিশন বা ক্ষমা?

# CASE 1 -- Attribute Exists
class Foo(object):
    hello = 'world'
foo = Foo()

if hasatter(foo, 'hello'):
    foo.hello
## 149ns ##

try:
    foo.hello
except AttributeError:
    pass
## 43.1 ns ##
## 3.5 times faster


# CASE 2 -- Attribute Absent
class Bar(object):
    pass
bar = Bar()

if hasattr(bar, 'hello'):
    bar.hello
## 428 ns ##

try:
    bar.hello
except AttributeError :
    pass
## 536 ns ##
## 25% slower

4

যদি আপনি এটির পরীক্ষা নিরীক্ষণ করেন তবে আমি অবশ্যই এটি ব্যবহার করব hasattr। তবে, আপনি যদি এমন বৈশিষ্ট্যগুলির বেশ কয়েকটি অ্যাকসেস করছেন যা উপস্থিত থাকতে পারে বা নাও থাকতে পারে তবে tryব্লক ব্যবহার করা আপনাকে কিছু টাইপ করে বাঁচাতে পারে।


3

আমি বিকল্পটি 2 টি পরামর্শ দিই 1 বিকল্প 1 টিতে একটি রেসের শর্ত রয়েছে যদি অন্য কোনও থ্রেড যুক্ত বা যুক্ত করে মুছে ফেলা হয়।

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


2

ব্যবহারিক দৃষ্টিকোণ থেকে, বেশিরভাগ ভাষায় শর্তসাপেক্ষ ব্যবহারটি সর্বদা একটি ব্যতিক্রম পরিচালনার চেয়ে দ্রুততর হবে faster

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

রেক্স অলগুড যেমন বলেছিলেন, অন্যের সাথে যোগাযোগ করা কোডের একটি গুরুত্বপূর্ণ বৈশিষ্ট্য, এবং "এটি একটি ব্যতিক্রমী পরিস্থিতি" বলে আপনি কী বলতে চান, "এটি এমন কিছু যা আমি প্রত্যাশা করি" এর চেয়ে আরও গুরুত্বপূর্ণ হতে পারে ।


শর্তাধীন পরীক্ষার তুলনায় "এটি চেষ্টা" ব্যতীত "এটি একটি ব্যতিক্রমী পরিস্থিতি" হিসাবে ব্যাখ্যা করা যেতে পারে এমন বিষয়ে জোর দেওয়ার জন্য +1। :)
এরিক হে লেবিগোট

0

প্রথম.

খাটো আরও ভাল। ব্যতিক্রম ব্যতিক্রমী হওয়া উচিত।


4
পাইথনে ব্যতিক্রমগুলি খুব সাধারণ - প্রতিটি forবিবৃতি শেষে একটি রয়েছে এবং hasattrএকটিও ব্যবহার করে। তবে, "সংক্ষিপ্ততর ভাল" (এবং "সহজতরতর ভাল"!) প্রয়োগ করুন, তাই সহজ, খাটো, আরও নির্দিষ্ট-তাত্ক্ষণিক প্রকৃত পক্ষে পছন্দনীয়।
অ্যালেক্স মার্টেলি

@ অ্যালেক্স কেবল কারণ পাইথন পার্সার এই বিবৃতিগুলিকে 1 তে রূপান্তরিত করে এর অর্থ এটি খুব সাধারণ নয়। তারা সেই সিনট্যাকটিক চিনি তৈরির কারণ রয়েছে: তাই আপনি ব্লক ব্যতীত চেষ্টা করে টাইপ করার ক্রোয়েফনে আটকে থাকেন না।
অজানা

যদি ব্যতিক্রমটি ব্যতিক্রমী হয়, তবে "সুস্পষ্টতর আরও ভাল", এবং মূল পোস্টারের দ্বিতীয় বিকল্পটি আরও ভাল, আমি বলব ...
এরিক হে লেবিগোট

0

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

তবুও এটাকে সেই দৃষ্টিকোণ থেকে দেখার পরে এটি তার মধ্যে বাছাইয়ের বিষয়টি হয়ে যায়

try: getattr(obj, attr)
except: ...

এবং

try: obj.attr
except: ...

যেহেতু hasattrফলাফল নির্ধারণের জন্য কেবল প্রথম কেস ব্যবহার করে। চিন্তার জন্য খাদ্য ;-)

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