ডিফল্টডিক্টের ডিফল্ট_ফ্যাক্টরির কীটি পাস করার কোনও চতুর উপায় আছে?


95

একটি শ্রেণীর একটি কনস্ট্রাক্টর থাকে যা একটি প্যারামিটার নেয়:

class C(object):
    def __init__(self, v):
        self.v = v
        ...

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

d = defaultdict(lambda : C(here_i_wish_the_key_to_be))

কোনও পরামর্শ?

উত্তর:


128

এটি চালাক হিসাবে খুব কমই যোগ্যতা অর্জন করে - তবে সাবক্লাসিংটি আপনার বন্ধু:

class keydefaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError( key )
        else:
            ret = self[key] = self.default_factory(key)
            return ret

d = keydefaultdict(C)
d[x] # returns C(x)

16
এটাই ঠিক যে কুৎসিততা আমি এড়াতে চাইছি ... এমনকি সাধারণ ডিক ব্যবহার করে এবং মূল অস্তিত্বের জন্য পরীক্ষা করা আরও পরিষ্কার।
বেনিয়ামিন নিতলেহু

4
@ পল: এবং এখনও এটি আপনার উত্তর। কদর্যতা? চলে আসো!
tzot

4
আমি মনে করি যে আমি ঠিক সেই বিট কোডটি নিয়ে যাচ্ছি এবং এটি আমার ব্যক্তিগতকৃত সাধারণ ইউটিলিটিস মডিউলে রেখেছি যাতে আমি যখনই চাই এটি ব্যবহার করতে পারি। না খুব কুশ্রী যে ভাবে ...
weronika

24
+1 সরাসরি ওপির প্রশ্নকে সম্বোধন করে এবং আমার কাছে "কুরুচিপূর্ণ" দেখাচ্ছে না। এছাড়াও একটি ভাল উত্তর কারণ অনেকেই বুঝতে পারে না যে defaultdictএর __missing__()পদ্ধতিটি ওভাররাইড করা যেতে পারে (এটি dictভার্সন 2.5 এর সংস্করণ থেকে অন্তর্নির্মিত শ্রেণীর কোনও সাবক্লাসে থাকতে পারে )।
মার্টিনো

7
+1 __ মিসিং__ এর পুরো উদ্দেশ্য হ'ল চাবিগুলির জন্য আচরণটি কাস্টমাইজ করা। @ সাইলেন্টঘোস্ট দ্বারা উল্লিখিত ডিক্ট.সেটেফল্ট () পদ্ধতিটিও কাজ করবে (প্লাস সাইডে, সেটডেফল্ট () সংক্ষিপ্ত এবং ইতিমধ্যে বিদ্যমান; বিয়োগের দিক থেকে, এটি দক্ষতার সমস্যাগুলিতে ভুগছে এবং "সেটডেফল্ট" নামটি আসলে কেউ পছন্দ করে না) ।
রেমন্ড হেটেঞ্জার

26

কোন নেই.

defaultdictবাস্তবায়ন অনুপস্থিত পাস কনফিগার করা যায় না keyকরার default_factoryআউট-অফ-বক্স। আপনার কেবলমাত্র বিকল্পটি আপনার নিজের defaultdictসাবক্লাসটি বাস্তবায়িত করা হবে, উপরের উপরের @ জোচেনরিটজেলের পরামর্শ অনুসারে।

তবে এটি "চতুর" বা স্ট্যান্ডার্ড লাইব্রেরির সমাধান হিসাবে প্রায় পরিষ্কার নয় (এটি বিদ্যমান থাকলে)। সুতরাং আপনার সংযুক্তির উত্তর, হ্যাঁ / কোনও প্রশ্নের স্পষ্টভাবে "না"।

এটি খুব খারাপ যে স্ট্যান্ডার্ড লাইব্রেরিতে এ জাতীয় প্রায়শই প্রয়োজনীয় সরঞ্জাম অনুপস্থিত।


হ্যাঁ, কারখানার চাবিটি (নালারির পরিবর্তে আনরি ফাংশন) দেওয়ার জন্য এটি আরও ভাল ডিজাইনের পছন্দ হতে পারে। যখন আমরা একটি ধ্রুবক ফিরিয়ে দিতে চাই তখন একটি যুক্তি ত্যাগ করা সহজ।
YvesgereY

6

আমি মনে করি না যে defaultdictএখানে আপনার মোটেই প্রয়োজন । কেন শুধু dict.setdefaultপদ্ধতি ব্যবহার করবেন না ?

>>> d = {}
>>> d.setdefault('p', C('p')).v
'p'

এটি অবশ্যই অনেক উদাহরণ তৈরি করবে C। যদি এটি কোনও সমস্যা হয় তবে আমি মনে করি যে সহজ পদ্ধতির কাজটি করবে:

>>> d = {}
>>> if 'e' not in d: d['e'] = C('e')

defaultdictযতদূর আমি দেখতে পাচ্ছি এটি অন্য যে কোনও বিকল্পের চেয়ে দ্রুত হবে ।

inপরীক্ষার গতি সম্পর্কিত ইটিএ বনাম চেষ্টা করে বাদ দিয়ে চেষ্টা করুন:

>>> def g():
    d = {}
    if 'a' in d:
        return d['a']


>>> timeit.timeit(g)
0.19638929363557622
>>> def f():
    d = {}
    try:
        return d['a']
    except KeyError:
        return


>>> timeit.timeit(f)
0.6167065411074759
>>> def k():
    d = {'a': 2}
    if 'a' in d:
        return d['a']


>>> timeit.timeit(k)
0.30074866358404506
>>> def p():
    d = {'a': 2}
    try:
        return d['a']
    except KeyError:
        return


>>> timeit.timeit(p)
0.28588609450770264

7
এটি অনেক ক্ষেত্রে অপ্রয়োজনীয় যেখানে d বহুবার অ্যাক্সেস করা হয় এবং খুব কমই একটি কী অনুপস্থিত হয়: সি (কী) এইভাবে জিসি সংগ্রহ করার জন্য অযাচিত অবজেক্ট তৈরি করবে objects এছাড়াও, আমার ক্ষেত্রে একটি অতিরিক্ত ব্যথা হয়, যেহেতু নতুন সি অবজেক্ট তৈরি করা ধীর।
বেনিয়ামিন নিতলেহু

@ পল: ঠিক আছে। আমি তারপরে আরও সহজ পদ্ধতিটি প্রস্তাব করব, আমার সম্পাদনাটি দেখুন।
সাইলেন্টগোস্ট

আমি নিশ্চিত যে এটি ডিফল্ট ডিটিক্টের চেয়ে দ্রুত, তবে আমি সাধারণত এটি করি (টিএইচসি 4 এর উত্তরে আমার মন্তব্য দেখুন)। আমি আশা করেছি যে ডিফল্ট_ফ্যাক্টরিটি কোডটি আরও মার্জিত রাখার জন্য কোনও হস্তক্ষেপের সহজ উপায় রয়েছে the
বেনিয়ামিন নিতলেহু

4
@ সাইলেন্টগোস্ট: আমি বুঝতে পারি না - এটি কীভাবে ওপি'র সমস্যা সমাধান করবে? আমি ভেবেছিলাম ওপি যদি d[key]ফেরার জন্য কোনও প্রয়াস চাইছিল । কিন্তু আপনার সমাধানের জন্য তাকে কী আসলেই যেতে হবে এবং আগে থেকেই প্রাক-সেট করা উচিত? সে কীভাবে জানতে পারে যার প্রয়োজন তার? d[key] = C(key)key not in dd[key]key
সর্বোচ্চ

4
কারণ সেটডাফল্ট নরক হিসাবে কুরুচিপূর্ণ এবং সংগ্রহ থেকে ডিফল্টডিক্ট্টটি এমন কোনও কারখানার ফাংশন সাপোর্ট করে যা কীটি গ্রহণ করে। পাইথন ডিজাইনারদের কাছ থেকে কী অপচয়!
jgomo3

0

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

class FullPaths:

    def __init__(self,filename):
        self.filename = filename
        self.paths = set()

    def record_path(self,path):
        self.paths.add(path)

class PathDict(dict):

    def __missing__(self, key):
        ret = self[key] = FullPaths(key)
        return ret

if __name__ == "__main__":
    pathdict = PathDict()
    for root, _, files in os.walk('/usr/include'):
        for f in files:
            path = os.path.join(root,f)
            pathdict[f].record_path(path)
    for fullpath in pathdict.values():
        if len(fullpath.paths) > 1:
            print("{} located in {}".format(fullpath.filename,','.join(fullpath.paths)))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.