পাইথন ফাংশনগুলি আপনি যে প্যারামিটারগুলিতে প্রবেশ করেন সেগুলি কীভাবে পরিচালনা করে?


305

আমার ভুল না হলে পাইথনে একটি ফাংশন তৈরি করা এইভাবে কাজ করে:

def my_func(param1, param2):
    # stuff

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


15
আমি মনে করি এই প্রশ্ন গ্রহণযোগ্য উত্তর আরো ইন-লাইন সাথে থাকতে আপডেট করা উচিত বর্তমান যে পাইথন অফার ক্ষমতা। আমি মনে করি এই উত্তরটি কাজ করে।
কোড_ড্রেড 21

উত্তর:


172

পাইথন শক্তিশালী ভাবে টাইপ করা হয়, কারণ প্রত্যেক বস্তুর হয়েছে একটি টাইপ, প্রত্যেক বস্তুর জানে তার ধরন, এটা ঘটনাক্রমে বা ইচ্ছাকৃতভাবে একটি প্রকারের একটি বস্তু ব্যবহার করতে "যেন" এটি একটি একটি অবজেক্ট ছিল অসম্ভব বিভিন্ন প্রকার, এবং বস্তুর উপর সব প্রাথমিক অপারেশন হয় তার প্রকারের জন্য প্রেরণ করা।

নামগুলির সাথে এর কোনও যোগসূত্র নেই । পাইথনের একটি নাম "ধরণের" থাকে না: যদি এবং যখন কোনও নাম সংজ্ঞায়িত করা হয় তবে নামটি কোনও বস্তুকে বোঝায় এবং অবজেক্টটির একটি প্রকার থাকে (তবে বাস্তবে এটি নামের উপর একটি প্রকার জোর করে না : একটি নাম একটি নাম)।

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


71
সুতরাং এটি শক্তিশালী টাইপিং তেমন শক্তিশালী নয় বলে মনে হয়, এই নির্দিষ্ট ক্ষেত্রে এটি স্ট্যাটিক টাইপিংয়ের চেয়ে দুর্বল IM আইএমএইচও, নাম / ভেরিয়েবল / রেফারেন্সে টাইপ করার টাইপ সীমাবদ্ধতা আসলে বেশ গুরুত্বপূর্ণ, এইভাবে আমি দৃ bold়তার সাথে দাবি করি অজগরটি স্ট্যাটিক টাইপিংয়ের মতো ভাল নয় is এই দিক। আমি ভুল হলে আমাকে সংশোধন করুন।
লিয়াং

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

6
তবে এটি কোনও প্রশ্নের উত্তর দেয় না: "তবে পাইথন কীভাবে জানতে পারে যে ফাংশনটির ব্যবহারকারী যথাযথ প্রক্রিয়ায় চলেছে? প্রোগ্রামটি যদি ভুল টাইপ করে তবেই মারা যাবে, ধরে নিবেন ফাংশনটি আসলে প্যারামিটারটি ব্যবহার করে? আপনি কি টাইপ নির্দিষ্ট করতে হবে? " বা ..
কিপিসিআরসিআর

4
@ qPCR4vir, যে কোনও অবজেক্টকে আর্গুমেন্ট হিসাবে পাস করা যেতে পারে। ত্রুটি (একটি ব্যতিক্রম, প্রোগ্রামটি ধরার জন্য কোডিং করা থাকলে "মরা" না, দেখুন try/ except) ঘটবে কখন এবং যদি কোনও অপারেশন চেষ্টা করা হয় যাতে অবজেক্টটি সমর্থন করে না। পাইথন ৩.৩-এ আপনি এখন যুক্তিগুলির optionচ্ছিকভাবে "ধরণের নির্দিষ্টকরণ" করতে পারেন, তবে কোনও ত্রুটি ঘটবে না, প্রতি সেপ্টেম্বর, যদি অনুমানের লঙ্ঘন হয়; টাইপিং নোটেশনটি কেবল পৃথক সরঞ্জামগুলিকে সহায়তা করে যা বিশ্লেষণ ইত্যাদি সম্পাদন করে, এটি পাইথনের আচরণের কোনও পরিবর্তন করে না।
অ্যালেক্স মার্টেলি

2
@AlexMartelli। ধন্যবাদ! আমার জন্য এটি সঠিক উত্তর: "ত্রুটি (একটি ব্যতিক্রম, প্রোগ্রামটি ধরার জন্য কোডিং করা থাকলে" মারা যাবে না ", চেষ্টা করুন / বাদে দেখুন) .."
কিপিসিআরসিআরভিউয়ার

753

অন্যান্য উত্তরগুলি হাঁসের টাইপিং এবং tzot এর সহজ উত্তরটি ব্যাখ্যা করার জন্য একটি ভাল কাজ করেছে :

পাইথনের ভেরিয়েবলগুলি নেই, অন্যান্য ভাষার মতো যেখানে ভেরিয়েবলের একটি ধরণ এবং মান থাকে; এটিতে বস্তুর প্রতি ইঙ্গিত করার নাম রয়েছে যা তাদের ধরণটি জানে।

তবে , একটি আকর্ষণীয় বিষয় ২০১০ সাল থেকে পরিবর্তিত হয়েছে (যখন প্রশ্নটি প্রথম জিজ্ঞাসা করা হয়েছিল), পিইপি 3107 (পাইথন 3 এ বাস্তবায়িত) এর বাস্তবায়ন। আপনি এখন কোনও প্যারামিটারের ধরন এবং ফাংশনটির রিটার্ন টাইপের ধরণটি নির্দিষ্ট করে বলতে পারেন:

def pick(l: list, index: int) -> int:
    return l[index]

আমরা দেখতে পাচ্ছি যে pickএটি 2 পরামিতি, একটি তালিকা lএবং একটি পূর্ণসংখ্যা লাগে index। এটিও একটি পূর্ণসংখ্যা ফেরত দেওয়া উচিত।

সুতরাং এখানে এটি বোঝানো হয়েছে যে lপূর্ণসংখ্যার একটি তালিকা যা আমরা অনেক প্রচেষ্টা ছাড়াই দেখতে পাই, তবে আরও জটিল ক্রিয়াকলাপগুলির জন্য তালিকাটি কী থাকা উচিত তা কিছুটা বিভ্রান্তিকর হতে পারে। আমরা ডিফল্ট মান index0 হওয়াও চাই this এটি সমাধান করার জন্য আপনি পরিবর্তে এইভাবে লিখতে পছন্দ করতে pickপারেন:

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

নোট করুন যে আমরা এখন স্ট্রিংয়ের ধরণ হিসাবে lরেখেছি, যা সিনথেটিকভাবে অনুমোদিত, তবে প্রোগ্রামিকভাবে পার্স করা ভাল নয় (যা আমরা পরে ফিরে আসব)।

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

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

আপনার কেন কমই করা উচিত এবং এর পরিবর্তে আপনার কী করা উচিত সে সম্পর্কে আরও পরবর্তী বিভাগে এবং মন্তব্যে আলোচনা করা হয়েছে।

পিইপি 3107 কেবল কোড পঠনযোগ্যতার উন্নতি করে না তবে এখানে বেশ কয়েকটি উপযুক্ত ব্যবহারের কেস রয়েছে যা আপনি এখানে পড়তে পারেন ।


টাইপ টীকাগুলি পিইপি 484 প্রবর্তনের সাথে পাইথন 3.5 তে আরও বেশি মনোযোগ পেল যা টাইপ ইঙ্গিতগুলির জন্য একটি স্ট্যান্ডার্ড মডিউল প্রবর্তন করে।

এই ধরণের ইঙ্গিতগুলি টাইপ চেকার মাইপি ( গিটহাব ) থেকে এসেছে , যা এখন পিইপি 484 অনুগত।

টাইপিং মডিউলটি সহ টাইপ ইঙ্গিতগুলির একটি দুর্দান্ত বিস্তৃত সংগ্রহ সহ আসে:

  • List, Tuple, Set, Map- জন্য list, tuple, setএবং mapযথাক্রমে।
  • Iterable - জেনারেটর জন্য দরকারী।
  • Any - যখন এটি কিছু হতে পারে।
  • Union- যখন এটি কোনও নির্দিষ্ট ধরণের সেটগুলির বিপরীতে কিছু হতে পারে Any
  • Optional- যখন এটি কিছুই নাও হতে পারে। শর্টহ্যান্ডের জন্য Union[T, None]
  • TypeVar - জেনেরিকের সাথে ব্যবহৃত
  • Callable - মূলত ফাংশনগুলির জন্য ব্যবহৃত হয়, তবে অন্যান্য কলযোগ্যগুলির জন্য এটি ব্যবহার করা যেতে পারে।

এগুলি সর্বাধিক সাধারণ ধরণের ইঙ্গিত। টাইপিং মডিউলটির জন্য ডকুমেন্টেশনে একটি সম্পূর্ণ তালিকা পাওয়া যাবে ।

টাইপিং মডিউলটিতে প্রবর্তিত টীকাগুলি ব্যবহার করে পুরানো উদাহরণ এখানে দেওয়া হয়েছে:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

একটি শক্তিশালী বৈশিষ্ট্য হ'ল Callableযা আপনাকে এ্যানোটেট পদ্ধতিগুলি টাইপ করতে দেয় যা একটি যুক্তি হিসাবে কোনও ফাংশন নেয়। উদাহরণ স্বরূপ:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

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


পূর্বে যখন এক সঙ্গে উদাহরণস্বরূপ পাইথন কোড নথিভুক্ত স্পিংক্স উপরে কার্যকারিতা কিছু ভালো ফরম্যাট docstrings লেখার দ্বারা প্রাপ্ত করা যেতে পারে:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

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

আমার ব্যক্তিগত মতে এটি পাইথনের সর্বকালের অন্যতম সেরা বৈশিষ্ট্য। লোকেরা এর শক্তিকে ব্যবহার করা শুরু করার জন্য আমি অপেক্ষা করতে পারি না। দীর্ঘ উত্তরের জন্য দুঃখিত, তবে আমি উত্তেজিত হয়ে উঠলে এটি ঘটে।


পাইথন কোডের উদাহরণ যা ভারীভাবে টাইপ হিন্টিং ব্যবহার করে তা এখানে পাওয়া যাবে


2
@ ক্রিকফুসুসা: আমি সন্দেহ করি আপনি পাইথন 3 চালাচ্ছেন না যেখানে বৈশিষ্ট্যটি যুক্ত করা হয়েছিল।
ERB

26
একটি মিনিট অপেক্ষা করুন! যদি প্যারামিটার এবং রিটার্নের ধরণ সংজ্ঞায়িত না করা TypeErrorহয় তবে তা pick(l: list, index: int) -> intএক-লাইনের মতো সংজ্ঞায়িত করার মতো কী হবে? বা আমি এটা ভুল পেয়েছি, আমি জানি না।
এরদিন ইরে

24
@ ইরে এরদিন: এটি একটি সাধারণ ভুল বোঝাবুঝি এবং মোটেই খারাপ প্রশ্ন নয়। এটি ডকুমেন্টেশনের উদ্দেশ্যে ব্যবহার করা যেতে পারে, আইডিইগুলিকে আরও ভাল স্বয়ংক্রিয়তা সম্পন্ন করতে সহায়তা করে এবং স্ট্যাটিক বিশ্লেষণ ব্যবহার করে রানটাইমের আগে ত্রুটিগুলি খুঁজে পেতে (যেমন আমি উত্তরটিতে উল্লেখ করেছি যে মাইপি)। আশা আছে যে রানটাইম তথ্যের সুযোগ নিতে পারে এবং প্রকৃতপক্ষে প্রোগ্রামগুলিকে গতি দিতে পারে তবে সম্ভবত এটি বাস্তবায়িত হতে খুব বেশি সময় লাগবে take আপনি পারে একটি প্রসাধক যে (তথ্য সংরক্ষণ করা হয় আপনার জন্য TypeErrors ছোঁড়ার তৈরি করতে সক্ষম হবেন __annotations__ফাংশন বস্তুর বৈশিষ্ট্য)।
এরব

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

2
@Tony: আপনি যখন আরো দুটি ফিরে বা আপনি আসলে একটি tuple আসতে বস্তু, যাতে আপনি Tuple টাইপ টীকা ব্যবহার করা উচিত, অর্থাত্def f(a) -> Tuple[int, int]:
ERB

14

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

সুতরাং এই সহজ ফাংশন:

def no_op(param1, param2):
    pass

... যাই হোক না কেন দুটি অর্গ পাস করা যায় তা ব্যর্থ হবে না।

তবে, এই ফাংশন:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

... রানটাইমে ব্যর্থ হবে যদি param1এবং param2উভয়টির নামকরণযোগ্য বৈশিষ্ট্য না থাকে quack


+1: বৈশিষ্ট্য এবং পদ্ধতিগুলি স্থিরভাবে নির্ধারিত হয় না। এই "সঠিক টাইপ" বা "ভুল টাইপ" কীভাবে টাইপটি ফাংশনে সঠিকভাবে কাজ করে বা না তার দ্বারা প্রতিষ্ঠিত হবে তার ধারণা।
এসলট

11

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

অন্যান্য ভাষায়, যখন আপনি বলেন:

a = 1

তারপরে একটি (সাধারণত পূর্ণসংখ্যার) পরিবর্তনশীল এর বিষয়বস্তুগুলিকে মান 1 এ পরিবর্তন করে।

পাইথনে,

a = 1

মানে হলো "নাম ব্যবহার একটি বস্তুর উল্লেখ করতে 1 "। একটি ইন্টারেক্টিভ পাইথন সেশনে আপনি নিম্নলিখিতগুলি করতে পারেন:

>>> type(1)
<type 'int'>

ফাংশনটি typeঅবজেক্টের সাথে ডাকা হয় 1; যেহেতু প্রতিটি বস্তু তার প্রকারটি জানে, তাই typeবলা ধরণটি খুঁজে বের করতে এবং এটি ফিরে পাওয়া সহজ।

তেমনি, আপনি যখনই কোনও ফাংশন সংজ্ঞায়িত করেন

def funcname(param1, param2):

ফাংশন দুটি বস্তু গ্রহণ করে param1এবং তাদের নাম এবং param2তাদের প্রকার নির্বিশেষে গ্রহণ করে। আপনি যদি নিশ্চিত করতে চান যে প্রাপ্ত জিনিসগুলি কোনও নির্দিষ্ট ধরণের, আপনার ফাংশনটি কোড করুন যেন সেগুলি প্রয়োজনীয় ধরণের (গুলি) এবং সেগুলি ব্যতীত ছড়িয়ে দেওয়া ব্যতিক্রমগুলি ধরেন they নিক্ষিপ্ত ব্যতিক্রমগুলি হ'ল সাধারণত TypeError(আপনি একটি অবৈধ ক্রিয়াকলাপটি ব্যবহার করেছেন) এবং AttributeError(আপনি একটি অযোগ্য সদস্যকে অ্যাক্সেস করার চেষ্টা করেছিলেন (পদ্ধতিগুলিও সদস্য))।


8

পাইথন স্ট্যাটিক বা কম্পাইল-টাইম টাইপ চেকিংয়ের অর্থে দৃ strongly়ভাবে টাইপ করা হয় না।

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


21
পাইথন হয় শক্তিশালী ভাবে টাইপ। এটি গতিশীলভাবেও টাইপ করা হয়।
ড্যানিয়েল নিউবি

1
তবে এটি কোনও প্রশ্নের উত্তর দেয় না: "তবে পাইথন কীভাবে জানতে পারে যে ফাংশনটির ব্যবহারকারী যথাযথ প্রক্রিয়ায় চলেছে? প্রোগ্রামটি যদি ভুল টাইপ করে তবেই মারা যাবে, ধরে নিবেন ফাংশনটি আসলে প্যারামিটারটি ব্যবহার করে? আপনি কি টাইপ নির্দিষ্ট করতে হবে? " বা ..
qPCR4vir

6

অ্যালেক্স মার্টেলি যেমন ব্যাখ্যা করেছেন ,

পাইথোনিক, পছন্দসই সমাধানটি প্রায় অলসভাবে "হাঁসের টাইপিং": যুক্তিটি ব্যবহার করার চেষ্টা করুন যেন এটি একটি নির্দিষ্ট কাঙ্ক্ষিত ধরণের ছিল, চেষ্টা করে দেখুন / বিবৃতি ব্যতীত যে সমস্ত ব্যতিক্রম ঘটতে পারে যেগুলি যুক্তিটি বাস্তবে না থাকলে উপস্থিত হতে পারে except এই ধরণের (বা অন্য কোনও ধরণের এটি সুন্দরভাবে হাঁস-নকল করে ;-), এবং অন্যের ধারাটিতে অন্য কিছু চেষ্টা করুন ("যদি" এটি অন্য কোনও ধরণের ছিল "তর্কটি ব্যবহার করে)।

সহায়ক তথ্যের জন্য তার বাকি পোস্টটি পড়ুন।


5

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


11
পাইথনের ভেরিয়েবলগুলি নেই, অন্যান্য ভাষার মতো যেখানে ভেরিয়েবলের একটি ধরণ এবং মান থাকে; এটিতে বস্তুর প্রতি ইঙ্গিত করার নাম রয়েছে , যা তাদের প্রকারগুলি জানে।
tzot

2

আপনি কখনও প্রকারটি নির্দিষ্ট করেন না; পাইথনের হাঁসের টাইপিংয়ের ধারণা রয়েছে ; মূলত কোডগুলি যা পরামিতিগুলি প্রসেস করে সেগুলি তাদের সম্পর্কে কিছু নির্দিষ্ট ধারণা তৈরি করবে - সম্ভবত নির্দিষ্ট পদ্ধতিগুলিকে কল করে যে কোনও পরামিতি বাস্তবায়িত হবে বলে আশা করা হচ্ছে। যদি প্যারামিটারটি ভুল ধরণের হয় তবে একটি ব্যতিক্রম ছুঁড়ে দেওয়া হবে।

আপনি যথাযথ ধরণের অবজেক্টের কাছাকাছি চলেছেন তা নিশ্চিত করার পক্ষে আপনার কোডটি নির্ভর করে - সময়ের পূর্বে এটি প্রয়োগ করার জন্য কোনও সংকলক নেই।


2

এই পৃষ্ঠায় উল্লেখযোগ্য হাঁস-টাইপিং থেকে একটি কুখ্যাত ব্যতিক্রম রয়েছে।

যখন strফাংশন __str__ক্লাস পদ্ধতিতে কল করে তখন এটি সূক্ষ্মভাবে তার প্রকারগুলি পরীক্ষা করে:

>>> class A(object):
...     def __str__(self):
...         return 'a','b'
...
>>> a = A()
>>> print a.__str__()
('a', 'b')
>>> print str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __str__ returned non-string (type tuple)

যেন কোনও প্রোগ্রাম কোনও অপ্রত্যাশিত ধরণের মুখোমুখি হয় তবে কোন ব্যতিক্রম উত্থাপন করা উচিত তা গিডো আমাদের ইঙ্গিত দেয়।


1

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

উদাহরণ: এড করা fooযেতে পারে এমন সমস্ত কিছু যুক্ত করা হবে __add__;) এর ধরণের সম্পর্কে খুব বেশি চিন্তা না করে। সুতরাং এর অর্থ, ব্যর্থতা এড়াতে আপনার কেবলমাত্র সেইগুলি সরবরাহ করা উচিত যা সংযোজনকে সমর্থন করে।

def foo(a,b):
    return a + b

class Bar(object):
    pass

class Zoo(object):
    def __add__(self, other):
        return 'zoom'

if __name__=='__main__':
    print foo(1, 2)
    print foo('james', 'bond')
    print foo(Zoo(), Zoo())
    print foo(Bar(), Bar()) # Should fail

1

আমি অন্যান্য উত্তরে এটি উল্লিখিত দেখিনি, তাই আমি এটি পাত্রটিতে যুক্ত করব।

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

এটি করার অন্যতম প্রধান সরঞ্জাম হ'ল isinstance () ফাংশন।

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

def process(data):
    if not isinstance(data, bytes) and not isinstance(data, bytearray):
        raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data))
    # Do more stuff

পাইথন বস্তুগুলি খননের জন্য সমস্ত ধরণের সরঞ্জাম সরবরাহ করে। আপনি যদি সাহসী হন তবে আপনি ফ্লাইতে নিজের স্বেচ্ছাসেবীর ক্লাসগুলির নিজস্ব জিনিস তৈরি করতে আমদানিও করতে পারেন। আমি JSON ডেটা থেকে অবজেক্ট পুনরায় তৈরি করতে এটি করেছি। এই জাতীয় জিনিস সি ++ এর মতো স্থির ভাষায় দুঃস্বপ্ন হবে।


1

টাইপিং মডিউলটি কার্যকরভাবে ব্যবহার করতে (পাইথন 3.5 তে নতুন) সমস্ত ( *) অন্তর্ভুক্ত করে ।

from typing import *

এবং আপনি ব্যবহার করতে প্রস্তুত হবে:

List, Tuple, Set, Map - for list, tuple, set and map respectively.
Iterable - useful for generators.
Any - when it could be anything.
Union - when it could be anything within a specified set of types, as opposed to Any.
Optional - when it might be None. Shorthand for Union[T, None].
TypeVar - used with generics.
Callable - used primarily for functions, but could be used for other callables.

তবে, এখনও তোমার মত টাইপ নামের ব্যবহার করতে পারেন int, list, dict, ...


1

যদি কেউ পরিবর্তনশীল প্রকারগুলি নির্দিষ্ট করতে চান তবে আমি একটি মোড়ক কার্যকর করেছি।

import functools

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for i in range(len(args)):
            v = args[i]
            v_name = list(func.__annotations__.keys())[i]
            v_type = list(func.__annotations__.values())[i]
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        v = result
        v_name = 'return'
        v_type = func.__annotations__['return']
        error_msg = 'Variable `' + str(v_name) + '` should be type ('
        error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
        if not isinstance(v, v_type):
                raise TypeError(error_msg)
        return result

    return check

এটি হিসাবে ব্যবহার করুন:

@type_check
def test(name : str) -> float:
    return 3.0

@type_check
def test2(name : str) -> str:
    return 3.0

>> test('asd')
>> 3.0

>> test(42)
>> TypeError: Variable `name` should be type (<class 'str'>) but instead is type (<class 'int'>)

>> test2('asd')
>> TypeError: Variable `return` should be type (<class 'str'>) but instead is type (<class 'float'>)

সম্পাদনা

আর্গুমেন্টের (বা ফেরতের) প্রকারের কোনওটি ঘোষণা না করা থাকলে উপরের কোডটি কার্যকর হয় না। অন্যদিকে, নিম্নলিখিত সম্পাদনাটি সাহায্য করতে পারে, এটি কেবল কাওয়ার্গের জন্য কাজ করে এবং আরোগুলি পরীক্ষা করে না।

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for name, value in kwargs.items():
            v = value
            v_name = name
            if name not in func.__annotations__:
                continue

            v_type = func.__annotations__[name]

            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ') '
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        if 'return' in func.__annotations__:
            v = result
            v_name = 'return'
            v_type = func.__annotations__['return']
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                    raise TypeError(error_msg)
        return result

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