| jupytext |
|
||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| kernelspec |
|
||||||||||||||||||||||||||||||||||||||||||||||
| translation |
|
(python_done_right)=
<div id="qe-notebook-header" align="right" style="text-align:right;">
<a href="https://quantecon.org/" title="quantecon.org">
<img style="width:250px;display:inline;" width="250px" src="https://assets.quantecon.org/img/qe-menubar-logo.svg" alt="QuantEcon">
</a>
</div>
ما تاکنون مطالب زیادی را با تمرکز بر مثالها، بهسرعت پوشش دادهایم.
اکنون بیایید برخی ویژگیهای اصلی پایتون را بهصورت نظاممندتر بررسی کنیم.
این روش شاید کمتر هیجانانگیز باشد، اما به درک بهتر جزئیات کمک میکند.
برنامههای کامپیوتری مجموعهای از انواع داده را مدیریت میکنند.
برای مثال، 1.5 یک عدد اعشاری (float) است، در حالی که 1 یک عدد صحیح (integer) محسوب میشود. در برنامه نویسی باید بین این دو نوع تفاوت قائل شوید، زیرا در حافظه به شکل متفاوتی ذخیره میشوند و عملیات ریاضی روی آنها فرق دارد.
- به عنوان نمونه، در بیشتر رایانهها محاسبات اعشاری توسط یک واحد خاص به نام واحد ممیز شناور (FPU) انجام میشود.
به طور کلی، اعداد اعشاری اطلاعات بیشتری دارند اما عملیات ریاضی روی اعداد صحیح سریعتر و دقیقتر است.
- پایتون چندین نوع دادهٔ داخلی دیگر نیز دارد، مثل رشتهها (strings) و فهرستها (lists).
بیایید بیشتر با آنها آشنا شویم.
(boolean)=
یک نوع از داده های اولیه، مقادیر بولی هستند که میتوانند فقط True (درست) یا False (نادرست) باشند.
x = True
x
میتوانیم نوع هر شیء در حافظه را با استفاده از تابع ()type بررسی کنیم:
type(x)
مثلاً در مثال زیر، پایتون مقدار عبارت سمت راست را محاسبه کرده و آن را به متغیر y نسبت میدهد:
y = 100 < 10
y
type(y)
در عبارات ریاضی، True معادل 1 و False معادل 0 در نظر گرفته میشود.
این ویژگی را محاسبات بولی (Boolean arithmetic) مینامند و اغلب در برنامه نویسی کاربردی است.
مثال های زیر نمونه هایی از این دست هستند:
x + y
x * y
True + True
bools = [True, True, False, True] # List of Boolean values
sum(bools)
داده های عددی از دیگر دادههای اولیه هستند.
همانطور که پیشتر با داده های صحیح (integer) و اعشاری (float) یا به اختصار intو float آشنا شدید؛ نوعی دیگر از داده های عددی اعداد مختلط (complex) نام دارند.
همانند مثال زیر:
x = complex(1, 2)
y = complex(2, 1)
print(x * y)
type(x)
پایتون چندین نوع پایه برای ذخیره سازی مجموعه هایی از داده ها(احتمالا ناهمگن) دارد.
پییشتر با {ref}لیستها <lists_ref> آشنا شدیم.
نوعی دیگر از آن، تاپل (tuple) است که «غیرقابل تغییر» (immutable) می باشد.
x = ('a', 'b') # Parentheses instead of the square brackets
x = 'a', 'b' # Or no brackets --- the meaning is identical
x
type(x)
اگر شیئی پس از ساخته شدن قابل تغییر نباشد، immutable است. در مقابل، اگر قابل ویرایش باشد، mutable نام دارد.
در پایتون لیست ها قابل تغییر هستند:
x = [1, 2]
x[0] = 10
x
اما tupleها قابل تغییر نیستند:
---
tags: [raises-exception]
---
x = (1, 2)
x[0] = 10
کمی بعدتر درباره نقش دادههای قابل تغییر و تغییرناپذیر بیشتر صحبت خواهیم کرد.
میتوان تاپلها (و لیستها) را به صورت زیر «بازکرد» (unpack) کرد:
integers = (10, 20, 30)
x, y, z = integers
x
y
در واقع شما قبلاً {ref}نمونهای از این را دیدهاید <tuple_unpacking_example>.
باز کردن tuple راحت است و ما اغلب از آن استفاده خواهیم کرد.
برای دسترسی به چندین عنصر از یک دنباله (یک لیست، یک tuple یا یک رشته)، میتوانید از نشانهگذاری slice در پایتون استفاده کنید.
برای مثال:
a = ["a", "b", "c", "d", "e"]
a[1:]
a[1:3]
قانون کلی این است که a[m:n] تعداد n - m عنصر را بازمیگرداند، که از a[m] شروع میشود.
اعداد منفی نیز مجاز هستند:
a[-2:] # Last two elements of the list
همچنین میتوانید از قالب [start:end:step] برای مشخص کردن گام برش استفاده کنید:
a[::2]
با استفاده از یک گام منفی، میتوانید دنباله را به صورت معکوس برگردانید:
a[-2::-1] # Walk backwards from the second last element to the first element
همان نشانهگذاری slice روی tupleها و رشتهها نیز کار میکند:
s = 'foobar'
s[-3:] # Select the last three elements
دو نوع دیگر از ظرف ها در پایتون،مجموعه ها (sets) و دیکشنری ها (dictionaries) هستند.
دیکشنریها بسیار شبیه لیستها هستند، با این تفاوت که آیتمها به جای شمارهگذاری، نامگذاری میشوند:
d = {'name': 'Frodo', 'age': 33}
type(d)
d['age']
در این مثال از دیکشنری، نام های 'name' و'age' کلیدها(keys) نامیده میشوند.
اشیایی که کلیدها به آنها ارجاع میدهند ('Frodo' و 33) مقادیر(Values) نامیده میشوند.
مجموعهها(sets) دسته های بدون ترتیب و بدون عنصر تکراری هستند و متدهای مجموعه،عملیات معمول مربوط به مجموعه ها را فراهم می کنند:
s1 = {'a', 'b'}
type(s1)
s2 = {'b', 'c'}
s1.issubset(s2)
s1.intersection(s2)
تابع ()set مجموعه ها را از دنباله ها می سازد:
s3 = set(('foo', 'bar', 'foo'))
s3
بیایید به طور خلاصه خواندن و نوشتن در فایلهای متنی را مرور کنیم.
با نوشتن شروع میکنیم:
f = open('newfile.txt', 'w') # Open 'newfile.txt' for writing
f.write('Testing\n') # Here '\n' means new line
f.write('Testing again')
f.close()
در اینجا:
- تابع سازنده داخلی
()openیک فایل برای نوشتن ایجاد می کند. - هم
()writeو هم()closeمتدهای فایل های ایجادشده هستند.
این فایلی که ساختهایم کجاست؟
به خاطر داشته باشید که پایتون مفهوم دایرکتوری فعلی (present working directory یا pwd) شما را حفظ می کند، که در Jupyter یا IPython می توان آن را از طریق دستور زیر پیدا کرد:
%pwd
اگر مسیری مشخص نشده باشد، پایتون در همین مکان(پوشه جاری)فایل را می نویسد.
ما همچنین میتوانیم با پایتون محتوای فایل newline.txt را به صورت زیر بخوانیم:
f = open('newfile.txt', 'r')
out = f.read()
out
print(out)
در واقع، رویکرد پیشنهادی در پایتون مدرن، استفاده از یک دستور with است تا اطمینان حاصل شود که فایلها به درستی دریافت و منتشر میشوند.
محدود کردن عملیات در همان بلوک نیز وضوح کد شما را بهبود میبخشد.
این نوع بلوک به طور رسمی به عنوان یک [*context*](https://realpython.com/python-with-statement/#the-with-statement-approach) شناخته میشود.
بیایید سعی کنیم دو مثال بالا را به عبارت with تبدیل کنیم.
ابتدا مثال نوشتن را تغییر میدهیم:
with open('newfile.txt', 'w') as f:
f.write('Testing\n')
f.write('Testing again')
توجه کنید که نیازی به فراخوانی متد ()close نداریم زیرا بلوک with تضمین میکند که جریان(stream) در پایان بلوک بسته شود.
با کمی تغییر، میتوانیم فایلها را با استفاده از دستور with نیز بخوانیم:
with open('newfile.txt', 'r') as fo:
out = fo.read()
print(out)
اکنون فرض کنید که میخواهیم ورودی را از یک فایل بخوانیم و خروجی را در فایل دیگری بنویسیم.
در اینجا نحوه انجام این کار در حالی که به درستی منابع را دریافت و به سیستم عامل بازمیگردانیم با استفاده از عبارات with آمده است:
with open("newfile.txt", "r") as f:
file = f.readlines()
with open("output.txt", "w") as fo:
for i, line in enumerate(file):
fo.write(f'Line {i}: {line} \n')
فایل خروجی به صورت زیر خواهد بود:
with open('output.txt', 'r') as fo:
print(fo.read())
میتوانیم مثال بالا را ساده کنیم با این کار که دو دستور with را در یک خط قرار دهیم:
with open("newfile.txt", "r") as f, open("output2.txt", "w") as fo:
for i, line in enumerate(f):
fo.write(f'Line {i}: {line} \n')
فایل خروجی یکسان خواهد بود:
with open('output2.txt', 'r') as fo:
print(fo.read())
فرض کنید میخواهیم به جای بازنویسی فایل موجود به نوشتن در آن ادامه دهیم.
میتوانیم حالت را به a تغییر دهیم که مخفف حالت append است:
with open('output2.txt', 'a') as fo:
fo.write('\nThis is the end of the file')
with open('output2.txt', 'r') as fo:
print(fo.read())
توجه کنید که ما فقط حالتهای `r`، `w` و `a` را در اینجا پوشش دادیم که رایجترین حالتهای مورد استفاده هستند.
پایتون [حالتهای متنوعی](https://www.geeksforgeeks.org/python/reading-writing-text-files-python/) ارائه میدهد که میتوانید با آنها آزمایش کنید.
توجه کنید که اگر newfile.txt در دایرکتوری کاری فعلی نباشد، فراخوانی ()open با خطا مواجه میشود.
در این حالت، میتوانید فایل را به pwd منتقل کنید یا مسیر کامل فایل را مشخص کنید:
:class: no-execute
f = open('insert_full_path_to_file/newfile.txt', 'r')
(iterating_version_1)=
یکی از مهمترین وظایف در علوم کامپیوتر، عبور گامبهگام از یک دنباله از دادهها و انجام یک عمل مشخص است.
یکی از نقاط قوت پایتون رابط کاربری ساده و انعطافپذیر آن برای این نوع تکرار از طریق حلقه for است.
بسیاری از اشیاء پایتون "قابل تکرار" هستند، به این معنی که میتوان روی آنها حلقه(loop) زد.
برای ارائه یک مثال، بیایید فایل us_cities.txt را بنویسیم که شهرهای ایالات متحده و جمعیت آنها را فهرست میکندو در پوشه کاری فعلی ذخیره می گردد:
(us_cities_data)=
%%writefile us_cities.txt
new york: 8244910
los angeles: 3819702
chicago: 2707120
houston: 2145146
philadelphia: 1536471
phoenix: 1469471
san antonio: 1359758
san diego: 1326179
dallas: 1223229
در اینجا writefile%% یک IPython cell magic است.
فرض کنید میخواهیم اطلاعات را با بزرگ کردن نامها و اضافه کردن ویرگول برای نشان دادن هزارگان خواناتر کنیم.
برنامه زیر دادهها را میخواند و تبدیل را انجام میدهد:
data_file = open('us_cities.txt', 'r')
for line in data_file:
city, population = line.split(':') # Tuple unpacking
city = city.title() # Capitalize city names
population = f'{int(population):,}' # Add commas to numbers
print(city.ljust(15) + population)
data_file.close()
در اینجا 'f یک f-string است که برای درج متغیرها در رشتهها استفاده میشود.
قالببندی مجدد هر خط نتیجه سه متد مختلف رشته است که بررسی جزئیات آنها را میتوان برای بعد گذاشت.
بخش جالب این برنامه برای ما خط 2 است که نشان میدهد:
- شیء فایل
data_fileقابل تکرار است، به این معنی که میتوان آن را در سمت راستinدر یک حلقهforقرار داد. - تکرار به صورت خط به خط از فایل عبور میکند.
این همان چیزی است که منجر به سینتکس ساده و کاربردی نمایش داده شده در برنامه ما می شود.
بسیاری از انواع دیگر اشیاء قابل تکرار هستند و ما بعداً درباره برخی از آنها بحث خواهیم کرد.
یکی از چیزهایی که ممکن است متوجه شده باشید این است که پایتون تمایل دارد مستقیما روی آیتم ها حلقه بزنیم، بدون اینکه شماره موقعیت(یا همان ایندکس) هر آیتم را به صورت صریح استفاده کنیم.
برای مثال:
x_values = [1, 2, 3] # Some iterable x
for x in x_values:
print(x * x)
به این ترجیح داده میشود:
for i in range(len(x_values)):
print(x_values[i] * x_values[i])
وقتی این دو گزینه را مقایسه میکنید، میتوانید ببینید چرا اولی ترجیح داده میشود.
پایتون امکاناتی دارد که کار با حلقه ها را بدون ایندکس ساده میکند.
یکی از این امکانات ()zip است که به شما اجازه میدهد دو لیست را هم زمان با هم طی کنید و هر بار یک جفت از عناصر آنها را بگیرید.
برای مثال، کد زیر را اجرا کنید:
countries = ('Japan', 'Korea', 'China')
cities = ('Tokyo', 'Seoul', 'Beijing')
for country, city in zip(countries, cities):
print(f'The capital of {country} is {city}')
تابع ()zip همچنین برای ایجاد دیکشنریها کاربردی است، برای مثال:
names = ['Tom', 'John']
marks = ['E', 'F']
dict(zip(names, marks))
اگر واقعاً به شماره موقعیت یا ایندکس از یک لیست نیاز داریم، یکی از گزینهها استفاده از ()enumerate است.
برای درک اینکه ()enumerate چه کاری انجام میدهد، مثال زیر را در نظر بگیرید:
letter_list = ['a', 'b', 'c']
for index, letter in enumerate(letter_list):
print(f"letter_list[{index}] = '{letter}'")
(list_comprehensions)=
همچنین میتوانیم کد تولید لیست مقادیر تصادفی را با استفاده از چیزی به نام خلاصه لیست(list comprehension) به طور قابل توجهی ساده کنیم.
خلاصه لیستها یک ابزار زیبای پایتون برای ایجاد لیست هستند.
مثال زیر را در نظر بگیرید، که خلاصه لیست در سمت راست خط دوم است:
animals = ['dog', 'cat', 'bird']
plurals = [animal + 's' for animal in animals]
plurals
این یک مثال دیگر است:
range(8)
doubles = [2 * x for x in range(8)]
doubles
بسیاری از انواع مختلف عبارات وجود دارند که نتیجهشان با یکی از مقادیر Boolean (یعنی True یا False) نشان داده میشوند.
یکی از رایج ترین این عبارت ها، عملگرهای مقایسهای هستند، مانند:
x, y = 1, 2
x < y
x > y
یکی از ویژگیهای خوب پایتون این است که میتوان نامساویها را به صورت پشت سر هم (Chain) در یک عبارت نوشت.
1 < 2 < 3
1 <= 2 <= 3
همانطور که قبلاً دیدیم، هنگام آزمایش برابری از == استفاده میکنیم:
x = 1 # Assignment
x == 2 # Comparison
برای "نابرابر" از != استفاده کنید:
1 != 2
توجه کنید که هنگام آزمایش شرایط، میتوانیم از هر عبارت معتبر پایتون استفاده کنیم:
x = 'yes' if 42 else 'no'
x
x = 'yes' if [] else 'no'
x
اینجا چه اتفاقی میافتد؟
قانون این است:
- عباراتی که به صفر، دنبالهها یا ظرف های خالی (رشتهها، لیستها و غیره) و
Noneتشخیص داده میشوند، همه معادلFalseهستند.- به عنوان مثال،
[]و()در یک شرطifمعادلFalseهستند
- به عنوان مثال،
- همه مقادیر دیگر معادل
Trueهستند.- به عنوان مثال،
42در یک شرطifمعادلTrueاست
- به عنوان مثال،
میتوانیم عبارات را با استفاده از and، or و not ترکیب کنیم.
اینها ربطدهندههای منطقی استاندارد (عطف، فصل و نفی) هستند.
1 < 2 and 'f' in 'foo'
1 < 2 and 'g' in 'foo'
1 < 2 or 'g' in 'foo'
not True
not not True
به خاطر بسپارید:
P and QزمانیTrueاست که هر دوTrueباشند، در غیر این صورتFalseP or QزمانیFalseاست که هر دوFalseباشند، در غیر این صورتTrue
همچنین میتوانیم از ()all و ()any برای آزمایش دنبالهای از عبارات استفاده کنیم:
all([1 <= 2 <= 3, 5 <= 6 <= 7])
all([1 <= 2 <= 3, "a" in "letter"])
any([1 <= 2 <= 3, "a" in "letter"])
* `()all` زمانی `True` برمیگرداند که *همه* مقادیر/عبارات boolean در دنباله `True` باشند
* `()any` زمانی `True` برمیگرداند که *هر* مقدار/عبارت boolean در دنباله `True` باشد
داشتن یک سبک کدنویسی سازگار و استفاده از مستندسازی میتواند کد را خواناتر و نگهداری و توسعه آن را آسان تر کند.
میتوانید با تایپ کردن import this در خط فرمان با فلسفه برنامهنویسی پایتون آشنا شوید.
پایتون در کنار موارد دیگر، تأکید زیادی بر یکدست بودن و ثبات در سبک برنامه نویسی دارد.
همه ما ضربالمثل « سازگاری و ذهنهای کوچک » را شنیدهایم.
در برنامهنویسی، همانند ریاضیات، کاملا برعکس است.
- یک مقاله ریاضی که در آن نمادهای
$\cup$ و$\cap$ معکوس شده باشند، خواندن آن بسیار سخت خواهد بود، حتی اگر نویسنده در صفحه اول به شما بگوید.
در پایتون، سبک استاندارد در PEP8 بیان شده است.
(گاهی اوقات در این درس ها از PEP8 منحرف خواهیم شد تا نمادگذاری ریاضی را بهتر رعایت کنیم)
(Docstrings)=
پایتون سیستمی برای اضافه کردن توضیحات به ماژولها، کلاسها، توابع و غیره دارد که داکاسترینگ(docstring) نامیده میشود.
نکته خوب درباره داکاسترینگها این است که در زمان اجرا در دسترس هستند.
اجرای این کد را امتحان کنید:
def f(x):
"""
This function squares its argument
"""
return x**2
پس از اجرای این کد، داکاسترینگ در دسترس است:
f?
:class: no-execute
Type: function
String Form:<function f at 0x2223320>
File: /home/john/temp/temp.py
Definition: f(x)
Docstring: This function squares its argument
f??
:class: no-execute
Type: function
String Form:<function f at 0x2223320>
File: /home/john/temp/temp.py
Definition: f(x)
Source:
def f(x):
"""
This function squares its argument
"""
return x**2
با یک علامت سوال داکاسترینگ را میآوریم، و با دو علامت سوال کد منبع را نیز دریافت میکنیم.
میتوانید قراردادهای داکاسترینگ را در PEP257 پیدا کنید.
تمرینهای زیر را حل کنید.
(برای برخی از تمرینات، تابع داخلی ()sum کاربردی است).
:label: pyess_ex1
قسمت 1: با توجه به دو لیست یا tuple عددی x_vals و y_vals با طول برابر، ضرب داخلی آنها را با استفاده از ()zip محاسبه کنید.
قسمت 2: در یک خط، تعداد اعداد زوج در بازه 0,...,99 را بشمارید.
قسمت 3: با توجه به pairs = ((2, 5), (4, 2), (9, 8), (12, 10))، تعداد جفتهای (a, b) را بشمارید که در آن هم a و هم b زوج باشند.
:class: dropdown
`x % 2` اگر `x` زوج باشد 0 برمیگرداند، در غیر این صورت 1.
:class: dropdown
راهحل قسمت 1:
یک راهحل ممکن میتواند این باشد:
x_vals = [1, 2, 3]
y_vals = [1, 1, 1]
sum([x * y for x, y in zip(x_vals, y_vals)])
این روش هم برای این سوال کار میکند:
sum(x * y for x, y in zip(x_vals, y_vals))
راهحل قسمت 2:
یک راهحل ممکن میتواند این باشد:
sum([x % 2 == 0 for x in range(100)])
این روش هم برای این سوال کار میکند:
sum(x % 2 == 0 for x in range(100))
برخی از جایگزینهای کمتر طبیعی که با این حال به نشان دادن انعطافپذیری خلاصه لیستها کمک میکنند عبارتند از:
len([x for x in range(100) if x % 2 == 0])
و
sum([1 for x in range(100) if x % 2 == 0])
راهحل قسمت 3:
یک راه حل این است:
pairs = ((2, 5), (4, 2), (9, 8), (12, 10))
sum([x % 2 == 0 and y % 2 == 0 for x, y in pairs])
:label: pyess_ex2
چندجملهای زیر را در نظر بگیرید:
:label: polynom0
p(x)
= a_0 + a_1 x + a_2 x^2 + \cdots a_n x^n
= \sum_{i=0}^n a_i x^i
تابع p را بنویسید به طوری که p(x, coeff) مقدار را در {eq}polynom0 با توجه به نقطه x و لیست ضرایب coeff (
سعی کنید از ()enumerate در حلقه خود استفاده کنید.
:class: dropdown
یک راهحل این است:
def p(x, coeff):
return sum(a * x**i for i, a in enumerate(coeff))
p(1, (2, 4))
:label: pyess_ex3
تابعی بنویسید که یک رشته را به عنوان آرگومان میگیرد و تعداد حروف بزرگ در رشته را برمیگرداند.
:class: dropdown
`'foo'.upper()` مقدار `'FOO'` را برمیگرداند.
:class: dropdown
یک راهحل این است:
def f(string):
count = 0
for letter in string:
if letter == letter.upper() and letter.isalpha():
count += 1
return count
f('The Rain in Spain')
یک راه حل جایگزین و پایتونی تر:
def count_uppercase_chars(s):
return sum([c.isupper() for c in s])
count_uppercase_chars('The Rain in Spain')
:label: pyess_ex4
تابعی بنویسید که دو دنباله `seq_a` و `seq_b` را به عنوان آرگومان میگیرد و `True` را برمیگرداند اگر هر عنصر در `seq_a` همچنین عنصری از `seq_b` باشد، در غیر این صورت `False`.
* منظور از "دنباله" یک لیست، یک tuple یا یک رشته است.
* تمرین را بدون استفاده از [setها](https://docs.python.org/3/tutorial/datastructures.html#sets) و متدهای set انجام دهید.
:class: dropdown
یک راهحل این است:
def f(seq_a, seq_b):
for a in seq_a:
if a not in seq_b:
return False
return True
# == test == #
print(f("ab", "cadb"))
print(f("ab", "cjdb"))
print(f([1, 2], [1, 2, 3]))
print(f([1, 2, 3], [1, 2]))
یک راه حل جایگزین، پایتونیتر با استفاده از ()all:
def f(seq_a, seq_b):
return all([i in seq_b for i in seq_a])
# == test == #
print(f("ab", "cadb"))
print(f("ab", "cjdb"))
print(f([1, 2], [1, 2, 3]))
print(f([1, 2, 3], [1, 2]))
البته، اگر از نوع داده sets استفاده کنیم، راهحل سادهتر است:
def f(seq_a, seq_b):
return set(seq_a).issubset(set(seq_b))
:label: pyess_ex5
وقتی کتابخانههای عددی را پوشش دهیم، خواهیم دید که آنها شامل جایگزینهای زیادی برای درونیابی و تقریب تابع هستند.
با این حال، بیایید روتین تقریب تابع خودمان را به عنوان یک تمرین بنویسیم.
به طور خاص، بدون استفاده از هیچ import، تابعی `linapprox` بنویسید که به عنوان آرگومانها میگیرد
* یک تابع `f` که بازهای $[a, b]$ را به $\mathbb R$ نگاشت میکند.
* دو اسکالر `a` و `b` که حدود این بازه را مشخص میکنند.
* یک عدد صحیح `n` که تعداد نقاط شبکه را تعیین میکند.
* یک عدد `x` که `a <= x <= b` را برآورده میکند.
و [درونیابی خطی تکهای](https://en.wikipedia.org/wiki/Linear_interpolation) `f` را در `x`، بر اساس `n` نقطه شبکه با فاصله یکسان `a = point[0] < point[1] < ... < point[n-1] = b` برمیگرداند.
برای وضوح تلاش کنید، نه کارایی.
:class: dropdown
یک راهحل این است:
def linapprox(f, a, b, n, x):
"""
Evaluates the piecewise linear interpolant of f at x on the interval
[a, b], with n evenly spaced grid points.
Parameters
==========
f : function
The function to approximate
x, a, b : scalars (floats or integers)
Evaluation point and endpoints, with a <= x <= b
n : integer
Number of grid points
Returns
=======
A float. The interpolant evaluated at x
"""
length_of_interval = b - a
num_subintervals = n - 1
step = length_of_interval / num_subintervals
# === find first grid point larger than x === #
point = a
while point <= x:
point += step
# === x must lie between the gridpoints (point - step) and point === #
u, v = point - step, point
return f(u) + (x - u) * (f(v) - f(u)) / (v - u)
:label: pyess_ex6
با استفاده از سینتکس خلاصه لیست، میتوانیم حلقه در کد زیر را ساده کنیم.
import numpy as np
rng = np.random.default_rng()
n = 100
ϵ_values = []
for i in range(n):
e = rng.standard_normal()
ϵ_values.append(e)
:class: dropdown
یک راهحل این است:
rng = np.random.default_rng()
n = 100
ϵ_values = [rng.standard_normal() for i in range(n)]