'উইথ' স্টেটমেন্টে একাধিক ভেরিয়েবল?


391

withপাইথনে স্টেটমেন্ট ব্যবহার করে একাধিক ভেরিয়েবল ঘোষণা করা সম্ভব ?

কিছুটা এইরকম:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

... বা একই সাথে দুটি সংস্থান পরিষ্কার করা হচ্ছে সমস্যা?


সম্ভবত এটির মতো: [expr1, expr2] এর সাথে f হিসাবে: এবং তারপরে f [0] এবং f [1] ব্যবহার করুন।
jbasko

ভালো হত কারন কিছু আমদানি করার দরকার পড়েনি .... তবে এটি এট্রিবিউটআরার কাজ করে না: 'তালিকা' অবজেক্টটির ' এক্সিট ' কোনও বৈশিষ্ট্য নেই
pufferfish

অজগরটির সবেমাত্র বন্ধ হয়ে গেলে, আপনার বিবৃতিটির দরকার
বিটি

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

1
এই উত্তরগুলির মধ্যে অনেকগুলি বিবৃতি দিয়ে দুটিরও বেশি প্রয়োজনের সাথে মোকাবিলা করে না। তাত্ত্বিকভাবে এমন অ্যাপ্লিকেশন থাকতে পারে যার দশক প্রসঙ্গ খোলার প্রয়োজন হয়, খুব দ্রুত বাসা বাঁধে যে কোনও লাইন দৈর্ঘ্যের সীমাবদ্ধতা আরোপিত হয়।
থারস্ম্মোনার

উত্তর:


666

V3.1 এবং পাইথন 2.7 থেকে পাইথন 3 এ এটি সম্ভব । নতুন withসিনট্যাক্স একাধিক প্রসঙ্গ পরিচালককে সমর্থন করে:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

ভিন্ন contextlib.nested, এই নিশ্চয়তা যে aএবং bথাকবে তাদের __exit__()'বলা র এমনকি যদি C()বা এটা __enter__()পদ্ধতি একটি ব্যতিক্রম উত্থাপন।

আপনি পরবর্তী সংজ্ঞাগুলিতে পূর্বের চলকগুলিও ব্যবহার করতে পারেন ( নীচে এইচ / টি আহমেদ ):

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

1
এটি কি বিবৃতিতে কিছু হিসাবে সমান ক্ষেত্রগুলি সেট করা সম্ভব with open('./file') as arg.x = file:?
চার্লি পার্কার

13
এছাড়াও, এটি সম্ভব: ক হিসাবে এ () এ, বি (ক) খ হিসাবে, সি (ক, খ) সি হিসাবে:
আহমদ ইউসোফান

শ্রেণি পরীক্ষা 2: x = 1; t2 = test2 () ওপেন ('f2.txt') এর সাথে t2.x হিসাবে: l1 for t2.x.readlines (): মুদ্রণ (l1); # চার্লি পার্কার # অজগর 3.6 এ পরীক্ষিত
আহমদ ইউসোফান

1
দয়া করে নোট করুন, asisচ্ছিক।
সাওওমির লেনার্ট

@ সাওমিরিলনার্ট যা বলছে তা স্পষ্ট করে বলতে: আপনার asযদি প্রয়োজন বস্তুর প্রয়োজন হয় aবা b, তবে পুরো as aবা as bপ্রয়োজন হয় না
সিপ্রিয়ান টোমাইগ

56

contextlib.nested এটি সমর্থন করে:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

আপডেট:
ডকুমেন্টেশন উদ্ধৃত করতে, সম্পর্কিত contextlib.nested:

সংস্করণ ২.7 থেকে অবহেলিত : বিবৃতি সহ এখন এই কার্যকারিতাটি সরাসরি সমর্থন করে (বিভ্রান্তিকর ত্রুটিযুক্ত প্রবণতা ছাড়াই)।

দেখুন Rafal Dowgird এর উত্তর দেখুন।


34
আমি এটি বলার জন্য দুঃখিত, তবে আমি মনে করি nestedপ্রসঙ্গ পরিচালকটি একটি ভুল এবং কখনও ব্যবহার করা উচিত নয়। এই উদাহরণস্বরূপ, যদি দ্বিতীয় ফাইলটি খোলার ফলে একটি ব্যতিক্রম উত্থাপিত হয়, তবে প্রথম ফাইলটি একেবারেই বন্ধ হবে না, ফলে প্রসঙ্গ পরিচালকগণের ব্যবহারের উদ্দেশ্যটি সম্পূর্ণরূপে ধ্বংস হয়ে যায়।
রাফা ডাউগার্ড

তুমি কেন এটা বললে? ডকুমেন্টেশনে বলা হয়েছে যে নেস্টেড ব্যবহার করা 'নেস্টেড' এর সাথে সমান
জেমস হপকিন

@ রাফাল: ম্যানুয়ালটিতে এক নজরে মনে হয় যে অজগরটি সঠিকভাবে বিবৃতি দিয়ে বাসা বেঁধেছে। আসল সমস্যাটি হ'ল দ্বিতীয় ফাইলটি বন্ধ হওয়ার পরে যদি ব্যতিক্রম ছুঁড়ে।
অজানা

10
@ জেমস: না, ডকস.পিথথন.আর.এলিবেরি / কনটেক্সটলিব এইচটিএমএল#contextlib.nested এ ডক্সে সমমানের কোডটি স্ট্যান্ডার্ড নেস্টেড withব্লক থেকে পৃথক । ম্যানেজারগুলি ব্লকগুলি সহ প্রবেশের আগে ক্রমে তৈরি করা হয়: এম 1, এম 2, এম 3 = এ (), বি (), সি () বি () বা সি () ব্যতিক্রম ব্যর্থ হলে, তবে আপনার এটিকে সঠিকভাবে চূড়ান্ত করার একমাত্র আশা hope ) আবর্জনা সংগ্রহকারী।
রাফা ডাউগার্ড

8
সংস্করণ ২.7 থেকে অবহেলিত । দ্রষ্টব্য: বিবৃতি সহ এখন সরাসরি এই কার্যকারিতা সমর্থন করে (বিভ্রান্তিকর ত্রুটিযুক্ত প্রবণতা ছাড়াই)।
মিকু

36

নোট করুন যে আপনি যদি ভেরিয়েবলগুলিকে লাইনে ভাগ করেন তবে আপনাকে নতুন লাইনগুলি মোড়ানোর জন্য অবশ্যই ব্যাকস্ল্যাশ ব্যবহার করতে হবে।

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

প্যারেন্টিসগুলি কাজ করে না, যেহেতু পাইথন পরিবর্তে একটি টিপল তৈরি করে।

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

যেহেতু টিপলসগুলির একটি __enter__বৈশিষ্ট্যের অভাব থাকে তাই আপনি একটি ত্রুটি পান (বর্ণনামূলক এবং শ্রেণীর ধরণের শনাক্ত করেন না):

AttributeError: __enter__

যদি আপনি প্রথম asবন্ধনীগুলির মধ্যে ব্যবহারের চেষ্টা করেন , পাইথন পার্স সময় ভুলটি ধরেন:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)

সিনট্যাক্সেরর: অবৈধ সিনট্যাক্স

https://bugs.python.org/issue12782 এই সমস্যার সাথে সম্পর্কিত বলে মনে হচ্ছে।


16

আমি মনে করি আপনি পরিবর্তে এটি করতে চান:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

5
আমি বর্তমানে এটি এটিই করি তবে তার পরে বাসা বাঁধতে চেয়ে দ্বিগুণ গভীর হয় (মানে) এটি হতে চাই ...
পফারফিশিশ

আমি মনে করি এটি যদিও সবচেয়ে পরিষ্কার পদ্ধতির - অন্য কোনও পদ্ধতির পড়া আরও কঠিন হতে চলেছে। অ্যালেক্স মার্তেলির উত্তর আপনি যা চান তার কাছাকাছি বলে মনে হচ্ছে তবে এটি খুব কম পাঠযোগ্য। বাসা বাঁধছে কেন এমন উদ্বেগ?
অ্যান্ড্রু হরে

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

2
@ অ্যালেক্স: খুব সত্য তবে আমাদের অবশ্যই "পাঠযোগ্যতার গণনা" বিবেচনা করতে হবে।
অ্যান্ড্রু হরে

4
@ অ্যান্ড্রু: আমি মনে করি একটি স্তর ইনডেন্টেশন আরও ভালভাবে প্রোগ্রামটির উদ্দিষ্ট যুক্তি প্রকাশ করে, যা "পরমাণুভাবে" দুটি ভেরিয়েবল তৈরি করা এবং পরে একসাথে পরিষ্কার করা (আমি বুঝতে পারি এটি আসলে কী হয় না)। ভাবেন ব্যতিক্রম বিষয়টি যদিও ডিল ব্রেকার
পফারফিশিশ

12

পাইথন ৩.৩ থেকে আপনি মডিউলটি ExitStackথেকে ক্লাসটি ব্যবহার করতে পারেন contextlib

এটি প্রাসঙ্গিক-সচেতন অবজেক্টগুলির একটি গতিশীল সংখ্যক পরিচালনা করতে পারে, যার অর্থ এটি আপনি বিশেষত কার্যকর প্রমাণিত করবেন যদি আপনি জানেন না যে আপনি কতগুলি ফাইল পরিচালনা করছেন।

ডকুমেন্টেশনে উল্লিখিত ক্যানোনিকাল ইউজ-কেস ফাইলগুলির গতিশীল সংখ্যা পরিচালনা করছে।

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

এখানে একটি সাধারণ উদাহরণ:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

আউটপুট:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

0

পাইথন ৩.১++ তে আপনি একাধিক প্রসঙ্গের এক্সপ্রেশনগুলি নির্দিষ্ট করতে পারবেন এবং সেগুলি এমনভাবে প্রক্রিয়া করা হবে যেন একাধিক withবক্তব্য নেস্ট করা থাকে:

with A() as a, B() as b:
    suite

সমতুল্য

with A() as a:
    with B() as b:
        suite

এর অর্থ এটিও হ'ল আপনি দ্বিতীয়টির প্রথম প্রকাশ থেকে উপনামটি ব্যবহার করতে পারেন (ডিবি সংযোগ / কার্সার দিয়ে কাজ করার সময় দরকারী):

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