if hasattr(obj, 'attribute'):
# do somthing
বনাম
try:
# access obj.attribute
except AttributeError, e:
# deal with AttributeError
কোনটি পছন্দ করা উচিত এবং কেন?
উত্তর:
hasattrঅভ্যন্তরীণভাবে এবং দ্রুত try/exceptব্লকের মতো একই কাজটি সম্পাদন করে : এটি একটি খুব নির্দিষ্ট, অনুকূলিত, এক-টাস্ক টুল এবং সুতরাং প্রযোজ্য ক্ষেত্রে খুব সাধারণ-উদ্দেশ্য বিকল্প হিসাবে পছন্দ করা উচিত।
hasattrহবে সব ব্যতিক্রম ধরা পাইথন 2.x. মধ্যে দেখুন আমার উত্তর একটি উদাহরণ এবং তুচ্ছ কার্যসংক্রান্ত জন্য।
tryঅভিব্যক্তিটি কাজ করা উচিত যে জানাতে পারেন । যদিও tryঅভিপ্রায়টি সর্বদা এ জাতীয় নয় তবে এটি সাধারণ, তাই এটি আরও পাঠযোগ্য বলে বিবেচিত হতে পারে।
পারফরম্যান্সের পার্থক্যের চিত্রিত কোন বেঞ্চ?
সময়মত এটি আপনার বন্ধু
$ 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
tryযত দ্রুত প্রায় দ্বিগুন হয় hasattr()। যদি এটি না tryহয় তবে 1.5x এর চেয়ে ধীর গতিতে hasattr()(এবং উভয়ই বৈশিষ্ট্যের অস্তিত্বের তুলনায় যথেষ্ট ধীর হয়)। এটি সম্ভবত কারণ, সুখী পথে, tryখুব কমই কিছু করে (পাইথন ইতিমধ্যে ব্যতিক্রমগুলির ওভারহেডের জন্য অর্থ প্রদান করছে আপনি সেগুলি ব্যবহার না করেই), তবে hasattr()নাম অনুসন্ধান এবং ফাংশন কল প্রয়োজন। অসুখী পথে, তাদের দুজনকে কিছু ব্যতিক্রম হ্যান্ডলিং এবং একটি করতে হবে gotoতবে hasattr()এটি পাইথন বাইটকোডের চেয়ে সি-তে করে।
একটি তৃতীয় এবং প্রায়শই ভাল বিকল্প রয়েছে:
attr = getattr(obj, 'attribute', None)
if attr is not None:
print attr
সুবিধাদি:
getattrমার্টিন গিজার নির্দেশিত খারাপ ব্যতিক্রম-গিলে ফেলার আচরণ নেই - পুরানো পাইথনসে, hasattrএমনকি একটি গিলে ফেলবে KeyboardInterrupt।
অবজেক্টটির কোনও বৈশিষ্ট্য রয়েছে কিনা তা আপনি যাচাই করছেন তার কারণ হ'ল আপনি বৈশিষ্ট্যটি ব্যবহার করতে পারেন এবং এটি স্বাভাবিকভাবেই এটির দিকে নিয়ে যায়।
অ্যাট্রিবিউটটি পরমাণুভাবে পড়া হয়, এবং অন্য থ্রেড থেকে অবজেক্ট পরিবর্তন করা নিরাপদ। (যদিও এটি যদি প্রধান উদ্বেগ হয় তবে আপনি অ্যাক্সেসের আগে লক করা বিবেচনা করতে পারেন))
এটা তোলে চেয়ে খাটো এর try/finallyএবং প্রায়ই চেয়ে খাটো hasattr।
আপনি যেটা আশা করছেন তা ব্যতীত একটি বিস্তৃত except AttributeErrorব্লক ধরতে পারে AttributeErrors, যা বিভ্রান্তিমূলক আচরণের দিকে নিয়ে যেতে পারে।
স্থানীয় ভেরিয়েবল অ্যাক্সেস করার চেয়ে কোনও অ্যাট্রিবিউট অ্যাক্সেস করা ধীর হয় (বিশেষত যদি এটি সরল উদাহরণ বৈশিষ্ট্য নয়)। (যদিও সত্য কথা বলতে গেলে পাইথনে মাইক্রো অপ্টিমাইজেশন প্রায়শই একটি বোকামির কাজ)
একটি বিষয় সাবধান হওয়া উচিত যদি আপনি কেইস obj.attributeকে সেট করেন না সে ক্ষেত্রে যত্নশীল হন , আপনাকে আলাদা আলাদা সেন্ডিনেল মান ব্যবহার করতে হবে।
আমি প্রায় সর্বদা ব্যবহার করি 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পরিস্থিতি মোকাবেলা করা যাক এবং এরপরে উপযুক্ত ব্যতিক্রমটি বাড়িয়ে তুলতে পারে।
safehasattr, কেবলমাত্র getattrস্থানীয় ভেরিয়েবলে মানটি অনুলিপি করতে ব্যবহার করুন যদি আপনি এটি ব্যবহার করতে চলেছেন যা আপনি প্রায় সর্বদা হন।
hasattrএরকম উন্নতি হয়েছে।
hasattr, এবং যাচাই করতে গেলাম। আমাদের কাছে কিছু মজার bzr বাগ রয়েছে যেখানে hasattr সবেমাত্র ডিগ্রি সেলসিয়াস গ্রাস করেছে।
আমি বলব এটি আপনার ফাংশন ডিজাইনের দ্বারা অ্যাট্রিবিউট ছাড়াই অবজেক্টগুলি গ্রহণ করতে পারে তার উপর নির্ভর করে , উদাহরণস্বরূপ যদি আপনার ফাংশনে দু'জন কলার থাকে তবে একটি বৈশিষ্ট্য সরবরাহ করে এবং অন্যটি এটি ছাড়াই কোনও সরবরাহ সরবরাহ করে।
বৈশিষ্ট্য ব্যতীত আপনি কোনও অবজেক্ট পাবেন এমন কোনও ক্ষেত্রে যদি কিছু ত্রুটির কারণে ঘটে থাকে তবে আমি ব্যতিক্রম প্রক্রিয়াটি ধীর হতে পারে তবে এটি ব্যবহার করার পরামর্শ দেব, কারণ আমি বিশ্বাস করি এটি একটি ক্লিনার ডিজাইন।
নীচের লাইন: আমি মনে করি এটি দক্ষতার সমস্যাটির চেয়ে একটি নকশা এবং পঠনযোগ্যতার সমস্যা।
যদি অ্যাট্রিবিউটটি না থাকা একটি ত্রুটি শর্ত না হয় তবে ব্যতিক্রম হ্যান্ডলিং ভেরিয়েন্টে একটি সমস্যা রয়েছে: এটি অজেক্ট.অ্যাট্রিবিউট অ্যাক্সেস করার সময় অভ্যন্তরীণভাবে আসতে পারে এমন অ্যাট্রিবিউটরিজগুলিও ধরতে পারে (উদাহরণস্বরূপ কারণ অ্যাট্রিবিউটটি এমন একটি সম্পত্তি যাতে এটি অ্যাক্সেস করে কিছু কোড কল করে)।
এই বিষয়টি ইউরোপাইথন 2016 এর আলোচনার আওতায় পড়েছিল সেবাস্তিয়ান উইটোভস্কি লিখেছেন দ্রুত পাইথন রচনা। এখানে পারফরম্যান্সের সংক্ষিপ্তসার সহ তাঁর স্লাইডটির একটি পুনরুত্পাদন। আপনি এই আলোচনায় ঝাঁপ দেওয়ার আগে তিনি পরিভাষা চেহারাটিও ব্যবহার করেন , সেই কীওয়ার্ডটি ট্যাগ করার জন্য এখানে উল্লেখ করার মতো।
যদি বৈশিষ্ট্যটি আসলে অনুপস্থিত থাকে তবে ক্ষমা প্রার্থনা করা অনুমতি চেয়ে জিজ্ঞাসা করা ধীর হবে। সুতরাং থাম্বের একটি নিয়ম হিসাবে আপনি অনুমতি চাওয়ার উপায়টি ব্যবহার করতে পারেন যদি জানেন যে বৈশিষ্টটি অনুপস্থিত বা আপনার ভবিষ্যদ্বাণী করতে পারে এমন অন্যান্য সমস্যা সম্ভবত রয়েছে very অন্যথায় আপনি যদি আশা করেন কোড বেশিরভাগ সময় পঠনযোগ্য কোডের ফলাফল করে
# 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
আমি বিকল্পটি 2 টি পরামর্শ দিই 1 বিকল্প 1 টিতে একটি রেসের শর্ত রয়েছে যদি অন্য কোনও থ্রেড যুক্ত বা যুক্ত করে মুছে ফেলা হয়।
অজগরটির একটি ইডিয়ামও রয়েছে , যে ইএএফপি ('অনুমতি চেয়ে ক্ষমা চাওয়া সহজ') এলবিওয়াইএল ('লাফানোর আগে দেখুন') এর চেয়ে ভাল।
ব্যবহারিক দৃষ্টিকোণ থেকে, বেশিরভাগ ভাষায় শর্তসাপেক্ষ ব্যবহারটি সর্বদা একটি ব্যতিক্রম পরিচালনার চেয়ে দ্রুততর হবে faster
যদি আপনি বর্তমান ফাংশনের বাইরে কোথাও বিদ্যমান না এমন কোনও অ্যাট্রিবিউটর মামলা পরিচালনা করতে চান তবে ব্যতিক্রমটি আরও ভাল উপায়। আপনি একটি শর্তসাপেক্ষীর পরিবর্তে একটি ব্যতিক্রম ব্যবহার করতে চাইতে পারেন এমন একটি সূচক হ'ল শর্তসাপেক্ষে কেবল একটি পতাকা সেট করে এবং বর্তমান অপারেশনটি বাতিল করে দেয় এবং অন্য কোথাও কোনও কিছু এই পতাকাটি পরীক্ষা করে এবং এর ভিত্তিতে ব্যবস্থা গ্রহণ করে।
রেক্স অলগুড যেমন বলেছিলেন, অন্যের সাথে যোগাযোগ করা কোডের একটি গুরুত্বপূর্ণ বৈশিষ্ট্য, এবং "এটি একটি ব্যতিক্রমী পরিস্থিতি" বলে আপনি কী বলতে চান, "এটি এমন কিছু যা আমি প্রত্যাশা করি" এর চেয়ে আরও গুরুত্বপূর্ণ হতে পারে ।
প্রথম.
খাটো আরও ভাল। ব্যতিক্রম ব্যতিক্রমী হওয়া উচিত।
forবিবৃতি শেষে একটি রয়েছে এবং hasattrএকটিও ব্যবহার করে। তবে, "সংক্ষিপ্ততর ভাল" (এবং "সহজতরতর ভাল"!) প্রয়োগ করুন, তাই সহজ, খাটো, আরও নির্দিষ্ট-তাত্ক্ষণিক প্রকৃত পক্ষে পছন্দনীয়।
অন্ততপক্ষে যখন প্রোগ্রামের মধ্যে যা চলছে তা কেবল পাঠযোগ্যতার মানব অংশকে ছেড়ে চলে যেতে পারে ইত্যাদি (যা আসলে বেশিরভাগ সময় পারফরম্যান্সের চেয়ে বেশি গুরুত্বপূর্ণ (কমপক্ষে এই ক্ষেত্রে - সেই পারফরম্যান্স স্প্যান সহ)), যেমনটি রই অ্যাডলার এবং অন্যরা নির্দেশ করেছেন)।
তবুও এটাকে সেই দৃষ্টিকোণ থেকে দেখার পরে এটি তার মধ্যে বাছাইয়ের বিষয়টি হয়ে যায়
try: getattr(obj, attr)
except: ...
এবং
try: obj.attr
except: ...
যেহেতু hasattrফলাফল নির্ধারণের জন্য কেবল প্রথম কেস ব্যবহার করে। চিন্তার জন্য খাদ্য ;-)