আমি কোনও ফাংশন থেকে কীভাবে একাধিক মান ফিরিয়ে দেব? [বন্ধ]


1067

এটি সমর্থন করে এমন ভাষাগুলিতে একাধিক মান ফেরত দেওয়ার আধ্যাত্মিক উপায়টি প্রায়শই দুর্বল হয়ে পড়ে

বিকল্প: একটি টিপল ব্যবহার করে

এই তুচ্ছ উদাহরণ বিবেচনা করুন:

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

যাইহোক, মানগুলি ফিরে আসার ফলে এটি দ্রুত সমস্যাযুক্ত হয়ে ওঠে। আপনি যদি চার বা পাঁচটি মান ফেরত চান? অবশ্যই, আপনি এগুলি চালিয়ে যেতে পারেন, তবে কোন মানটি কোথায় তা ভুলে যাওয়া সহজ হয়ে যায়। আপনি যেখানেই সেগুলি পেতে চান সেগুলি আনপ্যাক করা বরং কুশ্রী।

বিকল্প: একটি অভিধান ব্যবহার করে

পরবর্তী যৌক্তিক পদক্ষেপটি একরকম 'রেকর্ড নোটেশন' প্রবর্তন করে বলে মনে হচ্ছে। পাইথনে, এটি করার সুস্পষ্ট উপায় হ'ল ক dict

নিম্নোক্ত বিবেচনা কর:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

(কেবল স্পষ্ট করে বলতে গেলে, y0, y1 এবং y2 কেবল বিমূর্ত শনাক্তকারী হিসাবে বোঝানো হয়েছে।

এখন, আমাদের একটি ব্যবস্থা রয়েছে যার মাধ্যমে আমরা প্রত্যাবর্তিত অবজেক্টের কোনও নির্দিষ্ট সদস্যকে প্রজেক্ট করতে পারি। উদাহরণ স্বরূপ,

result['y0']

বিকল্প: একটি ক্লাস ব্যবহার করে

তবে, আরও একটি বিকল্প আছে। আমরা পরিবর্তে একটি বিশেষায়িত কাঠামো ফিরে আসতে পারে। আমি পাইথনের প্রসঙ্গে এটি তৈরি করেছি, তবে আমি নিশ্চিত এটি অন্যান্য ভাষার ক্ষেত্রেও প্রযোজ্য। আসলে আপনি যদি সি তে কাজ করতেন তবে এটি সম্ভবত আপনার একমাত্র বিকল্প হতে পারে। এখানে যায়:

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

পাইথন সালে আগের দুই সম্ভবত নদীর গভীরতানির্ণয় পরিপ্রেক্ষিতে অনুরূপ রয়েছে - পরে { y0, y1, y2 }শুধু অভ্যন্তরীণ এন্ট্রিগুলির হচ্ছে শেষ __dict__এর ReturnValue

পাইথন দ্বারা দেওয়া একটি অতিরিক্ত বৈশিষ্ট্য যদিও ক্ষুদ্র বস্তুগুলির জন্য, __slots__বৈশিষ্ট্যটি for শ্রেণিটি প্রকাশ করা যেতে পারে:

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

থেকে পাইথন রেফারেন্স ম্যানুয়াল :

__slots__ঘোষণা প্রতিটি পরিবর্তনশীল জন্য একটি মান রাখা প্রতিটি ইনস্ট্যান্সের মধ্যে উদাহরণস্বরূপ ভেরিয়েবল এবং মজুদ মাত্র যথেষ্ট স্থান একটি ক্রম লাগে। স্থানটি সংরক্ষণ করা হয়েছে কারণ __dict__প্রতিটি উদাহরণের জন্য তৈরি করা হয়নি।

বিকল্প: একটি ডেটাগ্লাস ব্যবহার করে (পাইথন 3.7+)

পাইথন ৩.7 এর নতুন ডেটাচলস ব্যবহার করে, স্বয়ংক্রিয়ভাবে যুক্ত বিশেষ পদ্ধতি, টাইপিং এবং অন্যান্য দরকারী সরঞ্জাম সহ একটি ক্লাস ফিরিয়ে দিন:

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

বিকল্প: একটি তালিকা ব্যবহার করে

আরেকটি পরামর্শ যা আমি উপেক্ষা করেছি তা বিল দ্য টিকটিকির কাছ থেকে আসে:

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

যদিও এটি আমার সবচেয়ে কম প্রিয় পদ্ধতি। আমি মনে করি আমি হাস্কেলের সংস্পর্শে কলঙ্কিত, তবে মিশ্র ধরনের তালিকার ধারণাটি আমার কাছে সর্বদা অস্বস্তি বোধ করে। এই বিশেষ উদাহরণে তালিকাটি হ'ল-মিশ্র প্রকার নয়, তবে এটি অনুমেয় হতে পারে।

এইভাবে ব্যবহৃত তালিকাগুলি টিপলের প্রতি শ্রদ্ধার সাথে আসলে যতটা আমি বলতে পারি কিছুই লাভ করে না। পাইথনের তালিকাগুলি এবং টিপলসের মধ্যে একমাত্র আসল পার্থক্য হ'ল তালিকাগুলি পরিবর্তনযোগ্য , যেখানে টিপলস হয় না।

আমি ব্যক্তিগতভাবে ফাংশনাল প্রোগ্রামিং থেকে সম্মেলনগুলি বহন করার প্রবণতা রাখি: একই ধরণের যে কোনও সংখ্যক উপাদানের জন্য তালিকা ব্যবহার করুন এবং পূর্বনির্ধারিত ধরণের উপাদানগুলির একটি নির্দিষ্ট সংখ্যার জন্য টিপলস ব্যবহার করুন।

প্রশ্ন

দীর্ঘ উপস্থাপকের পরে, অনিবার্য প্রশ্ন আসে। কোন পদ্ধতিটি (আপনার মনে হয়) সবচেয়ে ভাল?


10
আপনার দুর্দান্ত উদাহরণগুলিতে আপনি পরিবর্তনশীল ব্যবহার করেন y3তবে y3 কে বিশ্বব্যাপী ঘোষিত না করা হলে এটি NameError: global name 'y3' is not definedকেবলমাত্র ব্যবহারের ফলস্বরূপ 3?
hetepepphaan

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

@ হিট্পেপ্পানকে 3 পরিবর্তন করার দরকার নেই, এবং বিশ্বব্যাপী y3 সংজ্ঞায়িতও করা হচ্ছে না, আপনি একটি স্থানীয় নামও ব্যবহার করতে পারেন y3, এটি একই কাজটিও করবে।
ঠিক আছে

উত্তর:


637

এই কাজের জন্য নামকরণ করা টিউপসগুলি ২.6-এ যুক্ত করা হয়েছিল। অনুরূপ অন্তর্নির্মিত উদাহরণের জন্য os.stat দেখুন ।

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

পাইথন 3 (3.6+, আমি মনে করি) এর সাম্প্রতিক সংস্করণগুলিতে, নতুন typingলাইব্রেরি নামকৃত টিপলগুলি NamedTupleতৈরি করা আরও সহজ এবং আরও শক্তিশালী করার জন্য ক্লাস পেয়েছে । থেকে typing.NamedTupleইনহেরিটিং আপনাকে ডকাস্ট্রিংস, ডিফল্ট মান এবং টীকা টিকা ব্যবহার করতে দেয়।

উদাহরণ (ডক্স থেকে):

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3

68
এটি কেবলমাত্র সঠিক উত্তর কারণ এটিই কেবলমাত্র প্রচলিত কাঠামো যা ওপি বিবেচনা করে না এবং কারণ এটি দীর্ঘ টিপলগুলি পরিচালনা করার ক্ষেত্রে তার সমস্যাটির সমাধান করে। স্বীকৃত হিসাবে চিহ্নিত করা উচিত।
এয়ারট্রাইক

7
ঠিক আছে, এর জন্য নকশার যুক্তিতে ভর ফলাফলের namedtupleজন্য ছোট মেমরির পদক্ষেপ রয়েছে (টিপলগুলির দীর্ঘ তালিকা, যেমন ডিবি কোয়েরির ফলাফল)। স্বতন্ত্র আইটেমগুলির জন্য (যদি প্রশ্নে ফাংশনটি প্রায়শই বলা হয় না) অভিধান এবং ক্লাসগুলিও ঠিক আছে। তবে নেমেডটপলসগুলিও এই ক্ষেত্রে একটি দুর্দান্ত / সুন্দর সমাধান।
লুটজ প্রিচেল্ট

8
@ ওমো: এটি করবেন না। পাইথন namedtupleসংজ্ঞাগুলিকে আলাদা করার জন্য কোনও প্রচেষ্টা করে না (প্রতিটি কল একটি নতুন তৈরি করে), namedtupleক্লাস তৈরি করা সিপিইউ এবং মেমরি উভয় ক্ষেত্রে তুলনামূলকভাবে ব্যয়বহুল এবং সমস্ত শ্রেণীর সংজ্ঞা অন্তর্ভুক্তভাবে চক্রীয় রেফারেন্সগুলিতে জড়িত (সুতরাং সিপিথনে, আপনি একটি চক্রীয় জিসি রানের জন্য অপেক্ষা করছেন তাদের মুক্তি দেওয়ার জন্য)। এটি pickleশ্রেণীর পক্ষে এটিও অসম্ভব করে তোলে (এবং multiprocessingবেশিরভাগ ক্ষেত্রে উদাহরণগুলি ব্যবহার করা অসম্ভব )। আমার 6.6.৪ এক্স 64৪ এ শ্রেণীর প্রতিটি সৃষ্টি ~ 0.337 এমএস খরচ করে এবং 1 কেবি মেমরির অধীনে দখল করে, যেকোন ঘটনার সঞ্চয়কে হত্যা করে।
শ্যাডোর্যাঞ্জার

3
আমি লক্ষ করব, পাইথন ৩.7 নতুন namedtupleক্লাস তৈরির গতি উন্নত করেছে ; সিপিইউ ব্যয়গুলি প্রায় 4x এর একটি ফ্যাক্টর দ্বারা হ্রাস পায় , তবে এগুলি এখনও উদাহরণ তৈরি করার জন্য প্রায় 1000x বেশি এবং প্রতিটি শ্রেণীর জন্য মেমরির দাম বেশি থাকে ("1 কেবি এর নীচে" সম্পর্কে আমার শেষ মন্তব্যে আমি ভুল ছিলাম শ্রেণীর জন্য, _sourceনিজে থেকে সাধারণত 1.5 কেবি; _sourceএটি 3.7-এ সরানো হয়, সুতরাং এটি সম্ভবত প্রতি ক্লাসে কেবল 1 কেবি এর নীচে মূল দাবির নিকটবর্তী হয়)।
শ্যাডোর্যাঞ্জার

4
@ সার্জস্ট্রোব্যান্ড - এটি স্ট্যান্ডার্ড লাইব্রেরির অংশ, কেবল একটি বিল্টিন নয়। আপনার উদ্বিগ্ন হওয়ার দরকার নেই যে এটি পাইথন> = 2.6 সহ অন্য সিস্টেমে ইনস্টল না করা হতে পারে। অথবা আপনি কেবল কোডের অতিরিক্ত লাইনটিকে আপত্তি করছেন?
জাস্টিন

234

ছোট প্রকল্পগুলির জন্য আমি টিউপলসের সাথে কাজ করা সবচেয়ে সহজ বলে মনে করি। যখন এটি পরিচালনা করা খুব কঠিন হয়ে যায় (এবং এর আগে নয়) আমি জিনিসগুলিকে যৌক্তিক কাঠামোর মধ্যে গোষ্ঠীকরণ শুরু করি, তবে আমি মনে করি আপনার অভিধান এবং ReturnValueবস্তুগুলির প্রস্তাবিত ব্যবহার ভুল (বা খুব সরল)।

কী এর মাধ্যমে একটি অভিধান রিটার্নিং "y0", "y1", "y2", ইত্যাদি tuples বেশী কোনো সুবিধা অফার করে না। একটি রিটার্নিং ReturnValueproperties সহযোগে উদাহরণস্বরূপ .y0, .y1, .y2, ইত্যাদি tuples বেশী কোনো সুবিধা হয় অফার করে না। আপনি কোথাও পেতে চাইলে আপনাকে জিনিসগুলির নামকরণ শুরু করতে হবে এবং যে কোনও উপায়ে tuples ব্যবহার করে এটি করতে পারেন:

def get_image_data(filename):
    [snip]
    return size, (format, version, compression), (width,height)

size, type, dimensions = get_image_data(x)

আইএমএইচও, টিপলস ছাড়িয়ে একমাত্র ভাল কৌশল হ'ল যথাযথ পদ্ধতি এবং বৈশিষ্ট্য সহ আসল বস্তুগুলি ফিরিয়ে দেওয়া, যেমন আপনি কাছ থেকে re.match()এসেছেন open(file)


6
প্রশ্ন - সেখানে মধ্যে কোনো পার্থক্য নেই size, type, dimensions = getImageData(x)এবং (size, type, dimensions) = getImageData(x)? অর্থাত্, একটি টিপল্ড অ্যাসাইনমেন্টের বাম-হাতের মোড়কে কি কোনও পার্থক্য রয়েছে?
রেব কেবিন

11
@ রেব.কবিন কোনও পার্থক্য নেই। টিপল কমা দ্বারা চিহ্নিত করা হয়েছে এবং প্রথম বন্ধনীর ব্যবহার কেবল জিনিসগুলিকে একসাথে গ্রুপ করা to উদাহরণস্বরূপ (1)একটি int হয় (1,)বা 1,একটি tuple হয়।
ফিল

19
পুনরায় "কী y0, y1, y2 ইত্যাদির সাহায্যে অভিধানে ফিরে আসা টিউপসগুলির তুলনায় কোনও সুবিধা দেয় না": অভিধানের সুবিধা রয়েছে যে আপনি বিদ্যমান কোডটি না ভাঙিয়ে প্রত্যাশিত অভিধানে ক্ষেত্রগুলি যুক্ত করতে পারেন।
অস্ট্রোকাচ

পুনরায় "কী y0, y1, y2 ইত্যাদির সাহায্যে অভিধানে ফিরে আসা টিউপসগুলির তুলনায় কোনও সুবিধা দেয় না": আপনি অবস্থানের পরিবর্তে এর নামের ভিত্তিতে ডেটা অ্যাক্সেস করার কারণে এটি আরও পাঠযোগ্য এবং কম ত্রুটিযুক্ত pr
ডেনিস ডলফাস

204

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

def f():
    return True, False
x, y = f()
print(x)
print(y)

দেয়:

True
False

24
আপনি এখনও একটি সংগ্রহ ফিরিয়ে দিচ্ছেন। এটি একটি tuple হয়। এটিকে আরও স্পষ্ট করার জন্য আমি প্রথম বন্ধনকে পছন্দ করি। এই চেষ্টা করুন: type(f())আয় <class 'tuple'>
ইগোর

20
@ ইগোর: tupleদিকটি সুস্পষ্ট করার কোনও কারণ নেই ; এটি সত্যিকার অর্থে গুরুত্বপূর্ণ নয় যে আপনি একটি ফিরিয়ে দিচ্ছেন tuple, এটি একাধিক মান পিরিয়ড ফিরিয়ে দেওয়ার প্রতিমা। অদলবদল আইডিয়ম x, y = y, x, একাধিক সূচনা x, y = 0, 1ইত্যাদির সাহায্যে আপনি পেরেনগুলি বাদ দেন একই কারণে ; অবশ্যই এটি tupleহুডের নীচে তৈরি করে তবে এটি স্পষ্ট করার কোনও কারণ নেই কারণ এসগুলি tupleবিন্দু নয়। পাইথন টিউটোরিয়ালটি একাধিক অ্যাসাইনমেন্টটি এমনকি এটিতে স্পর্শ করার অনেক আগেই পরিচয় করিয়ে দেয়tuple
শ্যাডোর্যাঞ্জার

@ শ্যাডোরেঞ্জার এর ডান হাতের কমা দ্বারা পৃথক করা মানগুলির যে কোনও অনুক্রমকে =পাইথনের একটি চারপাশে চারপাশে বা প্রথম বন্ধনী ছাড়াই। সুতরাং এখানে আসলে কোন সুস্পষ্ট বা অন্তর্নিহিত আছে। a, b, c হ'ল একটি টিপল (ক, খ, সি)। আপনি যখন এই জাতীয় মানগুলি ফিরিয়ে দেন তখন "হুডের নীচে" টুপল তৈরির কোনও ব্যবস্থা নেই, কারণ এটি কেবল একটি সরল সরল tuple। ওপি ইতিমধ্যে টিপলসটির কথা উল্লেখ করেছে যাতে তিনি উল্লেখ করেছেন এবং এই উত্তরটি কী দেখায় তার মধ্যে আসলে কোনও পার্থক্য নেই।
কোনওটিই

2
এটি আক্ষরিক অর্থে প্রথম বিকল্পটিতে পরামর্শ দেওয়া হয়েছে
এন্ডোলিথ

1
দুই বার @endolith লোক একটা প্রশ্ন জিজ্ঞেস ( "আমি একাধিক মান কিভাবে ফিরে আসে?" এবং "আপনি কিভাবে আপনি একাধিক মান আসতে?") এই উত্তর দ্বারা উত্তর দেওয়া হয়। প্রশ্নের পাঠ্য মাঝে মাঝে পরিবর্তিত হয়েছে। এবং এটি একটি মতামত ভিত্তিক প্রশ্ন।
জোসেফ হ্যানসেন

74

আমি অভিধানের পক্ষে ভোট দিই

আমি দেখতে পেলাম যে আমি যদি এমন কোনও ফাংশন তৈরি করি যা 2-3 ভেরিয়েবলের বেশি কিছু দেয় তবে আমি এগুলি একটি অভিধানে গুটিয়ে দেব। অন্যথায় আমি কী ফিরে আসছি তার ক্রম এবং বিষয়বস্তু ভুলে যাওয়ার প্রবণতা রয়েছে।

এছাড়াও, একটি 'বিশেষ' কাঠামো প্রবর্তন করা আপনার কোড অনুসরণ করা আরও কঠিন করে তোলে। (অন্য কেউ কোডটি খুঁজে বের করতে হবে এটি কী তা জানতে)

আপনি যদি টাইপ সম্পর্কে উদ্বিগ্ন হন তবে বর্ণনামূলক অভিধান কী ব্যবহার করুন, উদাহরণস্বরূপ, 'এক্স-মান তালিকা'।

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

5
বহু বছর প্রোগ্রামিংয়ের পরে, আমি কখনই ডেটা এবং ফাংশনের কাঠামোর প্রয়োজনীয়তার দিকে ঝুঁকছি। প্রথমে ফাংশন, আপনি সর্বদা প্রয়োজনীয় হিসাবে রিফেক্টর করতে পারেন।
মনকুট

ফাংশনটিকে একাধিকবার কল না করে আমরা অভিধানের মধ্যে কীভাবে মান পাব? উদাহরণস্বরূপ, আমি যদি অন্য কোনও ফাংশনে y1 এবং y3 ব্যবহার করতে চাই?
ম্যাট

3
ফলাফলগুলি একটি পৃথক ভেরিয়েবলের জন্য বরাদ্দ করুন। result = g(x); other_function(result)
monkut

1
@ মোমকুট হ্যাঁ এই উপায়ে ফলাফলটি বিভিন্ন ফাংশনে পাস করার অনুমতি দেয়, যা ফলাফল থেকে বিভিন্ন দিকনির্দেশনা গ্রহণ করে, প্রতিবার ফলাফলের নির্দিষ্ট অংশগুলি নির্দিষ্টভাবে উল্লেখ না করে।
জ্ঞানদিফ

38

আর একটি বিকল্প জেনারেটর ব্যবহার করা হবে:

>>> def f(x):
        y0 = x + 1
        yield y0
        yield x * 3
        yield y0 ** 4


>>> a, b, c = f(5)
>>> a
6
>>> b
15
>>> c
1296

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


1
এটি সবচেয়ে পরিষ্কার সমাধান বলে মনে হচ্ছে এবং এর একটি পরিষ্কার বাক্য গঠন রয়েছে। এটার কি কোন ডাউনসাইড আছে? আপনি যদি সমস্ত রিটার্ন ব্যবহার না করেন, তবে কি 'অনুপস্থিত' ফলনগুলি আপনাকে আঘাত করার অপেক্ষায় আছে?
জিমিনিয়ন

24
এটি "পরিষ্কার" হতে পারে তবে এটিকে মোটেই স্বজ্ঞাত বলে মনে হচ্ছে না। যে আগে কখনও এই প্যাটার্নটির মুখোমুখি হয়নি সে কীভাবে জানবে যে স্বয়ংক্রিয় টুপল আনপ্যাকিং করা প্রত্যেকেই ট্রিগার করবে yield?
coredumperror

1
@ কোরডাম্পরর, জেনারেটর কেবল ... জেনারেটর। তার মাঝে কোন বহিরাগত পার্থক্য নেই def f(x): …; yield b; yield a; yield rবনাম (g for g in [b, a, r]), এবং উভয় নির্দ্ধিধায় রূপান্তর করবে তালিকা বা tuples, এবং যেমন ইচ্ছা সমর্থন tuple unpacking। টিউপল জেনারেটর ফর্ম একটি কার্যকরী পদ্ধতির অনুসরণ করে, যখন ফাংশন ফর্মটি অপরিহার্য এবং প্রবাহ নিয়ন্ত্রণ এবং পরিবর্তনশীল কার্যের অনুমতি দেয়।
sleblanc

30

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

আমি অভিধানগুলি তখনই ফেরত মান হিসাবে ব্যবহার করি যখন গোষ্ঠীভিত্তিক জিনিসগুলি সর্বদা একই থাকে না। Emailচ্ছিক ইমেল শিরোনামগুলি ভাবেন।

বাকী ক্ষেত্রে, যেখানে গোষ্ঠীভুক্ত বস্তুগুলির গোষ্ঠীর অভ্যন্তর অন্তর্নিহিত অর্থ বা নিজস্ব পদ্ধতি সহ একটি পূর্ণ-বর্ধিত বস্তুর প্রয়োজন হয়, আমি একটি শ্রেণি ব্যবহার করি।


29

আমি পছন্দ করি:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

দেখে মনে হচ্ছে অন্য সব কিছুই একই জিনিস করার জন্য কেবল অতিরিক্ত কোড।


22
টিপলগুলি আনপ্যাক করা সহজ: y0, y1, y2 = g () আপনাকে যে ডিকটি করতে হবে তা দিয়ে: ফলাফল = জি () y0, y1, y2 = ফলাফল.get ('y0'), ফলাফল.get ('y1') ), ফলাফল.get ('y2') যা কিছুটা কুৎসিত। প্রতিটি সমাধানের 'প্লাস' এবং এর 'বিয়োগগুলি' থাকে।
অলি

27
>>> def func():
...    return [1,2,3]
...
>>> a,b,c = func()
>>> a
1
>>> b
2
>>> c
3

@ এডওয়ার্ড না এটি হয় না, এটি একটি তালিকে একটি তালিকা দেয় না।
সাইমন হিবস

1
ডেস্ট্রাকচারিংটি আমার মতে তালিকাগুলি ফিরিয়ে আনার যুক্তি
সেমিওম্যান্ট

21

সাধারণত, "বিশেষায়িত কাঠামো" আসলে তার নিজস্ব পদ্ধতি সহ কোনও জিনিসের বুদ্ধিমান বর্তমান অবস্থা।

class Some3SpaceThing(object):
  def __init__(self,x):
    self.g(x)
  def g(self,x):
    self.y0 = x + 1
    self.y1 = x * 3
    self.y2 = y0 ** y3

r = Some3SpaceThing( x )
r.y0
r.y1
r.y2

আমি যেখানে সম্ভব সেখানে বেনামে কাঠামোর জন্য নামগুলি খুঁজতে চাই। অর্থপূর্ণ নামগুলি বিষয়গুলিকে আরও স্পষ্ট করে তোলে।


20

পাইথনের টিউপস, ডিক্টস এবং অবজেক্টস প্রোগ্রামারকে ছোট ডেটা স্ট্রাকচার ("জিনিস") এর জন্য আনুষ্ঠানিকতা এবং সুবিধার মধ্যে একটি সহজ বাণিজ্য অফার করে। আমার জন্য, কোনও জিনিসকে কীভাবে উপস্থাপন করা যায় তা চয়ন করে মূলত কীভাবে আমি কাঠামোটি ব্যবহার করব তা নির্ধারিত হয়। সি ++ তে, structকেবলমাত্র ডেটা আইটেমগুলির classজন্য এবং পদ্ধতিগুলির সাথে অবজেক্টগুলির জন্য ব্যবহার করার জন্য এটি একটি সাধারণ কনভেনশন , যদিও আপনি আইনত আইনগুলিকে একটিতে প্রয়োগ করতে পারেন struct; আমার অভ্যাসটি পাইথনের সাথে dictএবং তার tupleজায়গায় একই রকম struct

স্থানাঙ্ক সেটগুলির জন্য, আমি tupleবিন্দু classবা ক এর পরিবর্তে একটি ব্যবহার করব dict(এবং মনে রাখবেন যে আপনি tupleঅভিধান কী হিসাবে একটি ব্যবহার করতে পারেন , সুতরাং dictদুর্দান্ত স্পার্স বহুমাত্রিক অ্যারে তৈরি করুন)।

যদি আমি জিনিসের একটি তালিকাতে পুনরাবৃত্তি করতে যাচ্ছি, আমি tupleপুনরাবৃত্তির উপর আনপ্যাকিং পছন্দ করি :

for score,id,name in scoreAllTheThings():
    if score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(score,id,name)

... অবজেক্ট ভার্সনটি পড়ার জন্য আরও বিশৃঙ্খল:

for entry in scoreAllTheThings():
    if entry.score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry.score,entry.id,entry.name)

... একা থাকতে দাও dict

for entry in scoreAllTheThings():
    if entry['score'] > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry['score'],entry['id'],entry['name'])

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

অবশেষে, যদি আমি পাইথন নন উপাদানগুলির সাথে ডেটা আদান প্রদান করতে যাচ্ছি, আমি বেশিরভাগ ক্ষেত্রে এগুলিতে রাখব dictকারণ এটি JSON সিরিয়ালাইজেশনের পক্ষে সবচেয়ে উপযুক্ত।


19

একটি নামী কন্টেইনার শ্রেণীর এস.লোটের পরামর্শে +1।

পাইথন ২.6 এবং তার বেশি বয়সের জন্য , একটি নামযুক্ত টিপল সহজেই এই ধারক শ্রেণীর তৈরি করার একটি দরকারী উপায় সরবরাহ করে এবং ফলাফলগুলি "হালকা ওজনের এবং নিয়মিত টিউপসগুলির চেয়ে বেশি মেমরির প্রয়োজন হয় না"।


4

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

যাইহোক, যদি আমি নিজেকে ক্রমাগত একই ভেরিয়েবলগুলির সেটটি ফেরত পেতে দেখতে পাই তবে সম্ভবত এটির মধ্যে একটি নতুন শ্রেণি জড়িত যা আমি ফ্যাক্টর করব।


4

আমি কোনও ফাংশন থেকে মানগুলি পাস এবং ফিরিয়ে দেওয়ার জন্য একটি ডিক ব্যবহার করব:

পরিবর্তনশীল ফর্ম ব্যবহার করুন যেমন সংজ্ঞায়িত ফর্ম

form = {
    'level': 0,
    'points': 0,
    'game': {
        'name': ''
    }
}


def test(form):
    form['game']['name'] = 'My game!'
    form['level'] = 2

    return form

>>> print(test(form))
{u'game': {u'name': u'My game!'}, u'points': 0, u'level': 2}

এটি আমার এবং প্রক্রিয়াকরণ ইউনিটের জন্য সবচেয়ে কার্যকর উপায়।

আপনাকে কেবলমাত্র একটি পয়েন্টারটি পাস করতে হবে এবং কেবল একটি পয়েন্টার বের করতে হবে।

আপনি যখনই আপনার কোডটিতে কোনও পরিবর্তন আনেন তখন আপনাকে ফাংশন '(তাদের হাজার হাজার) আর্গুমেন্ট পরিবর্তন করতে হবে না।


ডিক্টগুলি পরিবর্তনযোগ্য। যদি আপনি কোনও ফাংশনে ডিকটি পাস করেন এবং সেই ফাংশন ডিকটি সম্পাদনা করে, পরিবর্তনগুলি সেই ফাংশনের সুযোগের বাইরে প্রতিফলিত হবে। শেষে ডিকটি ফাংশনটি প্রদানের ফলে বোঝা যায় যে ফাংশনটির কোনও পার্শ্ব-প্রতিক্রিয়া নেই, সুতরাং মানটি ফেরত দেওয়া উচিত নয়, এটি স্পষ্ট করে যে testমানটি সরাসরি সংশোধন করবে। এর সাথে তুলনা করুন dict.update, যা কোনও মান দেয় না।
sleblanc

@ স্লেব্ল্যাঞ্চ "ফাংশন শেষে ডুকটি ফিরিয়ে দেওয়ার ফলে বোঝা যায় যে ফাংশনটির কোনও পার্শ্ব-প্রতিক্রিয়া নেই"। এটি বোঝায় না কারণ আপনি যেমন বলেছেন, ডিকটি পরিবর্তনযোগ্য। তবে, ফিরে আসার formফলে পাঠ্যতা বা পারফরম্যান্সের ক্ষতি হয় না। আপনার পুনরায় ফর্ম্যাট করার প্রয়োজন হতে পারে form, এটিকে [ফর্ম] formফিরিয়ে দেওয়া নিশ্চিত করে যে শেষটি ফিরে এসেছে কারণ আপনি কোথাও ফর্ম পরিবর্তনের উপর নজর রাখবেন না।
এলিস বাইবেরি

3

"সেরা" একটি আংশিক বিষয়গত সিদ্ধান্ত। সাধারণ ক্ষেত্রে ছোট রিটার্ন সেটের জন্য টিপলস ব্যবহার করুন যেখানে এক পরিবর্তনযোগ্য গ্রহণযোগ্য। কোনও পরিবর্তন যখন তালিকার পক্ষে সর্বদা পছন্দনীয় হয় যখন পরিবর্তনের প্রয়োজন হয় না।

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

যেমনটি বিজ্ঞ ব্যক্তি বলেছেন:

অকালীন অপ্টিমাইজেশান হ'ল প্রোগ্রামিংয়ে সমস্ত মন্দ (বা এর বেশিরভাগ অংশে) এর মূলে।


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