পাইথন: এই জায়গাগুলোতে সাবধান থাকবেন

তৈরি: 2016-12-29 13:46:12, আপডেট করা হয়েছে:
comments   0
hits   1385

পাইথন: এই জায়গাগুলোতে সাবধান থাকবেন

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

  • পাইথন সংস্করণ উপেক্ষা করা হয়েছে

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

  $ python --version
  Python 2.7.9

python সংস্করণ ব্যবস্থাপনা

pyenv একটি ভাল পাইথন সংস্করণ ম্যানেজমেন্ট টুল। দুর্ভাগ্যবশত এটি শুধুমাত্র*nix সিস্টেমে। Mac OS এ, আপনি সহজেই ব্রাউ ইনস্টল pyenv ইনস্টল করতে পারেন, লিনাক্স সিস্টেমে, একটি স্বয়ংক্রিয় ইনস্টলার রয়েছে automatic installer

  • কোডের এক লাইন দিয়ে সব সমস্যার সমাধান করা

অনেক মানুষ বলে যে আমি এক লাইন কোড দিয়ে সব সমস্যার সমাধান করেছি, এমনকি যদি তাদের কোডগুলি স্বাভাবিকের চেয়ে কম কার্যকর হয়, এবং কোডগুলি পড়তে আরও কঠিন এবং এমনকি বিভ্রান্তিকর হয়। যেমনঃ

  l = [m for a, b in zip(this, that) if b.method(a) != b for m in b if not m.method(a, b) and reduce(lambda x, y: a + y.method(), (m, a, b))]

সত্যি কথা বলতে কি, এই কোডটি আমি নিজেই লিখেছি, কিন্তু আমি অনেকের সাথে এই কাজটি করেছি। আপনি যদি কেবল একটি তালিকা বা একটি সেটে কিছু যোগ করে জটিল সমস্যার সমাধান করার জন্য নিজেকে উপস্থাপন করেন, তাহলে আপনি ক্ষতিগ্রস্ত হতে পারেন।

কোডের এক লাইন নিয়ন্ত্রণ করা খুব একটা বড় ব্যাপার নয়, যদিও মাঝে মাঝে মনে হয় এটি অত্যন্ত বুদ্ধিমান। ভাল কোডটি সংক্ষিপ্ত কিন্তু দক্ষতা এবং সহজ পাঠযোগ্যতার উপর বেশি গুরুত্ব দেয়।

  • ভুলভাবে সেট ইনিশিয়েল করা হয়েছে

এটি একটি আরো সূক্ষ্ম প্রশ্ন, এবং কখনও কখনও এটি আপনার হাতের মুঠোয় আসে না। সেট ডিডাকশনটি কিছুটা তালিকা ডিডাকশনের মতো।

  >>> { n for n in range(10) if n % 2 == 0 }
  {0, 8, 2, 4, 6}
  >>> type({ n for n in range(10) if n % 2 == 0 })

উপরের উদাহরণটি এটিকে বোঝায়। সেটটি একটি পাত্রে একটি তালিকা রাখার মতো। তাদের মধ্যে পার্থক্য হল যে, সেটটির কোন পুনরাবৃত্তি নেই এবং সেটটি অনিয়ন্ত্রিত। মানুষ সাধারণত {} কে একটি খালি সেট বলে মনে করে, কিন্তু এটা খালি নয়, এটা একটি খালি ডিক্ট।

  >>> {}
  {}
  >>> type({})

সুতরাং, যদি আমরা একটি খালি সেটকে প্রাথমিককরণ করতে চাই, তাহলে আমরা সেটটি ব্যবহার করতে পারি।

  >>> set()
  set()
  >>> type(set())

মনে রাখবেন যে একটি খালি সেটকে সেট হিসেবে প্রকাশ করা যেতে পারে, কিন্তু একটি সেট যার মধ্যে উপাদান রয়েছে সেটিকে সেট হিসেবে সংজ্ঞায়িত করা হয়।[1, 2]) এর চেহারা।

  • জিআইএল ভুল বোঝাবুঝি

জিআইএল (গ্লোবাল ইন্টারপ্রেটার লক) মানে যে একটি পাইথন প্রোগ্রামে শুধুমাত্র একটি থ্রেড চলতে পারে যে কোন সময়। এর মানে হল যে যখন আমরা একটি থ্রেড তৈরি করতে পারি না এবং এটির সমান্তরালভাবে চলার আশা করি। পাইথন ইন্টারপ্রেটার আসলে যা করে তা হ’ল বিভিন্ন চলমান থ্রেডকে দ্রুত স্যুইচ করা। তবে এটি একটি খুব সহজ সংস্করণ। অনেক ক্ষেত্রে প্রোগ্রামগুলি সমান্তরালভাবে চলতে থাকে, যেমন সি এক্সটেনশন লাইব্রেরি ব্যবহার করার সময়। তবে পাইথন কোডটি চলার সময় বেশিরভাগ সময় কার্যকর হয় না। অন্য কথায়, পাইথনে থ্রেডগুলি জাভা বা সি++ এর মতো নয়।

অনেক মানুষ Python এর পক্ষে যুক্তি দেখাতে চেষ্টা করবে যে এগুলো সবই আসল থ্রেড ৷ 3 এটা সত্যি, কিন্তু এটা এই সত্যকে পরিবর্তন করে না যে Python থ্রেডগুলোকে যেভাবে ব্যবহার করে তা আপনার প্রত্যাশার চেয়ে আলাদা ৷ রুবির ক্ষেত্রেও একই রকম ঘটনা ঘটেছে (এবং একটি ব্যাখ্যাকারী লক আছে) ৷

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

যাইহোক, এই সমস্যাটি প্রতিটি পাইথন প্রোগ্রামের মুখোমুখি হয় না। পাইপাই-এসটিএম হ’ল পাইথনের বাস্তবায়নের একটি উদাহরণ যা জিআইএল দ্বারা প্রভাবিত হয় না। অন্যান্য প্ল্যাটফর্মের উপর ভিত্তি করে বাস্তবায়ন যেমন জেভিএম (Jython) বা সিএলআর (CLR) (IronPython) জিআইএল সমস্যা ছাড়াই।

এই ধরনের থ্রেড ব্যবহারে সতর্ক থাকুন, কারণ আপনি যা পেতে চান তা নাও পেতে পারেন।

  • অপ্রচলিত স্টাইল ক্লাস

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

  class MyNewObject(object): # stuff here

এই নতুন ক্লাসের টুলস পুরোনো ক্লাসের কিছু মৌলিক সমস্যা সমাধান করে, যদি আপনি আগ্রহী হন তবে আপনি ডকুমেন্টেশন দেখতে পারেন।

  • ভুল পুনরাবৃত্তি

নতুনদের মধ্যে নিম্নলিখিত ভুলগুলো খুবই সাধারণঃ

  for name_index in range(len(names)):
    print(names[name_index])

এটা স্পষ্ট যে len ব্যবহার করার কোন প্রয়োজন নেই, এবং প্রকৃতপক্ষে, একটি খুব সহজ বাক্যাংশের মাধ্যমে তালিকাটি ঘুরে দেখা সম্ভবঃ

  for name in names:
     print(name)  

এছাড়াও, অনেক অন্যান্য সরঞ্জাম রয়েছে যা আপনি সহজেই পুনরাবৃত্তি করতে ব্যবহার করতে পারেন। উদাহরণস্বরূপ, জিপ দুটি তালিকার মধ্য দিয়ে যেতে পারেঃ

  for cat, dog in zip(cats, dogs):
     print(cat, dog)

যদি আমরা index এবং value list ভেরিয়েবল বিবেচনা করতে চাই, তাহলে আমরা enumerate ব্যবহার করতে পারি।

  for index, cat in enumerate(cats):
     print(cat, index)

Itertools এর মধ্যে অনেকগুলো ফাংশন আছে যেগুলো থেকে আপনি বেছে নিতে পারেন। আপনি যে ফাংশনগুলো চান তা যদি Itertools এর মধ্যে থাকে তাহলে তা ব্যবহার করা খুবই সহজ। তবে এটি ব্যবহার করার জন্য খুব বেশি ব্যবহার করবেন না।

itertools এর অপব্যবহারের ফলে StackOverflow-এর একজন বিরাট কর্মকর্তা এটি সমাধান করতে অনেক সময় ব্যয় করেছেন।

পরিবর্তনশীল ডিফল্ট প্যারামিটার ব্যবহার করে

আমি অনেকগুলো দেখেছি, যেমনঃ

  def foo(a, b, c=[]):
     # append to c
     # do some more stuff

পরিবর্তিত ডিফল্ট প্যারামিটার ব্যবহার করবেন না, বরং নিম্নলিখিত ব্যবহার করুনঃ

  def foo(a, b, c=None):
   if c is None:
     c = []
     # append to c
     # do some more stuff 

নিম্নলিখিত উদাহরণটি আমাদেরকে এই প্রশ্নটি বুঝতে সাহায্য করতে পারেঃ

  In[2]: def foo(a, b, c=[]):
  ...     c.append(a)
  ...     c.append(b)
  ...     print(c)
  ...
  In[3]: foo(1, 1)
  [1, 1]
  In[4]: foo(1, 1)
  [1, 1, 1, 1]
  In[5]: foo(1, 1)
  [1, 1, 1, 1, 1, 1]

একই c-কে প্রতিবার এই ফাংশনটি কল করার সময় পুনরাবৃত্তি করা হয়। এর ফলে কিছু অপ্রয়োজনীয় পরিণতি হতে পারে।