বোধগম্যতার পরেও তালিকা বোধগম্যতা পুনরায় নামকরণ করে। এটা কী ঠিক?


117

বোধগম্যতার সাথে স্কোপিংয়ের সাথে কিছু অপ্রত্যাশিত ইন্টারঅ্যাকশন হচ্ছে। এটা কি প্রত্যাশিত আচরণ?

আমি একটি পদ্ধতি পেয়েছি:

def leave_room(self, uid):
  u = self.user_by_id(uid)
  r = self.rooms[u.rid]

  other_uids = [ouid for ouid in r.users_by_id.keys() if ouid != u.uid]
  other_us = [self.user_by_id(uid) for uid in other_uids]

  r.remove_user(uid) # OOPS! uid has been re-bound by the list comprehension above

  # Interestingly, it's rebound to the last uid in the list, so the error only shows
  # up when len > 1

ঝকঝকে ঝুঁকিতে, এটি ত্রুটির একটি নির্মম উত্স। আমি যখন নতুন কোড লিখি তখন মাঝে মাঝে রিব্যান্ডিংয়ের কারণে আমি খুব অদ্ভুত ত্রুটিগুলি খুঁজে পাই - এমনকি এখনও আমি জানি যে এটি একটি সমস্যা। আমাকে "আন্ডারস্কোর সহ সর্বদা তালিকাভুক্ত টেম্প ওয়ার্স প্রফেস করুন" এর মতো একটি নিয়ম তৈরি করা দরকার, তবে এটি বোকা-প্রমাণও নয়।

এই যে এলোমেলো টাইম-বোম্ব ওয়েটিং ধরণের রয়েছে তা তালিকার বোধের সমস্ত দুর্দান্ত "ব্যবহারের সহজ" উপেক্ষা করে।


7
-1: "ত্রুটির নৃশংস উত্স"? কষ্টসহকারে। এ জাতীয় যুক্তিযুক্ত পদটি কেন বেছে নিন? সাধারণত সবচেয়ে ব্যয়বহুল ত্রুটিগুলি হ'ল প্রয়োজনীয়তা ভুল বোঝাবুঝি এবং সাধারণ লজিক ত্রুটি। এই জাতীয় ত্রুটিটি অনেক প্রোগ্রামিং ভাষায় একটি স্ট্যান্ডার্ড সমস্যা হয়ে দাঁড়িয়েছে। কেন এটাকে 'পাশবিক' বলে?
এস .লট

44
এটি অন্তত বিস্ময়ের নীতি লঙ্ঘন করে। এটি তালিকা বোঝার জন্য অজগর নথিতে উল্লেখ করা হয়নি যা তারা কতটা সহজ এবং সুবিধাজনক তা বেশ কয়েকবার উল্লেখ করেছে। মূলত এটি একটি ল্যান্ড-মাইন যা আমার ভাষার মডেলের বাইরে ছিল এবং তাই আমার পক্ষে ধারণা করা অসম্ভব ছিল।
জবাবু অ্যাডামস

33
"ত্রুটির নির্মম উত্স" এর জন্য +1। 'পাশবিক' শব্দটি সম্পূর্ণ ন্যায়সঙ্গত।
নাথানিয়েল

3
আমি এখানে দেখছি কেবলমাত্র "পাশবিক" জিনিসটি হল আপনার নামকরণের সম্মেলন। এটি 80 এর বেশি নয় আপনি 3 অক্ষরের পরিবর্তনশীল নামের মধ্যে সীমাবদ্ধ নন।
উলোপ

5
দ্রষ্টব্য: ডকুমেন্টমেন্টে উল্লেখ করা হয়েছে যে তালিকা- forউপলব্ধিটি সুস্পষ্ট- লুপ নির্মাণ এবং for-লুপ ফাঁস ভেরিয়েবলের সমান । সুতরাং এটি সুস্পষ্ট ছিল না তবে সুস্পষ্টভাবে বিবৃত ছিল।
বাকুরিউ

উত্তর:


172

লিখিত বোধগম্যতা পাইথন 2 এ লুপ কন্ট্রোল ভেরিয়েবল ফাঁস করে তবে পাইথন 3 তে নয় Gu এখানে পিছনের ইতিহাস ব্যাখ্যা করে এখানে গাইডো ভ্যান রসুম (পাইথনের স্রষ্টা) এখানে রয়েছে:

তালিকার বোধগম্যতা এবং জেনারেটর এক্সপ্রেশনগুলির মধ্যে সমতা উন্নত করতে আমরা পাইথন 3 এ আরও একটি পরিবর্তন করেছি। পাইথন 2-এ, তালিকা উপলব্ধিটি পার্শ্ববর্তী স্কোপটিতে লুপ নিয়ন্ত্রণের পরিবর্তনশীল "ফাঁস" করে:

x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'

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

তবে পাইথন 3-তে, আমরা জেনারেটর এক্সপ্রেশন হিসাবে একই বাস্তবায়ন কৌশল ব্যবহার করে তালিকা বোঝার "নোংরা ছোট্ট গোপন" ঠিক করার সিদ্ধান্ত নিয়েছি। সুতরাং, পাইথন 3-এ, উপরোক্ত উদাহরণ (মুদ্রণ (x) ব্যবহারের পরিবর্তনের পরে) :-) 'আগে' মুদ্রণ করবে, তা প্রমাণ করে যে তালিকার বোধগম্যতায় 'x' সাময়িকভাবে ছায়া গোছা হয়েছে তবে পার্শ্ববর্তী অঞ্চলে 'x' ওভাররাইড করে না সুযোগ।


14
আমি যুক্ত করব যে যদিও গাইডো এটিকে "নোংরা ছোট গোপন" বলে অভিহিত করেছেন, অনেকেই এটি একটি বৈশিষ্ট্য হিসাবে বিবেচনা করেছেন, কোনও বাগ নয়।
স্টিভেন রাম্বালস্কি

38
এছাড়াও লক্ষ করুন যে এখন ২.7-এ সেট এবং অভিধানের বোধগম্যতা (এবং জেনারেটর) এর ব্যক্তিগত স্কোপ রয়েছে, তবে তালিকা বোঝার এখনও নেই। যদিও এটি কিছুটা বোঝায় যে প্রাক্তনরা সবাই পাইথন 3 থেকে ব্যাক-পোর্ট করেছিলেন তবে এটি তালিকার বোঝাপড়াগুলিকে ব্যাহত করার সাথে সত্যই বিপরীতে পরিণত হয়েছে।
ম্যাট বি

7
আমি জানি এটি একটি অত্যন্ত পুরানো প্রশ্ন, তবে কেন কেউ কেউ এটিকে ভাষার বৈশিষ্ট্য হিসাবে বিবেচনা করেছেন? এই ধরণের ভেরিয়েবল লিকের পক্ষে কি কিছু আছে?
ম্যাথিয়াস মুলার

2
কারণ: লুপ ফাঁস হওয়ার ভাল কারণ রয়েছে, এসপিএস। তাড়াতাড়ি পরে শেষ মান অ্যাক্সেস করতে break- তবে বোঝা অপ্রাসঙ্গিক। আমি কিছু কম্প.লং.পিথন আলোচনার কথা স্মরণ করি যেখানে লোকেরা ভাবের মাঝখানে ভেরিয়েবল নির্ধারণ করতে চেয়েছিল। কম উন্মাদ উপায় খুঁজে পেয়েছে ক্লজ যেমন জন্য সিঙ্গল-মান ছিল। sum100 = [s for s in [0] for i in range(1, 101) for s in [s + i]][-1], তবে কেবল একটি বোধগম্যতা-স্থানীয় var প্রয়োজন এবং পাইথন 3 তেও কাজ করে I আমি মনে করি "ফুটো" একটি অভিব্যক্তির বাইরে পরিবর্তনশীল দৃশ্যমান করার একমাত্র উপায় ছিল। প্রত্যেকেই এই কৌশলগুলি ভয়াবহ বলে সম্মত হয়েছে :-)
বেনি চেরনিয়াভস্কি-পাসকিন

1
এখানে সমস্যাটি তালিকা বোধের আশেপাশের সুযোগগুলিতে অ্যাক্সেস পাচ্ছে না, তবে পার্শ্ববর্তী স্কোপকে প্রভাবিত করে তালিকা বোধগম্যতার সুযোগকে বাধ্য করছে।
ফিলিপ গোনালভেস মার্কস

48

হ্যাঁ, লুপগুলির মতো পাইথন ২.x এ তাদের পরিবর্তনশীলগুলি "ফুটো" তালিকাবদ্ধ করুন list

পূর্ববর্তী ক্ষেত্রে, এটি একটি ভুল হিসাবে স্বীকৃত হয়েছিল এবং এটি জেনারেটরের অভিব্যক্তি দিয়ে এড়ানো হয়েছিল। সম্পাদনা: ম্যাট বি হিসাবে দ্রষ্টব্য হিসাবে পাইথন 3 থেকে সেট এবং অভিধান বোঝার সিনট্যাক্সগুলি ব্যাকপোর্ট করার সময় এটিও এড়ানো হয়েছিল।

পাইথন 2-তে যেমন তালিকা বোধের আচরণ ছেড়ে দেওয়া হয়েছিল, তবে পাইথন 3 এ এটি সম্পূর্ণরূপে স্থির হয়েছে।

এর অর্থ এই যে:

list(x for x in a if x>32)
set(x//4 for x in a if x>32)         # just another generator exp.
dict((x, x//16) for x in a if x>32)  # yet another generator exp.
{x//4 for x in a if x>32}            # 2.7+ syntax
{x: x//16 for x in a if x>32}        # 2.7+ syntax

xসবসময় অভিব্যক্তি এই সময় স্থানীয় হল:

[x for x in a if x>32]
set([x//4 for x in a if x>32])         # just another list comp.
dict([(x, x//16) for x in a if x>32])  # yet another list comp.

পাইথন ২.x-এ সমস্ত xপার্শ্ববর্তী স্কোপে ভেরিয়েবল ফাঁস করে দেয় ।


পাইথন ৩.৮ (?) এর জন্য আপডেট করুন : পিইপি 572 এমন :=অ্যাসাইনমেন্ট অপারেটর প্রবর্তন করবে যা ইচ্ছাকৃতভাবে বোধগম্যতা এবং জেনারেটরের এক্সপ্রেশন থেকে ফাঁস হয়ে যায়! এটি মূলত ২ টি ব্যবহারের ক্ষেত্রে প্রেরণা দেয়: প্রারম্ভিক-সমাপ্তকরণের কাজগুলি থেকে "সাক্ষী" ধরা any()এবং all():

if any((comment := line).startswith('#') for line in lines):
    print("First comment:", comment)
else:
    print("There are no comments")

এবং পরিবর্তনীয় রাষ্ট্র আপডেট করে:

total = 0
partial_sums = [total := total + v for v in values]

সঠিক স্কোপিংয়ের জন্য পরিশিষ্ট বি দেখুন । ভেরিয়েবলটি নিকটবর্তী কাছাকাছি defবা নির্ধারিত হয় lambdaযদি না যে ফাংশনটি এটি ঘোষণা করে nonlocalবা global


7

হ্যাঁ, অ্যাসাইনমেন্টটি সেখানে ঘটে থাকে ঠিক যেমন এটি কোনও forলুপে। কোনও নতুন সুযোগ তৈরি করা হচ্ছে না।

এটি অবশ্যই প্রত্যাশিত আচরণ: প্রতিটি চক্রের উপর, মানটি আপনার নির্দিষ্ট নামের সাথে আবদ্ধ। এই ক্ষেত্রে,

>>> x=0
>>> a=[1,54,4,2,32,234,5234,]
>>> [x for x in a if x>32]
[54, 234, 5234]
>>> x
5234

এটি স্বীকৃত হয়ে গেলে, এড়াতে এটি যথেষ্ট সহজ বলে মনে হচ্ছে: বোধগম্যতার মধ্যে ভেরিয়েবলগুলির জন্য বিদ্যমান নামগুলি ব্যবহার করবেন না।


2

মজার বিষয় হল এটি অভিধান বা সেট বোঝাটিকে প্রভাবিত করে না।

>>> [x for x in range(1, 10)]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
9
>>> {x for x in range(1, 5)}
set([1, 2, 3, 4])
>>> x
9
>>> {x:x for x in range(1, 100)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35, 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, 47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68, 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99}
>>> x
9

তবে উপরে উল্লিখিত হিসাবে এটি 3 এ স্থির করা হয়েছে।


পাইথন ২.6 এ সিনট্যাক্সটি মোটেই কাজ করে না। আপনি কি পাইথন ২.7 সম্পর্কে কথা বলছেন?
পল হোলিংসওয়ার্থ

পাইথন ২.6-তে কেবল পাইথন 3.0.০ এর মতো তালিকা উপলব্ধি রয়েছে। ৩.১ সেট এবং অভিধান বোঝার যোগ করেছে এবং এগুলিকে ২. to এ পোর্ট করা হয়েছে orted দুঃখিত যদি এটি পরিষ্কার না ছিল। এটি অন্য উত্তরের একটি সীমাবদ্ধতা নোট করা বোঝানো হয়েছিল এবং এটি কোন সংস্করণে প্রযোজ্য তা সম্পূর্ণ সোজা নয়।
ক্রিস ট্র্যাভারস

যদিও আমি একটি যুক্তি তৈরির কল্পনা করতে পারি যে নতুন কোডগুলির জন্য পাইথন ২.7 ব্যবহার করা অর্থবোধ করে, আমি পাইথন ২.6 এর জন্যও একই কথা বলতে পারি না ... এমনকি যদি আপনার ওএসের সাথে ২.6 আসে তবে আপনি আটকে থাকেন না এটা। নতুন কোডের জন্য ভার্চুয়ালেনভ এবং 3.6 ব্যবহার করার বিষয়টি বিবেচনা করুন!
অ্যালেক্স এল

পাইথন ২.6 সম্পর্কে বিষয়টি বিদ্যমান লিগ্যাসি সিস্টেম বজায় রাখার ক্ষেত্রে উঠে আসতে পারে। সুতরাং একটি noteতিহাসিক নোট হিসাবে এটি সম্পূর্ণ অপ্রাসঙ্গিক নয়। 3.0 (ick) এর সাথে একই
ক্রিস ট্র্যাভারস

দুঃখিত যদি আমি অভদ্র মনে হয় তবে এটি কোনওভাবেই প্রশ্নের উত্তর দেয় না। এটি একটি মন্তব্য হিসাবে ভাল উপযুক্ত।
0xc0de

1

অজগর ২.6 এর জন্য কিছুটা কার্যকর, যখন এই আচরণটি কাম্য নয়

# python
Python 2.6.6 (r266:84292, Aug  9 2016, 06:11:56)
Type "help", "copyright", "credits" or "license" for more information.
>>> x=0
>>> a=list(x for x in xrange(9))
>>> x
0
>>> a=[x for x in xrange(9)]
>>> x
8

-1

পাইথন 3-তে তালিকা বোধের সময় ভেরিয়েবল তার সুযোগের পরে পরিবর্তন হচ্ছে না তবে যখন আমরা সরল-লুপ ব্যবহার করি তখন ভেরিয়েবলটি সুযোগের বাইরে চলে যায়।

i = 1 মুদ্রণ (i) মুদ্রণ ([আমি পরিসীমা (5)]) মুদ্রণ (i) আমার মান কেবল 1 থাকবে।

এখন কেবল লুপের জন্য ব্যবহার করুন I এর মান পুনরায় বরাদ্দ করা হবে।

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