در درس ۱۲ام آموزش رایگان پایتون در سایت دیتایاد می خواهیم در مورد گرفتن ورودی در پایتون و انواع حالات آن صحبت کنیم.
گرفتن ورودی در پایتون
توسعه دهندگان اغلب نیاز دارند تا با کاربران تعامل داشته باشند، چه برای دریافت اطلاعات و چه برای ارائه نوعی نتیجه. اکثر برنامهها امروزه از یک کادر گفتگو برای درخواست کاربر برای ارائه نوعی ورودی استفاده میکنند.
پایتون به ما دو تابع داخلی برای خواندن ورودی از صفحه کلید ارائه میدهد.
input ( prompt )
raw_input ( prompt )
تابع ()input
این تابع ابتدا ورودی را از کاربر دریافت کرده و آن را به یک رشته تبدیل میکند. نوع شیء برگردانده شده همیشه <class ‘str’> خواهد بود. این تابع عبارت را ارزیابی نمیکند بلکه تنها کل عبارت را به صورت رشته برمیگرداند.
برای مثال، پایتون تابع داخلی به نام input را ارائه میدهد که ورودی را از کاربر دریافت میکند. وقتی تابع input فراخوانی میشود، برنامه را متوقف کرده و منتظر ورودی کاربر میماند. وقتی کاربر کلید Enter را فشار میدهد، برنامه ادامه یافته و آنچه که کاربر تایپ کرده است را برمیگرداند.
نوشتار دستور input:
inp = input('STATEMENT') Example: 1. >>> name = input('What is your name?\n') # \n ---> newline ---> It causes a line break >>> What is your name? Ram >>> print(name) Ram # ---> comment in python
# Python program showing # a use of input() val = input("Enter your value: ") print(val)
خروجی:
گرفتن رشته به عنوان ورودی:
# \n ---> newline ---> It causes a line break name = input('What is your name?\n') print(name)
خروجی:
What is your name? Ram Ram
نحوه کار تابع ()input در پایتون
- زمانی که تابع ()input اجرا میشود، جریان برنامه متوقف میشود تا زمانی که کاربر ورودی خود را ارائه دهد.
- متن یا پیامی که بر روی صفحه خروجی نمایش داده میشود تا از کاربر بخواهد یک مقدار ورودی را وارد کند، اختیاری است، یعنی هر پیامی که بر روی صفحه چاپ میشود، اختیاری است.
- هر چیزی که شما به عنوان ورودی وارد کنید، تابع input آن را به یک رشته تبدیل میکند. حتی اگر عدد صحیح وارد کنید، باز هم تابع ()input آن را به یک رشته تبدیل میکند. در این حالت باید به صورت صریح آن را در کد خود با استفاده از تبدیل نوع به عدد صحیح تبدیل کنید.
# Program to check input # type in Python num = input ("Enter number :") print(num) name1 = input("Enter name : ") print(name1) # Printing type of input value print ("type of number", type(num)) print ("type of name", type(name1))
خروجی:
تابع ()raw_input
این تابع در نسخههای قدیمیتر (مانند پایتون ۲) کار میکند. این تابع دقیقاً همان چیزی را که از صفحه کلید تایپ میشود، دریافت کرده، آن را به رشته تبدیل میکند، و سپس آن را به متغیری که میخواهیم در آن ذخیره کنیم، برمیگرداند.
# Python program showing # a use of raw_input() g = raw_input("Enter your name : ") print g
خروجی:
در این برنامه، g یک متغیر است که مقدار رشتهای را که توسط کاربر در طول اجرای برنامه تایپ میشود، دریافت میکند. وارد کردن دادهها برای تابع ()raw_input با فشار دادن کلید Enter پایان مییابد. ما میتوانیم از تابع ()raw_input برای ورود دادههای عددی نیز استفاده کنیم. در آن مورد، ما از تبدیل نوع استفاده میکنیم. برای دیدن جزئیات بیشتر در مورد تبدیل نوع به سایر مقالات ما مراجعه کنید.
توجه: تابع ()input تمام ورودیها را تنها به صورت رشته دریافت میکند.
توابع مختلفی وجود دارند که برای گرفتن ورودیهای مورد نظر استفاده میشوند، برخی از آنها عبارتاند از:
– int(input())
– float(input())
مثال:
num = int(input("Enter a number: ")) print(num, " ", type(num)) floatNum = float(input("Enter a decimal number: ")) print(floatNum, " ", type(floatNum))
خروجی:
گرفتن ورودی از کنسول در پایتون
کنسول در پایتون چیست؟ کنسول -که به آن شل (shell) هم گفته میشود- به طور اساسی یک مفسر خط فرمان است که ورودی را از کاربر دریافت میکند، یعنی یک دستور در یک زمان و آن را تفسیر میکند.
اگر خطایی نداشته باشد، دستور را اجرا کرده و خروجی مورد نیاز را ارائه میدهد، در غیر این صورت پیام خطا نمایش داده میشود. کنسول پایتون به این شکل به نظر میرسد.
به این ترتیب میتوانید دستوری بنویسید و با فشار دادن کلید Enter، دستورتان اجرا شود. برای برنامهنویسی با پایتون، باید ابتدا با کنسولی که در پایتون استفاده میشود، آشنا باشید. نشانه اصلی در ابتدای خط در کنسول پایتون، سه نشانه بزرگتر از (<<<) است.
زمانی میتوانید دستور بعدی را بنویسید که این نشانهها پس از اجرای دستور قبلی ظاهر شوند. کنسول پایتون دستورات نوشته شده به زبان پایتون را که پس از این نشانهها قرار میگیرند، قبول میکند.
دریافت ورودی از کنسول
کاربر میتواند ورودی مورد نظرش را از طریق کنسول وارد برنامه کند، برای این کار همانطور که گفته شد میتوان از دستور ()input استفاده کرد.
# input input1 = input() # output print(input1)
همچنین میتوانیم ورودی را به صورت صریح به عدد صحیح، اعشاری، یا رشته تبدیل کنیم با این روش که تابع ()input را درون نوع مورد نظر خود قرار دهیم.
۱. تبدیل نوع ورودی به عدد صحیح: ممکن است شرایطی وجود داشته باشد که به ورودی عدد صحیح از کاربر یا کنسول نیاز داشته باشید، کد زیر دو ورودی (عدد صحیح یا اعشاری) را از کنسول دریافت کرده، آنها را به عدد صحیح تبدیل میکند و سپس مجموع آنها را چاپ میکند.
# input num1 = int(input()) num2 = int(input()) # printing the sum in integer print(num1 + num2)
۲. تبدیل نوع ورودی به اعشاری: برای تبدیل ورودی به اعشاری، کد زیر کاربردی خواهد بود.
# input num1 = float(input()) num2 = float(input()) # printing the sum in float print(num1 + num2)
۳. تبدیل نوع ورودی به رشته: تمامی انواع ورودیها، چه اعشاری و چه عدد صحیح، میتوانند به نوع رشته تبدیل شوند. ما از کلمه کلیدی str برای تبدیل نوع استفاده میکنیم.
همچنین میتوانیم ورودی رشتهای را تنها با نوشتن تابع ()input دریافت کنیم؛ چون همانطور که گفته شد این تابع به صورت پیشفرض ورودی را به نوع رشته تبدیل میکند.
# input string = str(input()) # output print(string) # Or by default string_default = input() # output print(string_default)
دریافت چندین ورودی از کاربر در پایتون
در پایتون، توسعهدهندگان اغلب میخواهند که کاربران چندین مقدار یا ورودی را در یک خط وارد کنند. در C++/C کاربران میتوانند با استفاده از scanf چندین ورودی را در یک خط دریافت کنند، اما در پایتون، کاربران میتوانند با دو روش چندین مقدار یا ورودی را در یک خط وارد کنند.
– استفاده از روش ()split
– استفاده از خلاصه لیست (List comprehension)
استفاده از روش ()split
این تابع به دریافت چندین ورودی از کاربران کمک میکند. این تابع ورودی داده شده را بر اساس جداکننده مشخص شده تقسیم میکند. اگر جداکنندهای ارائه نشود، هر فضای سفیدی به عنوان جداکننده در نظر گرفته میشود. به طور کلی، کاربران از روش ()split برای تقسیم یک رشته پایتون استفاده میکنند، اما میتوان از آن برای دریافت چندین ورودی نیز استفاده کرد.
نوشتار دستور:
input().split(separator, maxsplit)
مثال:
# Python program showing how to # multiple input using split # taking two inputs at a time x, y = input("Enter two values: ").split() print("Number of boys: ", x) print("Number of girls: ", y) # taking three inputs at a time x, y, z = input("Enter three values: ").split() print("Total number of students: ", x) print("Number of boys is : ", y) print("Number of girls is : ", z) # taking two inputs at a time a, b = input("Enter two values: ").split() print("First number is {} and second number is {}".format(a, b)) # taking multiple inputs at a time # and type casting using list() function x = list(map(int, input("Enter multiple values: ").split())) print("List of students: ", x)
خروجی:
Enter two values: 5 10 Number of boys: 5 Number of girls: 10 Enter three values: 5 10 15 Total number of students: 5 Number of boys is : 10 Number of girls is : 15 Enter two values: 5 10 First number is 5 and second number is 10 Enter multiple values: 5 10 15 20 25 List of students: [5, 10, 15, 20, 25]
استفاده از خلاصه لیست (List comprehension)
خلاصه لیست، روشی هوشمندانه برای تعریف و ساختن لیست در پایتون است. در این حالت میتوانیم درست مثل عبارات ریاضی، لیستهایی را فقط در یک خط بسازیم. این روش همچنین برای دریافت چندین ورودی همزمان از کاربر به کار میرود.
# Python program showing # how to take multiple input # using List comprehension # taking two input at a time x, y = [int(x) for x in input("Enter two values: ").split()] print("First Number is: ", x) print("Second Number is: ", y) # taking three input at a time x, y, z = [int(x) for x in input("Enter three values: ").split()] print("First Number is: ", x) print("Second Number is: ", y) print("Third Number is: ", z) # taking two inputs at a time x, y = [int(x) for x in input("Enter two values: ").split()] print("First number is {} and second number is {}".format(x, y)) # taking multiple inputs at a time x = [int(x) for x in input("Enter multiple values: ").split()] print("Number of list is: ", x)
خروجی:
Enter two values: 5 10 First Number is: 5 Second Number is: 10 Enter three values: 5 10 15 First Number is: 5 Second Number is: 10 Third Number is: 15 Enter two values: 5 10 First number is 5 and second number is 10 Enter multiple values: 5 10 15 20 25 Number of list is: [5, 10, 15, 20, 25]
توجه: مثالهای بالا ورودیهایی را که با فاصله جدا شدهاند، دریافت میکنند. در صورتی که بخواهیم ورودیهایی را که با کاما (،) جدا شدهاند، دریافت کنیم، میتوانیم از روش زیر استفاده کنیم:
# taking multiple inputs at a time separated by comma x = [int(x) for x in input("Enter multiple value: ").split(",")] print("Number of list is: ", x)
روشهای مختلف ورودی در پایتون برای برنامهنویسی رقابتی
پایتون زبانی است که کار با آن بسیار راحت است، اما نقطه ضعف آن کندی سرعتش است. چون نسبت به زبانهایی مانند C++، C و جاوا، سرعت پایینتری دارد. در بسترهای برنامهنویسی آنلاین، اگر حد زمانی برای C++/C، مثلاً x باشد، معمولاً برای جاوا دو برابر این زمان (2x) و برای پایتون پنج برابر (5x) است. برای افزایش سرعت اجرای کد در مسائلی که به ورودی و خروجی بالایی نیاز دارند، زبانها روشهای مختلف ورودی و خروجی دارند. در این بخش از مقاله، به بررسی روشهای مختلف ورودی در پایتون برای برنامهنویسی رقابتی خواهیم پرداخت.
مثال:
به عنوان مثال، فرض کنید مسئلهای داریم که در آن باید مجموع N عدد وارد شده توسط کاربر را محاسبه کنیم. پس باید:
- یک عدد N را وارد کنید.
- N عدد ورودی که با فاصله در یک خط از هم جدا شدهاند را وارد کنید.
Input:
5
1 2 3 4 5
Output:
15
روشهای ورودی برای برنامهنویسی رقابتی در پایتون
در زیر روشهایی آورده شدهاند که میتوانیم برای ورودی سریعتر در پایتون استفاده کنیم:
- روش معمولی
- روش سریعتر با استفاده از تابع داخلی
- گرفتن ورودی کاربر در یک خط و ذخیره در متغیرهای جداگانه
- گرفتن ورودیهای کاربر به صورت لیستی از اعداد صحیح
- گرفتن ورودی رشته از کاربر
- افزودن یک پایپ بافر شده io (پایتون ۲.۷)
روش معمولی در پایتون (پایتون ورژن ۲.۷)
تابع ()raw_input یک آرگومان اختیاری از نوع prompt میگیرد. همچنین کاراکتر خط جدید پایانی را از رشتهای که برمیگرداند، حذف میکند.
تابع print تنها یک wrapper است که ورودیها را فرمت میکند (فاصله بین آرگومانها و خط جدید در انتها) و تابع write را برای یک شیء معین فراخوانی میکند.
# input N n = int(input()) # input the array arr = [int(x) for x in input().split()] # initialize variable summation = 0 # calculate sum for x in arr: summation += x # print answer print(summation)
روش سریعتر با استفاده از stdin و stdout داخلی (پایتون ۲.۷)
- از طرف دیگر، sys.stdin یک شیء فایل است. و مانند ایجاد هر شیء فایل دیگری است که میتوان برای خواندن ورودی از فایل ایجاد کرد. در این مورد، فایل یک بافر ورودی استاندارد خواهد بود.
- استفاده از stdout.write(‘D\n’) سریعتر از استفاده از print ‘D’ است.
- حتی سریعتر از آن نوشتن همه چیز به صورت یکجا و با استفاده از stdout.write(“”.join(list-comprehension)) است، اما این باعث میشود که استفاده از حافظه به اندازه ورودی وابسته باشد.
from sys import stdin, stdout # suppose a function called main() and # all the operations are performed def main(): # input via readline method n = stdin.readline() # array input similar method arr = [int(x) for x in stdin.readline().split()] #initialize variable summation = 0 # calculate sum for x in arr: summation += x # could use inbuilt summation = sum(arr) # print answer via write # write method writes only # string operations # so we need to convert any # data into string for input stdout.write(str(summation)) # call the main method if __name__ == "__main__": main()
تفاوت در زمان اجرا در حالتی که هر دستور 100 خط را پردازش کند:
Timing summary (100k lines each)
——————————–
Print : 6.040 s
Write to file : 0.122 s
Print with Stdout : 0.121 s
همانطور که تاکنون دیدهایم، گرفتن ورودی از سیستم استاندارد و دادن خروجی به سیستم استاندارد همیشه ایده خوبی برای بهبود کارایی کد است که همیشه در برنامهنویسی رقابتی نیاز است. اما صبر کنید! آیا دوست دارید هر زمان که به آنها نیاز دارید، این خطوط طولانی را بنویسید؟ پس، فایده استفاده از پایتون چیست؟
بیایید راهحل این مشکل را بررسی کنیم. آنچه ما میتوانیم انجام دهیم این است که توابع جداگانهای برای گرفتن ورودیهای انواع مختلف ایجاد کنیم و فقط زمانی که به آنها نیاز داریم، آنها را فراخوانی کنیم.
گرفتن ورودی کاربر داده شده در یک خط در متغیرهای جداگانه
فرض کنید ورودی به شکل زیر است
۵ ۷ ۱۹ ۲۰
ما میخواهیم متغیرهای جداگانهای برای ارجاع به آنها داشته باشیم. یعنی آنچه ما میخواهیم به شکل زیر است
a = ۵
b = ۷
c = ۱۹
d = ۲۰
برای انجام این کار، میتوانیم تابعی به نام ()get_ints ایجاد کنیم که در کد زیر داده شده است.
import sys def get_ints(): return map(int, sys.stdin.readline().strip().split()) a,b,c,d = get_ints()
با داشتن این تابع دیگر نیازی نیست این خط را بارها و بارها بنویسید. و فقط باید تابع ()get_ints را فراخوانی کنید تا ورودی را به این شکل دریافت کنید. در تابع get_ints ما از تابع map استفاده کردهایم.
گرفتن ورودیهای کاربر به صورت لیستی از اعداد صحیح
فرض کنید ورودی به شکل زیر باشد
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸
حال، میخواهیم که فقط یک متغیر، تمام این لیست از اعداد صحیح را نگه دارد. آنچه ما میخواهیم به شکل زیر است.
Arr = [۱, ۲, ۳, ۴, ۵, ۶, ۷, ۸]
در اینجا ما تابعی به نام ()get_list ایجاد خواهیم کرد که در زیر آمده است.
import sys def get_list(): return list(map(int, sys.stdin.readline().strip().split())) Arr = get_list()
حالا دیگر نیازی نیست که این خطوط را بارها و بارها بنویسید. و برای ساختن لیست مورد نظر، فقط باید تابع ()get_list را فراخوانی کنید تا بتوانید به این شکل ورودی دریافت کنید.
گرفتن ورودی رشته از کاربر
فرض کنید ورودی به شکل زیر باشد
datayad is the best platform to practice Coding.
اکنون، میخواهیم که یک متغیر ارجاعی واحد این رشته را نگه دارد. آنچه ما میخواهیم به شکل زیر است
string = “datayad is the best platform to practice coding.”
در اینجا ما تابعی به نام ()get_string ایجاد خواهیم کرد که در کد زیر آمده است.
import sys def get_string(): return sys.stdin.readline().strip() string = get_string()
حالا دیگر نیازی نیست که این خط را بارها و بارها بنویسید. و فقط باید تابع ()get_string را فراخوانی کنید تا بتوانید ورودی را به این شکل دریافت کنید.
افزودن یک بافر پایپ io در پایتون ۲.۷
– به سادگی، با افزودن کد بافر IO قبل از کد ارسالی خود، خروجی را سریعتر کنید.
– مزیت اشیاء io.BytesIO این است که آنها یک رابط مشترک (که معمولاً به عنوان یک شیء ‘شبیهفایل’ شناخته میشوند) پیادهسازی میکنند. اشیاء BytesIO دارای یک نشانگر داخلی هستند و برای هر فراخوانی به read(n)، نشانگر پیش میرود.
– ماژول atexit یک رابط ساده برای ثبت توابعی است، که قرار است هنگام بسته شدن عادی یک برنامه فراخوانی شوند. ماژول sys نیز یک قلاب (hook)، به شکل sys.exitfunc، ارائه میدهد، اما فقط یک تابع میتواند در آنجا ثبت شود. رجیستری atexit میتواند همزمان توسط چندین ماژول و کتابخانه استفاده شود.
# import libraries for input/ output handling # on generic level import atexit, io, sys # A stream implementation using an in-memory bytes # buffer. It inherits BufferedIOBase. buffer = io.BytesIO() sys.stdout = buffer # print via here @atexit.register def write(): sys.stdout.write(buffer.getvalue()) ##################################### # template ends n = int(input()) # input the array arr = [int(x) for x in input().split()] # initialize variable summation = 0 # calculate sum for x in arr: summation += x # print answer print(summation)
خلاصه
هنگام کار با حجم بزرگی از دادهها، معمولاً روش معمولی نمیتواند در محدوده زمانی معین و مورد نظر ما اجرا شود. روش ۲ به نگهداری حجم بزرگی از دادههای ورودی/خروجی کمک میکند. و روش ۳ سریعترین روش است. معمولاً، کار با فایلهای داده ورودی بزرگتر از ۲ یا ۳ مگابایت توسط روشهای ۲ و ۳ تسهیل میشود.
توجه: کدهای ذکر شده بالا برای پایتون ۲.۷ هستند، برای استفاده در نسخههای پایتون ۳، تنها کافی است ()raw_input را با سینتکس ()input پایتون ۳ جایگزین کنید. با این تغییر، کد باید به خوبی کار کنند.