খালি তালিকা রয়েছে এমন ডিফল্ট পরামিতিগুলি এড়াতে পাইথোনিক উপায় কী?


117

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

উদাহরণস্বরূপ, আমার একটি ফাংশন রয়েছে:

def my_func(working_list = []):
    working_list.append("a")
    print(working_list)

এটির জন্য প্রথমবার বলা হয় ডিফল্ট কাজ করবে তবে তার পরে কলগুলি বিদ্যমান তালিকাকে আপডেট করবে (প্রতিটি কলের সাথে একটি "একটি") এবং আপডেট সংস্করণটি মুদ্রণ করবে।

সুতরাং, আমি যে আচরণটি করতে চাই তা পেতে প্রতিটি অজগর উপায় (প্রতিটি কলের একটি নতুন তালিকা)?


17
যদি কেউ আগ্রহী কেন এটি হতে আগ্রহী, effbot.org/zone/default-values.htm দেখুন
রায়ান

একই আচরণটি সেটগুলির ক্ষেত্রে ঘটে, যদিও এটির জন্য বাগ হিসাবে দেখানোর জন্য আপনার আরও কিছু জটিল উদাহরণ প্রয়োজন।
abeboparebop

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

উত্তর:


150
def my_func(working_list=None):
    if working_list is None: 
        working_list = []

    working_list.append("a")
    print(working_list)

দস্তাবেজগুলি বলছে যে আপনাকে Noneডিফল্ট হিসাবে ব্যবহার করা উচিত এবং এটির ফাংশনটির শৃঙ্খলে স্পষ্টভাবে পরীক্ষা করা উচিত


1
এটি কি বলা ভাল: যদি ওয়ার্কিং_লিস্ট == কোনওটি নয়: বা যদি ওয়ার্কিং_লিস্ট: ??
জন মুলদার 11

2
অজগরটিতে এটি করা সবচেয়ে পছন্দসই উপায়, এটি কুশ্রী হওয়ার পরেও আমার পছন্দ না হলেও। আমি বলব সেরা অনুশীলন হবে "যদি ওয়ার্কিং লিস্ট কোনও না হয়"।
ই-সন্তুষ্ট

21
এই উদাহরণের পছন্দসই উপায়টি হ'ল: ওয়ার্কিং_লিস্ট কোনওটি নয়। কলকারী কাস্টম সংযোজন সহ খালি তালিকার মতো বস্তুটি ব্যবহার করতে পারে।
tzot

5
মোহিত র্যাঙ্কা: সাবধান থাকুন যে তার কাজ দৈর্ঘ্য 0 হলে ওয়ার্কিং_লিস্টটি সঠিক নয় This এটি একটি অসামঞ্জস্যপূর্ণ আচরণের দিকে পরিচালিত করে: যদি ফাংশনগুলির মধ্যে কোনও উপাদানগুলির সাথে একটি তালিকা পাওয়া যায়, তবে তার ফোনকারী তার তালিকা আপডেট করে, এবং যদি তালিকাটি খালি থাকে, তবে স্পর্শ করা হবে না।
ভিনসেন্ট

1
@ পেট্রিকটি সঠিক সরঞ্জামটি কেসের উপর নির্ভর করে - একটি ভেরাগস ফাংশন একটি ( alচ্ছিক ) তালিকার যুক্তিটি গ্রহণের তুলনায় খুব আলাদা। আপনি যে পরিস্থিতিগুলির মধ্যে তাদের চয়ন করতে চান সেগুলি আপনার ভাবনার চেয়ে কম আসে। আরগের গণনা পরিবর্তিত হলে ভারার্গস দুর্দান্ত হয় তবে কোডটি লেখার সময় স্থির হয়। আপনার উদাহরণ পছন্দ করুন। এটি যদি রানটাইম-ভেরিয়েবল হয় বা আপনি f()একটি তালিকায় কল করতে চান তবে আপনাকে কল করতে হবে f(*l)যা স্থূল। সবচেয়ে খারাপ, বাস্তবায়ন mate(['larch', 'finch', 'robin'], ['bumble', 'honey', 'queen'])SUCK ডাব্লু / ভারার্গস হবে। এটা যদি আরও ভাল হয় def mate(birds=[], bees=[]):
এফআরডি

26

বিদ্যমান উত্তরগুলি ইতিমধ্যে জিজ্ঞাসা করা হিসাবে সরাসরি সমাধান সরবরাহ করেছে। তবে, যেহেতু এটি নতুন পাইথন প্রোগ্রামারদের পক্ষে একটি খুব সাধারণ সমস্যা, তাই পাইথনটি কেন এইভাবে আচরণ করে তা ব্যাখ্যা করার মতো, এটি " হিথিকার্স গাইড টু পাইথন " -র সংক্ষিপ্তসারিতভাবে " মিউটেবল ডিফল্ট আর্গুমেন্টস " হিসাবে সংক্ষেপিত হয়েছে : http: // ডকস .python-guide.org / bn / সর্বশেষ / লেখা / gotchas /

উদ্ধৃতি: " পাইথনের ডিফল্ট আর্গুমেন্টগুলি একবার ফাংশনটি সংজ্ঞায়িত হয়ে গেলে মূল্যায়ন করা হয় না, প্রতিবার ফাংশনটি ডাকা হয় না (যেমন এটি বলা হয়, রুবি) এটির অর্থ এই যে আপনি যদি একটি পরিবর্তনীয় ডিফল্ট যুক্তি ব্যবহার করেন এবং এটি পরিবর্তন করেন তবে আপনি পাবেন এবং ভবিষ্যতে সমস্ত কলগুলির জন্য সেই বস্তুকেও ফাংশনে পরিবর্তিত করে "

এটি প্রয়োগের জন্য নমুনা কোড:

def foo(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

13

এই ক্ষেত্রে এটি গুরুত্বপূর্ণ তা নয়, তবে আপনি কোনওটির পরীক্ষার জন্য অবজেক্ট পরিচয় ব্যবহার করতে পারেন:

if working_list is None: working_list = []

আপনি কীভাবে বুলিয়ান অপারেটরটি ব্যবহার করতে পারেন বা পাইথনে সংজ্ঞায়িত হয়েছেন তাও আপনি নিতে পারেন:

working_list = working_list or []

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


10

যদি ফাংশনটির উদ্দেশ্যটি পাশ করা প্যারামিটারটি পরিবর্তন করতে হয় তবে working_listহেনরিআরের উত্তর (= কিছুই নয়, ভিতরে কারও জন্য পরীক্ষা করে দেখুন) দেখুন।

তবে যদি আপনি যুক্তিটি পরিবর্তন করতে চান না, কেবল এটি একটি তালিকার সূচনা পয়েন্ট হিসাবে ব্যবহার করুন, আপনি কেবল এটি অনুলিপি করতে পারেন:

def myFunc(starting_list = []):
    starting_list = list(starting_list)
    starting_list.append("a")
    print starting_list

(বা এই সাধারণ ক্ষেত্রে কেবল print starting_list + ["a"]তবে আমি অনুমান করি যে এটি কেবল খেলনার উদাহরণ ছিল)

সাধারণভাবে, আপনার যুক্তিগুলিকে পরিবর্তন করা পাইথনের খারাপ স্টাইল। কেবলমাত্র ফাংশন যা কোনও বস্তুর রূপান্তর করতে সম্পূর্ণ প্রত্যাশিত তা হ'ল অবজেক্টের পদ্ধতিগুলি। Anচ্ছিক যুক্তিটি রূপান্তরিত করা এমনকি বিরল - এটি এমন কোনও পার্শ্ব প্রতিক্রিয়া যা কেবলমাত্র কিছু কলগুলিতে সত্যই সেরা ইন্টারফেসে ঘটে?

  • যদি আপনি এটি "আউটপুট আর্গুমেন্টস" এর সি অভ্যাস থেকে করেন তবে এটি সম্পূর্ণ অপ্রয়োজনীয় - আপনি সর্বদা টিপল হিসাবে একাধিক মান ফিরিয়ে দিতে পারেন।

  • আপনি যদি মধ্যবর্তী তালিকা তৈরি না করে দক্ষতার সাথে ফলাফলের দীর্ঘ তালিকা তৈরি করতে এই কাজটি করেন তবে এটি একটি জেনারেটর হিসাবে লেখা এবং result_list.extend(myFunc())আপনি যখন ফোন করছেন তখন ব্যবহার করার বিষয়টি বিবেচনা করুন। এইভাবে আপনার কলিং কনভেনশনগুলি খুব পরিষ্কার থাকে।

একটি প্যাটার্ন যেখানে প্রায়শই একটি alচ্ছিক আরগ পরিবর্তন করা হয় তা হ'ল পুনরাবৃত্ত ফাংশনগুলির একটি লুকানো "মেমো" আরগ:

def depth_first_walk_graph(graph, node, _visited=None):
    if _visited is None:
        _visited = set()  # create memo once in top-level call

    if node in _visited:
        return
    _visited.add(node)
    for neighbour in graph[node]:
        depth_first_walk_graph(graph, neighbour, _visited)

3

আমি অফ-টপিক হতে পারি, তবে মনে রাখবেন যে আপনি যদি কেবল একটি পরিবর্তনশীল সংখ্যক যুক্তিই পাস করতে চান তবে অজগর উপায়টি হল একটি টিউপল *argsবা অভিধান পাস করা **kargs। এগুলি alচ্ছিক এবং সিনট্যাক্সের চেয়ে ভাল myFunc([1, 2, 3])

আপনি যদি একটি টুপল পাস করতে চান:

def myFunc(arg1, *args):
  print args
  w = []
  w += args
  print w
>>>myFunc(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7)
[2, 3, 4, 5, 6, 7]

আপনি যদি একটি অভিধান পাস করতে চান:

def myFunc(arg1, **kargs):
   print kargs
>>>myFunc(1, option1=2, option2=3)
{'option2' : 2, 'option1' : 3}

0

ইতিমধ্যে ভাল এবং সঠিক উত্তর সরবরাহ করা হয়েছে। আমি যখন আপনি উদাহরণস্বরূপ ডিফল্ট খালি তালিকাগুলি সহ একটি বর্গ তৈরি করতে চান তখন আপনি যা করতে চান তা লিখতে আমি অন্য একটি বাক্য গঠন দিতে চেয়েছিলাম:

class Node(object):
    def __init__(self, _id, val, parents=None, children=None):
        self.id = _id
        self.val = val
        self.parents = parents if parents is not None else []
        self.children = children if children is not None else []

এই স্নিপেটটি যদি অন্য অপারেটর সিনট্যাক্স ব্যবহার করে। আমি এটি বিশেষত পছন্দ করি কারণ এটি কোনও কোলন ইত্যাদি ব্যতীত একটি ঝরঝরে সামান্য এক-লাইনার জড়িত এবং এটি প্রায় একটি সাধারণ ইংরেজি বাক্যটির মতো পড়ে। :)

আপনার ক্ষেত্রে আপনি লিখতে পারে

def myFunc(working_list=None):
    working_list = [] if working_list is None else working_list
    working_list.append("a")
    print working_list

-3

আমি ইউসিএসসি এক্সটেনশন ক্লাস নিয়েছি Python for programmer

যা সত্য: ডিফ এফএন (ডেটা = []):

ক) একটি ভাল ধারণা যাতে আপনার ডেটা তালিকাগুলি প্রতিটি কলের সাথে খালি শুরু হয়।

খ) একটি ভাল ধারণা যাতে কলটিতে কোনও আর্গুমেন্ট সরবরাহ না করে এমন ফাংশনটিতে সমস্ত কলগুলি ডেটা হিসাবে খালি তালিকা পাবে।

সি) যতক্ষণ না আপনার ডেটা স্ট্রিংয়ের তালিকা থাকে ততক্ষণ পর্যন্ত এটি একটি যুক্তিসঙ্গত ধারণা।

d) একটি খারাপ ধারণা কারণ ডিফল্ট [] ডেটা সংগ্রহ করবে এবং ডিফল্ট [] পরবর্তী কলগুলির সাথে পরিবর্তিত হবে।

উত্তর:

d) একটি খারাপ ধারণা কারণ ডিফল্ট [] ডেটা সংগ্রহ করবে এবং ডিফল্ট [] পরবর্তী কলগুলির সাথে পরিবর্তিত হবে।

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