কীভাবে TypeError কাটাবেন: অপ্রয়োজনীয় টাইপ: 'তালিকা'


97

আমি এমন একটি ফাইল নেওয়ার চেষ্টা করছি যা দেখে মনে হচ্ছে:

AAA x 111
AAB x 111
AAA x 112
AAC x 123
...

এবং এর জন্য একটি অভিধান ব্যবহার করুন যাতে আউটপুটটি দেখতে ভাল লাগে

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}

এটিই আমি চেষ্টা করেছি

file = open("filename.txt", "r") 
readline = file.readline().rstrip()
while readline!= "":
    list = []
    list = readline.split(" ")
    j = list.index("x")
    k = list[0:j]
    v = list[j + 1:]
    d = {}
    if k not in d == False:
        d[k] = []
    d[k].append(v)
    readline = file.readline().rstrip()

আমি একটি পেতে রাখা TypeError: unhashable type: 'list'। আমি জানি যে একটি অভিধানের কীগুলি তালিকাগুলি হতে পারে না তবে আমি চেষ্টা করছি যে আমার মানটি কী নয় একটি তালিকায় তৈরি করা। আমি ভাবছি আমি কোথাও ভুল করেছি কিনা।

উত্তর:


56

অন্যান্য উত্তরের দ্বারা নির্দেশিত হিসাবে, ত্রুটিটি তার কারণ k = list[0:j], যেখানে আপনার কী একটি তালিকায় রূপান্তরিত হয়েছে। একটি জিনিস যা আপনি চেষ্টা করতে পারেন তা হ'ল splitফাংশনটির সুবিধা নিতে আপনার কোডটি পুনরায় কাজ করা:

# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
  d = {}
  # Here we use readlines() to split the file into a list where each element is a line
  for line in f.readlines():
    # Now we split the file on `x`, since the part before the x will be
    # the key and the part after the value
    line = line.split('x')
    # Take the line parts and strip out the spaces, assigning them to the variables
    # Once you get a bit more comfortable, this works as well:
    # key, value = [x.strip() for x in line] 
    key = line[0].strip()
    value = line[1].strip()
    # Now we check if the dictionary contains the key; if so, append the new value,
    # and if not, make a new list that contains the current value
    # (For future reference, this is a great place for a defaultdict :)
    if key in d:
      d[key].append(value)
    else:
      d[key] = [value]

print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

মনে রাখবেন যে আপনি যদি পাইথন ৩.x ব্যবহার করে থাকেন তবে এটি সঠিকভাবে কাজ করার জন্য আপনাকে একটি সামান্য সমন্বয় করতে হবে। আপনি যদি ফাইলটি দিয়ে খোলেন rb, আপনাকে ব্যবহার করতে হবে line = line.split(b'x')(যা নিশ্চিত করে যে আপনি সঠিক ধরণের স্ট্রিং দিয়ে বাইট বিভক্ত করছেন)। আপনি with open('filename.txt', 'rU') as f:(বা এমনকি with open('filename.txt', 'r') as f:) ব্যবহার করে ফাইলটিও খুলতে পারেন এবং এটি ঠিকঠাক কাজ করা উচিত।


33

দ্রষ্টব্য: এই উত্তরটি জিজ্ঞাসিত প্রশ্নের স্পষ্টভাবে উত্তর দেয় না। অন্যান্য উত্তর এটি করতে। যেহেতু প্রশ্নটি একটি দৃশ্যের সাথে সুনির্দিষ্ট এবং উত্থাপিত ব্যতিক্রমটি সাধারণ , এই উত্তরটি সাধারণ ক্ষেত্রে নির্দেশ করে।

হ্যাশ মানগুলি কেবল পূর্ণসংখ্যা যা অভিধান অভিধানে দ্রুত দেখার সময় অভিধান কীগুলি তুলনা করতে ব্যবহৃত হয়।

অভ্যন্তরীণভাবে, hash()পদ্ধতি __hash__()কোনও অবজেক্টের পদ্ধতি কল করে যা কোনও অবজেক্টের জন্য ডিফল্টরূপে সেট করা হয়।

নেস্টেড তালিকাকে একটি সেটে রূপান্তর করা

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

তালিকার ভিতরে থাকা তালিকার কারণে এটি ঘটে যা একটি তালিকা যা হ্যাশ করা যায় না। যা অভ্যন্তরীণ নেস্টেড তালিকাগুলিকে একটি টুপলে রূপান্তর করে সমাধান করা যেতে পারে ,

>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])

স্পষ্টত একটি নেস্টেড তালিকা হ্যাশ

>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506

এই ত্রুটিটি এড়ানোর সমাধান হ'ল তালিকার পরিবর্তে নেস্টেড টুপলগুলি রয়েছে তালিকাটিকে পুনর্গঠন করা।


4
তালিকা খুব বড় হলে কি হবে ?? দেখে মনে হচ্ছে এটি একটি ভাল সমাধান তবে যথেষ্ট সাধারণ নয়
msh855

4
@ এমএস 85৮৫ কি কোনও আকারের সীমা আছে? আমি ১০০,০০০ সাইজের আকারের সাথে
অভিধানটি

19

আপনি এর kকী হিসাবে (যা একটি তালিকা) ব্যবহার করার চেষ্টা করছেন d। তালিকাগুলি পরিবর্তনীয় এবং ডিক কী হিসাবে ব্যবহার করা যায় না।

এছাড়াও, আপনি এই অভিধানের কারণে অভিধানের তালিকাগুলি কখনই আরম্ভ করছেন না:

if k not in d == False:

যা হওয়া উচিত:

if k not in d == True:

যা আসলে হওয়া উচিত:

if k not in d:

6

আপনি unhashable type: 'list'ব্যতিক্রম হওয়ার কারণ হ'ল k = list[0:j]সেটগুলি kতালিকার একটি "টুকরা" হতে হবে যা যৌক্তিকভাবে অন্য, প্রায়শই সংক্ষিপ্ত, তালিকার হয়ে থাকে। আপনার কি কি প্রয়োজন তালিকায় শুধু প্রথম আইটেম, তাই মত লিখিত পেতে হয় k = list[0]। কলটি থেকে ফিরে আসা তালিকার তৃতীয় উপাদানটির জন্য একই v = list[j + 1:]হওয়া উচিত ।v = list[2]readline.split(" ")

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

এখানে আপনার এই পরিবর্তনগুলির সাথে একটি কার্যকারী সংস্করণ রয়েছে, ifআপনি কীটি অভিধানে ইতিমধ্যে রয়েছেন কিনা তা পরীক্ষা করতে আপনি যে বিবৃতিটি ব্যবহার করেছেন তা প্রতিস্থাপন করেছি এবং setdefault()একই জিনিসটি আরও কিছুটা সংক্ষেপে সম্পাদন করতে এখন অভিধানের পদ্ধতি ব্যবহার করছি ।

d = {}
with open("nameerror.txt", "r") as file:
    line = file.readline().rstrip()
    while line:
        lst = line.split() # Split into sequence like ['AAA', 'x', '111'].
        k, _, v = lst[:3]  # Get first and third items.
        d.setdefault(k, []).append(v)
        line = file.readline().rstrip()

print('d: {}'.format(d))

আউটপুট:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

0

এটি TypeErrorহ'ল কারণ kএটি একটি তালিকা, যেহেতু এটি লাইন সহ অন্য তালিকা থেকে একটি স্লাইস ব্যবহার করে তৈরি করা হয়েছে k = list[0:j]। এটি সম্ভবত এমন কিছু হওয়া উচিত k = ' '.join(list[0:j]), যাতে পরিবর্তে আপনার কাছে স্ট্রিং থাকে।

এগুলি ছাড়াও, ifজেসির উত্তর দ্বারা উল্লিখিত হিসাবে আপনার বক্তব্যটি ভুল, যা পড়তে হবে if k not in dবা if not k in d(আমি পরবর্তীটি পছন্দ করি)।

d = {}আপনার forলুপের অভ্যন্তরীণ অংশটি রয়েছে তাই আপনি প্রতিটি পুনরাবৃত্তিতে আপনার অভিধানটি সাফ করছেন ।

নোট আপনার কাছে ব্যবহার করা উচিত হবে না যে listবা fileযেমন পরিবর্তনশীল নাম, যেহেতু আপনি builtins মাস্কিং করা হবে না।

আমি এখানে আপনার কোডটি আবার লিখব কীভাবে:

d = {}
with open("filename.txt", "r") as input_file:
    for line in input_file:
        fields = line.split()
        j = fields.index("x")
        k = " ".join(fields[:j])
        d.setdefault(k, []).append(" ".join(fields[j+1:]))

dict.setdefault()পদ্ধতি উপরে প্রতিস্থাপন if k not in dআপনার কোড থেকে যুক্তি।


অগ্রাধিকার আপনার সম্পূর্ণ অধিকার, যদিও কোনও not k in dনবজাতককে বিভ্রান্ত করতে পারে (not k) in d, যদিও k not in dকোনও অস্পষ্টতা নেই
জেসি গেম

আমি এমনকি তর্ক করবে এটি 'pythonic' হিসেবে উপায় not inএকটি হিসেবে তালিকাভুক্ত করা হয় অপারেটর
জেসি গেমটি

হ্যাঁ, আমি মনে করি আমার পছন্দটি সম্ভবত প্রথমে অন্যান্য ভাষা শেখার থেকে আসে, যেখানে কন্টেন্ট টেস্টের মতো কোনও কিছুর জন্য আপনি অপারেটর রাখেন না যাতে আপনি এর মতো কিছু করেন !a.contains(b)not inআরও পাইথোনিক হতে পারে, আমি বুলিয়ান এক্সপ্রেশনটিতে ইনভার্স ব্যবহার না করে কেবল দুটি শব্দ অপারেটরের ধারণাটি আরও বিভ্রান্তিকর বলে মনে করি।
অ্যান্ড্রু ক্লার্ক

-1
    python 3.2

    with open("d://test.txt") as f:
              k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
              d={}
              for i,_,v in k:
                      d.setdefault(i,[]).append(v)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.