مدرسه زبان برنامه‌نویسی PYTHON

وبلاگی جهت معرفی - آموزش و تحلیل زبان برنامه نویسی ‍پایتون

مدرسه زبان برنامه‌نویسی PYTHON

وبلاگی جهت معرفی - آموزش و تحلیل زبان برنامه نویسی ‍پایتون

۵۰ مطلب در تیر ۱۳۹۸ ثبت شده است

در قسمت های گذشته با exception ها به طور غیر مستقیم برخورد داشته اید. این مدل زمانی اتفاق میافتد که عملکردی به خاطر ورودی اشتباه انجام شود.وقتی این حالت اتفاق میافتد همراه با اخطار برنامه کاملا متوقف می شود.

کد زیر نحوه عملکرد و خروجی یک Exception را هنگام تقسیم عددی بر صفر نشان می دهد.

num1 = 7
num2 = 0
print(num1/num2)

خروجی:

>>>
ZeroDivisionError: division by zero
>>>

استثنا و یا exception ها در موارد متعددی اتفاق میافتند.
چند مورد از متداول ترین آنها شمامل موارد زیر است:
ImportError:زمانی که درج ماژول به اشتباه صورت گیرد
IndexError: زمانی که لیستی با یک عدد نشانگر خارج از اعضا نشان داده شود
NameError: زمان استفاده از یک متغیر نا معلوم
SyntaxError: هنگام اشتباه در کد نویسی
TypeError: صدا زدن یک مقدار با نوع اشتباه در یک تابع
ValueError: صدا زدن یک مقدار درون تابع با نوع درست اما مقدار اشتباه

برای رسیدگی به استثنا ها، و هنگام فراخوانی یک exception، می توانید از دستور try/ exception استفاده کنید.
بلوک try حاوی کدیست که ممکن است exception را برانگیزد. اگر این exception اتفاق افتد، کد در بلوک try اجرا نمی شود و کد در بلوک except اجرا می شود. اگر هیچ خطایی رخ نداده باشد، کد در بلوک except اجرا نمی شود.
برای مثال:

try:
   num1 = 7
   num2 = 0
   print (num1 / num2)
   print("Done calculation")
except ZeroDivisionError:
   print("An error occurred")
   print("due to zero division")

خروجی:

>>>
An error occurred
due to zero division
>>>

نکته:در کد بالا پیغام خطا نوع exception را مشخص می کند.

Exception Handling
یک کد حاوی try می تواند چندین حالت متفاوتی داشته باشد، به جز بلوک هایی که بتواند exception های مختلف را مدیریت کند
exception چندگانه همچنین می تواند در یک تک جز به بلوک با استفاده از پرانتز قرار داده شود.

try:
   variable = 10
   print(variable + "hello")
   print(variable / 2)
except ZeroDivisionError:
   print("Divided by zero")
except (ValueError, TypeError):
   print("Error occurred")

خروجی:

>>>
Error occurred
>>>

except ها می توانند بدون هیچ ساختار مشخصی نیز استفاده شوند. این ها باید به ندرت مورد استفاده قرار گیرد، زیرا می توانند اشتباهات غیرمنتظره ای را بدست آورند و اشتباهات برنامه نویسی را پنهان کنند.
مثلا:

try:
   word = "spam"
   print(word / 0)
except:
   print("An error occurred")

خروجی:

>>>
An error occurred
>>>

نکته:استفاده از exception handeling بسیار کارآمد است به خصوص زمانی که ورودی از جانب کاربر اشتباه باشد.

۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۲۲:۳۹
سعید دامغانیان

ماژول ها

سه نوع اصلی از ماژول ها در پایتون وجود دارد،آنهایی که خودتان می نویسید، آنهایی که از منابع خارجی نصب می کنید ودر آخز آنهایی که با پایتون از پیش نصب شده اند.
آخرین نوع کتابخانه استاندارد نامیده می شود و شامل بسیاری از ماژول های مفید می باشد.برخی از ماژول های مفید کتابخانه استاندارد عبارتند از:stringredatetimemathrandomosmultiprocessingsubprocess,socketemailjsondoctestunittestpdbargparse ,sys.

وظایفی که می تواند توسط کتابخانه استاندارد انجام شود عبارتند از تجزیه رشته، سریال سازی داده ها، آزمایش، اشکال زدایی و دستکاری تاریخ، ایمیل، استدلال خط فرمان و خیلی بیشتر!

نکته:کتابخانه استاندارد گسترده پایتون یکی از مهمترین نقاط قوت آن به عنوان یک زبان است.

کتابخانه های استاندارد

برخی از ماژولهای کتابخانه استاندارد در پایتون نوشته شده و برخی از آنها در C نوشته شده است.
اکثر آنها در تمام سیستم عاملها قابل دسترسی هستند، اما برخی از آنها برای ویندوز یا یونیکس خاص هستند.

نکته: ما تمام ماژول های موجود در کتابخانه استاندارد را پوشش نمی دهیم. به سادگی بیش از حد وجود دارد. مستندات کامل کتابخانه استاندارد در سایت اینترنتی www.python.org در دسترس است.

ماژول ها

خیلی از ماژول های قابل نصب که توسط دیگران نوشته شده اند را می توان در قالبی از پکیج های پایتون یافت.(Python Package Index (PYPI))
بهترین راه برای نصب این ماژول ها، استفاده از یک برنامه به نام pip است.
(برای نصب pip کافیست که فایل پیسوت شده به نام را دانلود و با دو بار کلیک بر روی آن اجرا نمایید، در اصل هدف اجرا شدن کد های نوشته شده در فایل get-pip.py هستش پس یا فایل رو باز کنید و اجرا کنید و یا در دایرکتوری فایل دانلود شده دستور python get-pip.py رو اجرا کنید تا پکیج نصب بشه. لطفا به نسخه پایتون نصب شده برای اجرای کد دقت کنید)

این به طور پیش فرض با توزیع های مدرن پایتون نصب می شود. اگر شما آن را ندارید، نصب آنلاین آسان است.هنگامی که شما آن را دارید، نصب کتابخانه ها از PyPI آسان است. به دنبال نام کتابخانه ای که می خواهید نصب کنید، به خط فرمان بروید (برای ویندوز Command Prompt) و فرمان pip install library_name را وارد کنید تا نصب شود. پس از انجام این کار، کتابخانه را وارد کنید و از آن در کد خود استفاده کنید.

استفاده از pip روش استاندارد نصب کتابخانه ها در اکثر سیستم عامل ها است، اما برخی از کتابخانه ها دارای دو نسخه ی مجتمع شده برای ویندوز هستند. این فایل های اجرایی نرمال است که به شما اجازه می دهد کتابخانه ها را با GUI نصب کنید همانطور که برنامه های دیگر را نصب می کنید.

نکته: مهم است که دستورات pip را در خط فرمان وارد کنید، نه مفسر پایتون.

۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۰۵:۰۵
سعید دامغانیان

ماژول ها Modules

ماژول در پایتون قطعاتی از کد هستند که افراد دیگر برای انجام وظایف مشترک مانند تولید اعداد تصادفی، انجام عملیات ریاضی و غیره نوشته اند.

راه اصلی برای استفاده از یک ماژول، افزودن import module_name در بالای کد خود است و سپس با استفاده از module_name.var برای دسترسی به توابع و مقادیر با نام var در ماژول است.
به عنوان مثال، در مثال زیر از ماژول random برای تولید اعداد تصادفی استفاده می کند:

import random

for i in range(5):
   value = random.randint(1, 6)
   print(value)

خروجی:

>>>
2
3
6
5
4
>>>

نکته:کد از تابع randint تعریف شده در ماژول تصادفی برای چاپ 5 عدد تصادفی در محدوده 1 تا 6 استفاده می کند.

نوع دیگری از حالت import وجود دارد و برای زمانی است که شما می خواهید یک تابع خاص از ماژول را مورد استفاده قرار دهید. مدل استفاده آن به شکل from module_name import var خواهد بود که var تابع داخل ماژول را مشخص می کند.

from math import pi

print(pi)

خروجی:

>>>
3.141592653589793
>>>

همچنین می توانید از comma باری جدا سازی توابع بهره ببرید.

from math import pi, sqrt

نکته:* همه اشیا را از یک ماژول وارد می کند. به عنوان مثال:from math import *
این کار توصیه شده است، زیرا متغیرها را در کد خود با متغیرهای موجود در ماژول خارجی اشتباه می گیرد.

تلاش برای وارد کردن یک ماژول که در دسترس نیست، باعث ایجاد کردن خطا می شود.

import some_module

خروجی:

>>>
ImportError: No module named 'some_module'
>>>

شما می توانید یک ماژول یا یک شی را تحت نام دیگری با استفاده از کلمه کلیدی وارد کنید. این عمدتا زمانی مورد استفاده قرار می گیرد که یک ماژول یا یک شیء دارای نام طولانی یا گیج کننده است.
مثلا:

from math import sqrt as square_root
print(square_root(100))

خروجی:

>>>
10.0
>>>
۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۰۵:۰۳
سعید دامغانیان

توابع به عنوان شئ

اگرچه آنها به صورت متفاوتی از متغیرهای عادی ایجاد می شوند، توابع مانند هر نوع دیگری در پایتون دارای ارزش هستند.
می توانند به متغیر ها بست داده شوند و یا دوباره مقدار دهی شوند و مجدد در قسمت دیگری از کد فرا خوانده شوند.

def multiply(x, y):
   return x * y

a = 4
b = 7
operation = multiply
print(operation(a, b))

خروجی:

>>>
28
>>>

نکته: مثال بالا توابع را به یک عملیات متغیر اختصاص داده است. در حال حاضر، نام عملیات نیز می تواند برای انجام عملایت صدا زده شود و مورد استفاده قرار گیرد.

توابع نیز می توانند بعنوان استدلال های دیگر توابع استفاده شوند.

def add(x, y):
  return x + y

def do_twice(func, x, y):
  return func(func(x, y), func(x, y))

a = 5
b = 10

print(do_twice(add, a, b))

خروجی:

>>>
30
>>>

نکته: همانطور که می بینید تابع do_twice یک تابع دیگر را به عنوان آرگومان ورودی دریافت می کند و در بدنه کد خود استفاده می کند.

۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۰۵:۰۱
سعید دامغانیان

کامنت گذاری در پایتون

نظرات حاوی نکات مربوط به کد مورد استفاده برای درک بهتر آن است. آنها بر نحوه اجرا کد تاثیر نمی گذارد.

در پایتون، یک نظر با قرار دادن یک octothorpe ایجاد می شود (در غیر این صورت به عنوان علامت شمارشی یا علامت هش: # نام برده می شود). تمام متن پس از آن در آن خط نادیده گرفته می شود.
مثلا:

x = 365
y = 7
# this is a comment

print(x % y) # find the remainder
# print (x // y)
# another comment

خروجی:

>>>
1
>>>

نکته:پایتون نظر چند منظوره عمومی ندارد، همانطور که زبان های برنامه نویسی مانند C.

Docstrings (رشته های مستند سازی) هدف مشترکی را در ایجاد نظرات ارائه می دهند، زیرا آنها برای توضیح کد طراحی شده اند.
به عنوان مثال:

def shout(word):
  """
  Print a word with an
  exclamation mark following it.
  """
  print(word + "!")
    
shout("spam")

خروجی:

>>>
spam!
>>>

نکته:بر خلاف نظرات متعارف، دایرکتوری ها در طول زمان اجرای برنامه حفظ می شوند. این موضوع به برنامه نویس برای بازبینی این نظرات در زمان اجرا کمک شایانی خواهد کرد.

۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۰۴:۵۹
سعید دامغانیان

تابع در پایتون

مجدد نویسی

استفاده مجدد کد یک بخش بسیار مهمی از برنامه نویسی در هر زبان است. افزایش حجم کد باعث سخت شدن ایجاد تغییرات و یا تشخیص عیب آن می شود.
برای یک پروژه برنامه نویسی بزرگ ضروریست تا از اصولی استفاده کنیم که منجر به مختصر سازی و همچنین دسترسی راحت تر به بخش های مختلف را ایجاد کنیم.همچنین می بایست از اصل تکرار کد ممنوع پیروی کنیم.ما قبلا یکی از راههای انجام این کار را مورد بررسی قرار دادیم: با استفاده از حلقه ها. در این قسمت، دو مورد دیگر را نیز بررسی خواهیم کرد: توابع و ماژول ها.

تذکر:گفته می شود که کد تکراری نامناسب با اصل WET مطابقت دارد که «Write Everything Twice» است یا ما از تایپ کردن لذت می بریم.

شما قبلا از توابع در درس های قبلی استفاده کرده اید.
هر بیانیه ای که شامل کلمه ای است که بعد از آن اطلاعات در پرانتز قرار می گیرد، یک فراخوانی تابع است.
بعضی از نمونه هایی که قبلا دیده اید، در اینجا آمده است:

print("Hello world!")
range(2, 20)
str(12)
range(10, 20, 3)

نکته:کلمات در مقابل پرانتز نام های تابع هستند، و مقادیر جدا شده با کام در داخل پرانتزها، استدلال های عملکرد هستند.

ساخت تابع

اولین قدم در ساخت تابع

علاوه بر استفاده از توابع از پیش تعریف شده، می توانید با استفاده از دستور def، توابع خود را ایجاد کنید.
در اینجا یک مثال از تابع به نام my_func است. هیچ مقداری نمیگیرد و فقط سه بار یک خروجی را چاپ می کند. این تابع با نام مشخص تعریف شده است و سپس فراخوانده می شود. کد های داخل تابع فقط زمانی اجرا می شود که تابع فراخوانده می شود.

def my_func():
   print("spam")
   print("spam")
   print("spam")

my_func()

خروجی:

>>>
spam
spam
spam
>>>

نکته:بلوک کد در هر تابع با یک کولون (:) آغاز می شود و از هم جدا است.

قبل از اینکه آنها را فراخوانی کنید، باید توابع را تعریف کنید، همانطور که قبل از استفاده از متغیرها باید متغیرها را اختصاص دهید.

>>hello()

def hello():
    print("Hello world!")

خروجی:

>>>>>
NameError: name 'hello' is not defined
>>>

آرگومان (argument) در تابع

توابع حاوی آرگومان یا argument

تمام تعاریف تابع که تا به حال مورد بررسی قرار گرفته اند توابع استدلال صفر است که با پرانتزهای خالی نامیده می شوند.
با این حال، اکثر توابع استدلال می کنند.
مثال زیر یک تابع را تعریف می کند که یک استدلال را می گیرد:

def print_with_exclamation(word):
   print(word + "!")
    
print_with_exclamation("spam")
print_with_exclamation("eggs")
print_with_exclamation("python")

خروجی:

>>>
spam!
eggs!
python!
>>>

نکته:همانطور که می بینید آرگومان در داخل پرانتز قرار گرفته است.

شما همچنین می توانید توابع را با بیش از یک استدلال تعریف کنید. آنها را با کاما جدا کنید.

def print_sum_twice(x, y):
   print(x + y)
   print(x + y)

print_sum_twice(5, 8)

خروجی:

>>>
13
13
>>>

آرگومان های عملکرد را می توان به عنوان متغیرهای درون تعریف تابع استفاده کرد. با این حال، آنها نمی توانند در خارج از تعریف تابع اشاره داشته باشند. این نیز در مورد متغیرهای دیگر ایجاد شده در داخل یک تابع استفاده می شود.

def function(variable):
   variable += 1
   print(variable)

function(7)
print(variable)

خروجی:

>>>
8

NameError: name 'variable' is not defined
>>>

نکته:از لحاظ فنی، پارامترهای متغیر در یک تعریف تابع هستند، و استدلال ها ارزش هایی هستند که در هنگام فراخوانی توابع در پارامترها قرار می گیرند.

بازگشت پاسخ از تابع return

بعضی توابع، مقادیری مانند int یا str، را می توانند بازگردانند تا بعدا استفاده شود.
برای انجام این کار شما می توانید از عبارت return استفاده کنید.

به عنوان مثال:

def max(x, y):
    if x >=y:
        return x
    else:
        return y
        
print(max(4, 7))
z = max(8, 5)
print(z)

خروجی:

>>>
7
8
>>>

نکته:از حالت Return در خارج از تابع نمی توان استفاده کرد

هنگامی که شما مقداری را از تابع return می کنید بلافاصله تابع متوقف می شود. هر کدی بعد از return که باشد اجرا نخواهد شد.

def add_numbers(x, y):
  total = x + y
  return total
  print("This won't be printed")

print(add_numbers(4, 5))

خروجی:

>>>
9
>>>
۰ نظر موافقین ۰ مخالفین ۰ ۰۶ تیر ۹۸ ، ۰۴:۵۷
سعید دامغانیان

ماشین حساب ساده

این درس در مورد پروژه ای ساده در پایتون است: یک ماشین حساب ساده.
هر بخش متفاوتی از برنامه را توضیح می دهد. که به صورت یک دسته از کد به هم مرتبط در آمده و بینشی از نحوه ساخت یک برنامه ساده را نشان خواهد داد.
بخش اول منوی کلی است.
در این حالت تا زمانی که از کاربر ورودی quit را نگیرد از کاربر ورودی برای عملکرد های متفاوت را دریافت خواهد کرد.

while True:
   print("Options:")
   print("Enter 'add' to add two numbers")
   print("Enter 'subtract' to subtract two numbers")
   print("Enter 'multiply' to multiply two numbers")
   print("Enter 'divide' to divide two numbers")
   print("Enter 'quit' to end the program")
   user_input = input(": ")

   if user_input == "quit":
      break
   elif user_input == "add":
      ...
   elif user_input == "subtract":
      ...
   elif user_input == "multiply":
      ...
   elif user_input == "divide":
      ...
   else:
      print("Unknown input")

نکته:کد بالا، نقطه شروع برای برنامه ما است. در ابتدای کار از کاربر ورودی را خواهد گرفت.

بخش بعدی برنامه گرفتن شماره هایی است که کاربر میخواهد کاری را انجام دهد.
کد زیر نشان می دهد که برای بخش جمع ماشین حساب چه عملکردی خواهد داشت. کد مشابه برای بخش های دیگر باید نوشته شود.

elif user_input == "add":
  num1 = float(input("Enter a number: "))
  num2 = float(input("Enter another number: "))

در حال حاضر، هنگامی که کاربر ورودی “add” می دهد، برنامه درخواست وارد کردن دو عدد و ذخیره آنها را در متغیرهای متناظر را خواهد داشت.

بخش نهایی برنامه ورودی کاربر را پردازش می کند و آن را نمایش می دهد.
کد قسمت اضافه شده در اینجا نشان داده شده است.

elif user_input == "add":
  num1 = float(input("Enter a number: "))
  num2 = float(input("Enter another number: "))
  result = str(num1 + num2)
  print("The answer is " + result)

ما اکنون یک برنامه کاری داریم که از کاربر ورودی میگیرد و سپس مقدار خروجی را محاسبه و چاپ می کند.
کد مشابهی باید برای شاخه های دیگر (برای تفریق، ضرب و تقسیم) نوشته شود.

۰ نظر موافقین ۰ مخالفین ۰ ۰۵ تیر ۹۸ ، ۲۲:۳۷
سعید دامغانیان

حلقه for و دیگر حلقه های تکرار:

گاهی نیاز است تا یک عمل را بر روی هر یک از اعضای یک لیست انجام دهید. که در اینجا نیاز به حلقه های تکرار است. و این کار با حلقه while و یک شمارنده به عنوان counter صورت می گیرد.
به عنوان مثال:

words = ["hello", "world", "spam", "eggs"]
cnt = 0
max_index = len(words) - 1
while cnt <= max_index:
   word = words[cnt]
   print(word + "!")
   cnt = cnt + 1

خروجی:

>>>
hello!
world!
spam!
eggs!
>>>

نکته:در مثال بالا با استفاده از شاخصه های عددی اعضای لیست صدایشان می کند و عمل مورد نظر را بر رویشان انجام می دهد.

از طریق یک لیست با استفاده از یک حلقه زمانی نیاز به مقدار زیادی کد دارد، بنابراین Python حلقه را به عنوان یک میانبر فراهم می کند که همان کار را انجام می دهد.
همان کد از مثال قبلی را می توان با حلقه ای به صورت زیر نوشته شده است:

words = ["hello", "world", "spam", "eggs"]
for word in words:
  print(word + "!")

خروجی:

>>>
hello!
world!
spam!
eggs!
>>>

از حلقه معمولا برای تکرار بعضی از کد ها در تعداد بارهای معین استفاده می شود. این کار با ترکیب کردن حلقه ها با Range انجام می شود.

for i in range(5):
  print("hello!")

خروجی:

>>>
hello!
hello!
hello!
hello!
hello!
>>>
۰ نظر موافقین ۰ مخالفین ۰ ۰۵ تیر ۹۸ ، ۲۲:۳۶
سعید دامغانیان

تابع range

تابع range و یا دامنه یک لیست پیوندی از اعداد درست می کند.
کد زیر یک لیست شامل تمام اعداد صحیح، تا 10 را تولید می کند.

numbers = list(range(10))
print(numbers)

خروجی:

>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

نکته: صدا کردن تابع list اجباریست چرا که Range به تنهایی یک شی و آیتم را خواهد ساخت. و همچنین می بایستی به لیست تبدیل شود تا بتوان نشانش داد.

اگر لیست با یک آرگومان صدا زده شود به صورت پیش فرض از 0 تا آن بازه را در نظر می گیرد. و در صورتی که از دو آرگومان تشکیل شود بازه میانی آن دو را نشان خواهد داد.
البته به صورت n تا n-1 خواهد بود.

numbers = list(range(3, 8))
print(numbers)

print(range(20) == range(0, 20))

خروجی:

>>>
[3, 4, 5, 6, 7]

True
>>>

Range می تواند یک استدلال سوم داشته باشد که فاصله بازه تولید شده را تعیین می کند. این استدلال سوم باید یک عدد صحیح باشد.

numbers = list(range(5, 20, 2))
print(numbers)

خروجی:

>>>
[5, 7, 9, 11, 13, 15, 17, 19]
>>>
۰ نظر موافقین ۰ مخالفین ۰ ۰۵ تیر ۹۸ ، ۲۲:۳۵
سعید دامغانیان

توابع در لیست

متد append

یکی دیگر از روش های تغییر در لیست استفاده از متد ها و توابع در لیست است از جمله متد append . این متد یک مقدار را به انتهای لیست اضافه می کند.

nums = [1, 2, 3]
nums.append(4)
print(nums)

خروجی:

>>>
[1, 2, 3, 4]
>>>

نکته: نقطه قبل از دستور append به دلیل این است که از متدی در کلاس لیست استفاده می شود. متد ها در آموزش های بعدی بررسی خواهند شد.

متد len

از متد len برای به دست آوردن تعداد آیتم های داخل لیست استفاده می شود.

nums = [1, 3, 5, 2, 4]
print(len(nums))

خروجی:

>>>
5
>>>

نکته: برخلاف append در حقیقت len یک تابع عادی است و نه یک متد. پس به این معناست که نیازی به نقطع ندارد و قبل از آیتم صدا زده می شود.

متد insert

این متد تشابهاتی با متد append دارد با این تفاوت که می توانید جایگاه اضافه کردن آیتم را نیز مشخص کنید حتی در انتها.

words = ["Python", "fun"]
index = 1
words.insert(index, "is")
print(words)

خروجی:

>>>
['Python', 'is', 'fun']
>>>
متد index

در این متد از پایتون می توانید جایگاه آیتم را در لیست مشخص کنید و در صورتی که آیتم در خواست شده در لیست نباشد با اخطار ValueError مواجه خواهید شد.

letters = ['p', 'q', 'r', 's', 'p', 'u']
print(letters.index('r'))
print(letters.index('p'))
print(letters.index('z'))

خروجی:

>>>
2
0
ValueError: 'z' is not in list
>>>

نکته:
چند توابع و روش مفید برای لیست ها وجود دارد.
max (list): عنصر لیست با حداکثر مقدار را می دهد
min (list): آیتم لیست با حداقل مقدار را باز می گرداند
list.count (obj): شمارش تعداد چند بار یک مورد در یک لیست را نشان می دهد
list.remove (obj): حذف یک شی از یک لیست
list.reverse (): اشیا را در یک لیست معکوس می کند

۰ نظر موافقین ۰ مخالفین ۰ ۰۵ تیر ۹۸ ، ۲۲:۳۴
سعید دامغانیان