5 مهر 1402
تهران، خیابان آزادی، تقاطع قریب
برنامه نویسی نرم افزار برنامه نویسی وب

پروژه های پایتون برای افراد مبتدی و حرفه‌ای (1)

پروژه های پایتون برای افراد مبتدی و حرفه‌ای – قسمت 1
با برگذاری یک مینی دوره رایگان موافقید؟
برای ثبت نام در مینی دوره رایگان فرم زیر رو پر کنید.

صرف نظر از ظرفیت‌های کنونی پایتون، یادگیری نحوه ساخت پروژه های پایتون راهی مطمئن برای تقویت مهارت‌های شما و ارتقای نمونه‌ کارهای‌تان است. هیچ از بهتر از سر و کله زدن با برنامه نویسی واقعی و ساختن پروژه‌های پایتون نیست!

به علاوه، تبدیل شدن به یک برنامه نویس حرفه‌ای پایتون در سال 2023 می‌تواند درهای زیادی را به روی شما باز کند و به شما امکان می‌دهد برخی از بهترین فرصت‌های شغلی روی زمین را به دست بیاورید. یک بحث جذاب دیگر، بحث حقوق و درآمد است که در این باره می‌توانیم بگوییم درآمد برنامه نویسان پروژه های پایتون بیش از 100.000 دلار (در سال) است.

در این مقاله، 30 پروژه جالب پایتون را لیست کرده‌ایم، از پروژه های پایتون ساده برای افراد مبتدی گرفته تا ایده‌های پروژه متوسط و پیشرفته پایتون، که می‌توانید از آن‌ها برای به چالش کشیدن یا بهبود مهارت‌های برنامه نویسی خود استفاده کنید.

در این قسمت از این مطلب دو قسمتی، 15 مورد از این پروژه‌ها را مورد بررسی قرار می‌دهیم. قسمت دوم، شامل 15 پروژه پایتون دیگر است.

پروژه های مبتدی همراه با Source Code

پروژه های پایتون: Mad Libs Generator

این یکی از سرگرم‌کننده‌ترین پروژه های پایتون برای افراد مبتدی است. ناگفته نماند که این پروژه به شما امکان می‌دهد نحوه استفاده از رشته‌ها، متغیرها و Concatenation ها را تمرین کنید.

Mad Libs Generator داده‌های ورودی کاربر را به عنوان صفت، ضمیر و فعل جمع‌آوری و دستکاری می‌کند. برنامه این داده‌ها را می‌گیرد و آن‌ها را برای ساخت یک داستان مرتب می‌کند.

Source Code:

				
					'''
Mad Libs Generator
-------------------------------------------------------------
'''

# Questions for the user to answer

noun = input('Choose a noun: ')

p_noun = input('Choose a plural noun: ')

noun2 = input('Choose a noun: ')

place = input('Name a place: ')

adjective = input('Choose an adjective (Describing word): ')

noun3 = input('Choose a noun: ')

# Print a story from the user input

print('------------------------------------------')

print('Be kind to your', noun, '- footed', p_noun)

print('For a duck may be somebody\'s', noun2, ',')

print('Be kind to your', p_noun, 'in', place)

print('Where the weather is always', adjective, '. \n')

print('You may think that is this the', noun3, ',')

print('Well it is.')

print('------------------------------------------')

				
			

پروژه های پایتون: حدس زدن اعداد

این مورد از پروژه های مبتدی پایتون یک بازی سرگرم کننده است که یک عدد تصادفی (در یک محدوده مشخص) تولید می‌کند که کاربر باید پس از دریافت یک سری راهنمایی، آن را حدس بزند. به ازای هر حدس اشتباه کاربر، راهنمایی‌های بیشتری به او داده می‌شود، اما به قیمت کاهش امتیاز نهایی خود.

این برنامه یک راه عالی برای آزمایش با کتابخانه استاندارد پایتون است، زیرا از ماژول تصادفی پایتون برای تولید اعداد تصادفی استفاده می‌کند. همچنین می‌توانید با عبارات شرطی، Print Formatting و توابع تعریف‌شده توسط کاربر، تمرین عملی انجام دهید.

Source Code:

				
					'''
Number Guessing Game
-------------------------------------------------------------
'''

import random

attempts_list = []


def show_score():
    if not attempts_list:
        print('There is currently no high score,'
              ' it\'s yours for the taking!')

    else:
        print(f'The current high score is'
              f' {min(attempts_list)} attempts')


def start_game():
    attempts = 0
    rand_num = random.randint(1, 10)
    print('Hello traveler! Welcome to the game of guesses!')
    player_name = input('What is your name? ')
    wanna_play = input(
        f'Hi, {player_name}, would you like to play '
        f'the guessing game? (Enter Yes/No): ')

    if wanna_play.lower() != 'yes':
        print('That\'s cool, Thanks!')
        exit()
    else:
        show_score()

    while wanna_play.lower() == 'yes':
        try:
            guess = int(input('Pick a number between 1 and 10: '))
            if guess < 1 or guess > 10:
                raise ValueError(
                    'Please guess a number within the given range')

            attempts += 1
            attempts_list.append(attempts)

            if guess == rand_num:
                print('Nice! You got it!')
                print(f'It took you {attempts} attempts')
                wanna_play = input(
                    'Would you like to play again? (Enter Yes/No): ')
                if wanna_play.lower() != 'yes':
                    print('That\'s cool, have a good one!')
                    break
                else:
                    attempts = 0
                    rand_num = random.randint(1, 10)
                    show_score()
                    continue
            else:
                if guess > rand_num:
                    print('It\'s lower')
                elif guess < rand_num:
                    print('It\'s higher')

        except ValueError as err:
            print('Oh no!, that is not a valid value. Try again...')
            print(err)


if __name__ == '__main__':
    start_game()
				
			

پروژه های پایتون: سنگ کاغذ قیچی

این مورد از پروژه های پایتون، برنامه سنگ کاغذ قیچی است که این بازی محبوب جهانی را با توابع و عبارات شرطی شبیه‌سازی می‌کند. پس چه راهی بهتر از این برای یادگرفتن این مفاهیم مهم؟

این برنامه به عنوان یکی از پروژه های پرتعداد کدنویسی پایتون که کتابخانه‌های اضافی را وارد خود می‌کند، از ماژول‌های random ، os و re استفاده می‌کند.

به کد زیر نگاهی بیندازید و خواهید دید که این پروژه پایتون از کاربر می‌خواهد با عبور از یک کاراکتر، اولین حرکت را برای نشان دادن سنگ، کاغذ یا قیچی نشان دهد. پس از ارزیابی رشته وردی، منطق شرطی برنامه، برنده را شناسایی می‌کند.

Source Code:

				
					'''
Rock Paper Scissors
-------------------------------------------------------------
'''


import random
import os
import re


def check_play_status():
  valid_responses = ['yes', 'no']
  while True:
      try:
          response = input('Do you wish to play again? (Yes or No): ')
          if response.lower() not in valid_responses:
              raise ValueError('Yes or No only')

          if response.lower() == 'yes':
              return True
          else:
              os.system('cls' if os.name == 'nt' else 'clear')
              print('Thanks for playing!')
              exit()

      except ValueError as err:
          print(err)


def play_rps():
   play = True
   while play:
       os.system('cls' if os.name == 'nt' else 'clear')
       print('')
       print('Rock, Paper, Scissors - Shoot!')

       user_choice = input('Choose your weapon'
                           ' [R]ock], [P]aper, or [S]cissors: ')

       if not re.match("[SsRrPp]", user_choice):
           print('Please choose a letter:')
           print('[R]ock, [P]aper, or [S]cissors')
           continue

       print(f'You chose: {user_choice}')

       choices = ['R', 'P', 'S']
       opp_choice = random.choice(choices)

       print(f'I chose: {opp_choice}')

       if opp_choice == user_choice.upper():
           print('Tie!')
           play = check_play_status()
       elif opp_choice == 'R' and user_choice.upper() == 'S':
           print('Rock beats scissors, I win!')
           play = check_play_status()
       elif opp_choice == 'S' and user_choice.upper() == 'P':
           print('Scissors beats paper! I win!')
           play = check_play_status()
       elif opp_choice == 'P' and user_choice.upper() == 'R':
           print('Paper beats rock, I win!')
           play = check_play_status()
       else:
           print('You win!\n')
           play = check_play_status()


if __name__ == '__main__':
   play_rps()
				
			

پروژه های پایتون: شبیه‌ساز تاس

این برنامه به عنوان یکی از مبتدی‌ترین پروژه های پایتون برای کدنویسی، ریختن یک یا دو تاس را شبیه‌سازی می‌کند و یک راه عالی برای تقویت درک شما از توابع، حلقه‌ها (loops) و عبارات شرطی تعریف‌شده توسط کاربر است.

این یکی از پروژه های آسان پایتون است که از ماژول random پایتون برای تکرار ماهیت تصادفی پرتاب تاس استفاده می‌کند. همچنین متوجه خواهید شد که برای پاک کردن صفحه پس از انداختن تاس، از ماژول os استفاده کرده‌ایم.

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

Source Code:

				
					'''
Dice Roll Generator
-------------------------------------------------------------
'''


import random
import os


def num_die():
  while True:
      try:
          num_dice = input('Number of dice: ')
          valid_responses = ['1', 'one', 'two', '2']
          if num_dice not in valid_responses:
              raise ValueError('1 or 2 only')
          else:
              return num_dice
      except ValueError as err:
          print(err)


def roll_dice():
   min_val = 1
   max_val = 6
   roll_again = 'y'

   while roll_again.lower() == 'yes' or roll_again.lower() == 'y':
       os.system('cls' if os.name == 'nt' else 'clear')
       amount = num_die()

       if amount == '2' or amount == 'two':
           print('Rolling the dice...')
           dice_1 = random.randint(min_val, max_val)
           dice_2 = random.randint(min_val, max_val)

           print('The values are:')
           print('Dice One: ', dice_1)
           print('Dice Two: ', dice_2)
           print('Total: ', dice_1 + dice_2)

           roll_again = input('Roll Again? ')
       else:
           print('Rolling the die...')
           dice_1 = random.randint(min_val, max_val)
           print(f'The value is: {dice_1}')

           roll_again = input('Roll Again? ')


if __name__ == '__main__':
   roll_dice()
				
			

پروژه های پایتون: بازی Hangman

این یکی از پروژه های جذاب پایتون برای تقلید از بازی حدس کلمات، یعنی Hangman است. ما از یک لیست کلمات از پیش تعریف شده برای حدس زدن استفاده کرده‌ایم، اما می‌توانید با استفاده از دیکشنری API شخص ثالث، آن را بهبود ببخشید.

این پروژه پایتون از حلقه‌ها، توابع و formatting رشته برای پرینت کردن پیشرفت Hangman استفاده می‌کند. همچنین به شما امکان می‌دهد ماژول‌های random ، time و os را امتحان کنید.

به طور خاص، ما از ماژول random به منظور انتخاب کلمه برای حدس زدن، از ماژول os برای پاک کردن صفحه و از تابع .sleep() ماژول time برای معرفی مکث‌ها (Pauses) به منظور بهبود جریان بازی استفاده کرده‌ایم.

Source Code:

				
					'''
Hangman Game
-------------------------------------------------------------
'''


import random
import time
import os


def play_again():
  question = 'Do You want to play again? y = yes, n = no \n'
  play_game = input(question)
  while play_game.lower() not in ['y', 'n']:
      play_game = input(question)

  if play_game.lower() == 'y':
      return True
  else:
      return False


def hangman(word):
  display = '_' * len(word)
  count = 0
  limit = 5
  letters = list(word)
  guessed = []
  while count < limit:
      guess = input(f'Hangman Word: {display} Enter your guess: \n').strip()
      while len(guess) == 0 or len(guess) > 1:
          print('Invalid input. Enter a single letter\n')
          guess = input(
              f'Hangman Word: {display} Enter your guess: \n').strip()

      if guess in guessed:
          print('Oops! You already tried that guess, try again!\n')
          continue

      if guess in letters:
          letters.remove(guess)
          index = word.find(guess)
          display = display[:index] + guess + display[index + 1:]

      else:
          guessed.append(guess)
          count += 1
          if count == 1:
              time.sleep(1)
              print('   _____ \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '__|__\n')
              print(f'Wrong guess: {limit - count} guesses remaining\n')

          elif count == 2:
              time.sleep(1)
              print('   _____ \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '__|__\n')
              print(f'Wrong guess: {limit - count} guesses remaining\n')

          elif count == 3:
              time.sleep(1)
              print('   _____ \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |      \n'
                    '  |      \n'
                    '  |      \n'
                    '__|__\n')
              print(f'Wrong guess: {limit - count} guesses remaining\n')

          elif count == 4:
              time.sleep(1)
              print('   _____ \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |     O \n'
                    '  |      \n'
                    '  |      \n'
                    '__|__\n')
              print(f'Wrong guess: {limit - count} guesses remaining\n')

          elif count == 5:
              time.sleep(1)
              print('   _____ \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |     | \n'
                    '  |     O \n'
                    '  |    /|\ \n'
                    '  |    / \ \n'
                    '__|__\n')
              print('Wrong guess. You\'ve been hanged!!!\n')
              print(f'The word was: {word}')

      if display == word:
          print(f'Congrats! You have guessed the word \'{word}\' correctly!')
          break


def play_hangman():
   print('\nWelcome to Hangman\n')
   name = input('Enter your name: ')
   print(f'Hello {name}! Best of Luck!')
   time.sleep(1)
   print('The game is about to start!\nLet\'s play Hangman!')
   time.sleep(1)
   os.system('cls' if os.name == 'nt' else 'clear')

   words_to_guess = [
       'january', 'border', 'image', 'film', 'promise', 'kids',
       'lungs', 'doll', 'rhyme', 'damage', 'plants', 'hello', 'world'
   ]
   play = True
   while play:
       word = random.choice(words_to_guess)
       hangman(word)
       play = play_again()

   print('Thanks For Playing! We expect you back again!')
   exit()


if __name__ == '__main__':
  play_hangman()
				
			

پروژه های پایتون: بررسی قدرت پسوورد

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

ما همچنین از ماژول‌های string و getpass از کتابخانه استاندارد پایتون استفاده می‌کنیم. این به ما امکان می‌دهد تا به طیف کاملی از کاراکترهای رشته (string) دسترسی داشته باشیم تا آن‌ها را با ترکیب کاراکترهای پسوورد خود مقایسه کنیم. تابع .getpass() هم به ما امکان می‌دهد پسووردمان را در هنگام وارد کردن مخفی کنیم.

Source Code:

				
					'''
Password Strength Checker
-------------------------------------------------------------
'''


import string
import getpass


def check_password_strength():
   password = getpass.getpass('Enter the password: ')
   strength = 0
   remarks = ''
   lower_count = upper_count = num_count = wspace_count = special_count = 0

   for char in list(password):
       if char in string.ascii_lowercase:
           lower_count += 1
       elif char in string.ascii_uppercase:
           upper_count += 1
       elif char in string.digits:
           num_count += 1
       elif char == ' ':
           wspace_count += 1
       else:
           special_count += 1

   if lower_count >= 1:
       strength += 1
   if upper_count >= 1:
       strength += 1
   if num_count >= 1:
       strength += 1
   if wspace_count >= 1:
       strength += 1
   if special_count >= 1:
       strength += 1

   if strength == 1:
       remarks = ('That\'s a very bad password.'
           ' Change it as soon as possible.')
   elif strength == 2:
       remarks = ('That\'s a weak password.'
           ' You should consider using a tougher password.')
   elif strength == 3:
       remarks = 'Your password is okay, but it can be improved.'
   elif strength == 4:
       remarks = ('Your password is hard to guess.'
           ' But you could make it even more secure.')
   elif strength == 5:
       remarks = ('Now that\'s one hell of a strong password!!!'
           ' Hackers don\'t have a chance guessing that password!')

   print('Your password has:-')
   print(f'{lower_count} lowercase letters')
   print(f'{upper_count} uppercase letters')
   print(f'{num_count} digits')
   print(f'{wspace_count} whitespaces')
   print(f'{special_count} special characters')
   print(f'Password Score: {strength / 5}')
   print(f'Remarks: {remarks}')


def check_pwd(another_pw=False):
   valid = False
   if another_pw:
       choice = input(
           'Do you want to check another password\'s strength (y/n) : ')
   else:
       choice = input(
           'Do you want to check your password\'s strength (y/n) : ')

   while not valid:
       if choice.lower() == 'y':
           return True
       elif choice.lower() == 'n':
           print('Exiting...')
           return False
       else:
           print('Invalid input...please try again. \n')


if __name__ == '__main__':
   print('===== Welcome to Password Strength Checker =====')
   check_pw = check_pwd()
   while check_pw:
       check_password_strength()
       check_pw = check_pwd(True)
				
			

پروژه های پایتون: تبدیل اعداد به کلمات

این ایده پروژه های پایتون یک عدد صحیح ارائه شده از طریق ورودی کاربر را به کلمات معادل خود تبدیل می‌کند. این برنامه برای پشتیبانی از اعداد با حداکثر 12 رقم تنظیم شده است، اما با خیال راحت برنامه را modify کنید تا اعداد بزرگتر را مدیریت کند. (نکته: به عبارات شرطی و حلقه‌ها نیاز دارد).

این برنامه ساده اما مؤثر، به عنوان نمونه‌ای آسان برای درک پروژه های پایتون، می‌تواند مهارت‌های شما را با حلقه‌ها، ورودی‌های کاربر و عبارات شرطی گسترش دهد. البته اگر tuple ها و list های پایتون را ذکر نکنیم.

همچنین می‌توانید برخی عملیات‌های ریاضی را که ممکن است برایتان جدید باشند، تست کنید. مانند modulo (%) operator برای برگرداندن باقی‌مانده از تقسیم اعداد صحیح.

Source Code:

				
					'''
Numbers To Words
-------------------------------------------------------------
'''


ones = (
   'Zero', 'One', 'Two', 'Three', 'Four',
   'Five', 'Six', 'Seven', 'Eight', 'Nine'
   )

twos = (
   'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen',
    'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'
   )

tens = (
   'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty',
    'Seventy', 'Eighty', 'Ninety', 'Hundred'
   )

suffixes = (
   '', 'Thousand', 'Million', 'Billion'
   )

def fetch_words(number, index):
   if number == '0': return 'Zero'

   number = number.zfill(3)
   hundreds_digit = int(number[0])
   tens_digit = int(number[1])
   ones_digit = int(number[2])

   words = '' if number[0] == '0' else ones[hundreds_digit]
  
   if words != '':
       words += ' Hundred '

   if tens_digit > 1:
       words += tens[tens_digit - 2]
       words += ' '
       words += ones[ones_digit]
   elif(tens_digit == 1):
       words += twos[((tens_digit + ones_digit) % 10) - 1]
   elif(tens_digit == 0):
       words += ones[ones_digit]

   if(words.endswith('Zero')):
       words = words[:-len('Zero')]
   else:
       words += ' '

   if len(words) != 0:
       words += suffixes[index]
      
   return words


def convert_to_words(number):
   length = len(str(number))
   if length > 12:
       return 'This program supports a maximum of 12 digit numbers.'

   count = length // 3 if length % 3 == 0 else length // 3 + 1
   copy = count
   words = []

   for i in range(length - 1, -1, -3):
       words.append(fetch_words(
           str(number)[0 if i - 2 < 0 else i - 2 : i + 1], copy - count))
      
       count -= 1

   final_words = ''
   for s in reversed(words):
       final_words += (s + ' ')

   return final_words

if __name__ == '__main__':
   number = int(input('Enter any number: '))
   print('%d in words is: %s' %(number, convert_to_words(number)))
				
			

پروژه های پایتون: Tic-Tac-Toeیا دوز

Tic-Tac-Toe یک بازی کلاسیک دونفره شامل شبکه‌ای از 9 مربع است. هر بازیکن به صورت نوبتی یکی از مربع‌ها را با O یا X پر می‌کند و هر بازیکنی که بتواند سه O یا X را به صورت مورب، افقی یا عمودی علامت‌گذاری کند، برنده می‌شود. هر بازیکن همچنین باید زنجیره حریف خود را در حین ایجاد مسدود کند.

این یکی از سرگرم‌کننده‌ترین پروژه های پایتون است که برای مبتدیان برنامه‌ای منحصر به فرد خواهد بود، زیرا از برنامه نویسی شیءگرا برای ایجاد کلاس جدیدی به نام TicTacToe استفاده می‌کند. ما از این کلاس برای نمایش ویژگی‌های بازی از طریق class attribute ها و method ها استفاده می‌کنیم.

این method ها را به دقت مطالعه کنید تا ببینید چگونه می‌توانیم از برنامه نویسی شیءگرا برای package کردن منظم رفتارهای مختلف مورد نیاز، برای شبیه‌سازی این بازی استفاده کنیم.

برخی از جنبه‌های جدید این پروژه مبتدی پایتون، شامل nested loops برای بررسی ستون‌ها، ردیف‌ها و خطوط مورب این شبکه برای تعیین وضعیت برنده، به همراه set data type پایتون است که برای مقادیر منحصر به فرد استفاده می‌شود. این برنامه همچنین از ماژول random پایتون برای انتخاب یک بازیکن تصادفی برای شروع بازی استفاده می‌کند، که اکنون برای شما آشناتر است.

Source Code:

				
					'''
Tic Tac Toe
-------------------------------------------------------------
'''


import random


class TicTacToe:

   def __init__(self):
       self.board = []

   def create_board(self):
       for i in range(3):
           row = []
           for j in range(3):
               row.append('-')
           self.board.append(row)

   def get_random_first_player(self):
       return random.randint(0, 1)

   def fix_spot(self, row, col, player):
       self.board[row][col] = player

   def has_player_won(self, player):
       n = len(self.board)
       board_values = set()

       # check rows
       for i in range(n):
           for j in range(n):
               board_values.add(self.board[i][j])

           if board_values == {player}:
               return True
           else:
               board_values.clear()

       # check cols
       for i in range(n):
           for j in range(n):
               board_values.add(self.board[j][i])

           if board_values == {player}:
               return True
           else:
               board_values.clear()

       # check diagonals
       for i in range(n):
           board_values.add(self.board[i][i])
       if board_values == {player}:
           return True
       else:
           board_values.clear()
      
       board_values.add(self.board[0][2])
       board_values.add(self.board[1][1])
       board_values.add(self.board[2][0])
       if board_values == {player}:
           return True
       else:
           return False

   def is_board_filled(self):
       for row in self.board:
           for item in row:
               if item == '-':
                   return False
       return True

   def swap_player_turn(self, player):
       return 'X' if player == 'O' else 'O'

   def show_board(self):
       for row in self.board:
           for item in row:
               print(item, end=' ')
           print()

   def start(self):
       self.create_board()
       player = 'X' if self.get_random_first_player() == 1 else 'O'
       game_over = False

       while not game_over:
           try:
               self.show_board()
               print(f'\nPlayer {player} turn')

               row, col = list(
                   map(int, input(
                       'Enter row & column numbers to fix spot: ').split()))
               print()

               if col is None:
                   raise ValueError(
                       'not enough values to unpack (expected 2, got 1)')

               self.fix_spot(row - 1, col - 1, player)

               game_over = self.has_player_won(player)
               if game_over:
                   print(f'Player {player} wins the game!')
                   continue

               game_over = self.is_board_filled()
               if game_over:
                   print('Match Draw!')
                   continue

               player = self.swap_player_turn(player)

           except ValueError as err:
               print(err)

       print()
       self.show_board()


if __name__ == '__main__':
  tic_tac_toe = TicTacToe()
  tic_tac_toe.start()
				
			

پروژه های پایتون: ماشین حساب

این برنامه به عنوان یکی از پروژه های آسان پایتون، یک ماشین حساب پایه با توابع جمع، تفریق، ضرب و تقسیم (addition, subtraction, multiplication, and division) ایجاد می‌کند.

این یکی از پروژه های تمرینی پایتون است که برای یادگیری نحوه استفاده از حلقه‌ها، توابع، عبارات شرطی، ورودی کاربر و string formatting بسیار عالی است. ما همچنین از ماژول os پایتون برای پاک کردن صفحه پس از انجام اقدامات محاسباتی توسط کاربر، استفاده کرده‌ایم.

Source Code:

				
					'''
Calculator
-------------------------------------------------------------
'''


import os


def addition():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Addition')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 + num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans += num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def subtraction():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Subtraction')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 - num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans -= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def multiplication():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Multiplication')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 * num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans *= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def division():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Division')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   while num_2 == 0.0:
       print('Please enter a second number > 0')
       num_2 = float(input('Enter another number: '))

   ans = num_1 / num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       while num == 0.0:
           print('Please enter a number > 0')
           num = float(input('Enter another number: '))
       ans /= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def calculator():
   quit = False
   while not quit:
       results = []
       print('Simple Calculator in Python!')
       print('Enter \'a\' for addition')
       print('Enter \'s\' for substraction')
       print('Enter \'m\' for multiplication')
       print('Enter \'d\' for division')
       print('Enter \'q\' to quit')

       choice = input('Selection: ')

       if choice == 'q':
           quit = True
           continue

       if choice == 'a':
           results = addition()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 's':
           results = subtraction()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 'm':
           results = multiplication()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 'd':
           results = division()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       else:
           print('Sorry, invalid character')


if __name__ == '__main__':
   calculator()
				
			

پروژه های پایتون: شمارش معکوس و تایمر

این یکی از سرگرم کننده‌ترین پروژه های پایتون است! در این‌جا، یک تایمر شمارش معکس ایجاد کرده‌ایم که از طریق ورودی کاربر، تعداد ثانیه‌ها را دریافت می‌کند و سپس ثانیه به ثانیه شمارش معکوس می‌کند تا پیامی را نمایش دهد.

ما از تابع .sleep() ماژول time پایتون برای مکث در فواصل 1 ثانیه‌ای استفاده کرده‌ایم. ما این را با یک string formatting زیبا ترکیب می‌کنیم تا نمایشگر شمارش معکوس ایجاد شود.

Source Code:

				
					'''
Countdown Timer
-------------------------------------------------------------
'''


import time


def countdown(user_time):
   while user_time >= 0:
       mins, secs = divmod(user_time, 60)
       timer = '{:02d}:{:02d}'.format(mins, secs)
       print(timer, end='\r')
       time.sleep(1)
       user_time -= 1
   print('Lift off!')


if __name__ == '__main__':
   user_time = int(input("Enter a time in seconds: "))
   countdown(user_time)
				
			

پروژه های سطح متوسط همراه با Source Code

پروژه های پایتون: الگوریتم جستجوی باینری

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

این پروژه پایتون برای جستجوی باینری، یک لیست مرتب‌شده (array) می‌گیرد و سپس به طور مداوم، مقدار جستجو را با مقدار میانی آرایه مقایسه می‌کند.

بسته به این‌که مقدار جستجو از مقدار میانی کمتر یا بیشتر باشد، لیست تقسیم می‌شود (استراتژی تقسیم و غلبه- divide-and-conquer) تا فضای جستجو را کاهش دهد. این ارزش جستجوی داده شده را مشخص می‌کند. این تقسیم مداوم، منجر به پیچیدگی زمان لگاریتمی می‌شود.

اگر به کد زیر نگاه کنید، خواهید دید که ما دو راه حل را پیاده‌سازی کرده‌ایم: حلقه‌های شرطی و Recursion (بازگشت). هر دو رویکرد ظریف هستند، بنابراین می‌توانید با خیال راحت هر دوی آن‌ها را آزمایش کنید.

اگر در زمینه Recursion تازه‌کار هستید، این یک شروع عالی برای یادگیری این مبحث خواهد بود. زیرا نشان می‌دهد که چگونه اندازه مشکل (problem) را با هر تماس بازگشتی، یعنی با تقسیم لیست به یک طرف عنصر میانی فعلی، «کاهش» می‌دهیم.

ما همچنین حالت پایه بازگشتی را به عنوان نقطه‌ای تعریف کرده‌ایم که عنصر میانی در آن با عنصر جستجو برابر است. در این حالت، Recursion متوقف می‌شود و مقدار True را از طریق call stack باز می‌گرداند.

Source Code:

				
					'''
Binary Search
-------------------------------------------------------------
'''


def binary_search(a_list, an_item):
   first = 0
   last = len(a_list) - 1

   while first <= last:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
           else:
               first = mid_point + 1
   return False


def binary_search_rec(a_list, first, last, an_item):
   if len(a_list) == 0:
       return False
   else:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
               return binary_search_rec(a_list, first, last, an_item)
           else:
               first = mid_point + 1
               return binary_search_rec(a_list, first, last, an_item)


if __name__ == '__main__':
   a_list = [1, 4, 7, 10, 14, 19, 102, 2575, 10000]
  
   print('Binary Search:', binary_search(a_list, 4))
   print('Binary Search Recursive:',
       binary_search_rec(a_list, 0, len(a_list) -1, 4))
				
			

پروژه های پایتون: الگوریتم مرتب‌سازی ادغام (Merge Sort)

Merge Sort یکی دیگر از چالش‌های محبوب کدنویسی است که برنامه نویسان مشتاق، هنگام انجام دادن کارهای خود در پایتون با آن مواجه می‌شوند.

این استراتژی divide-and-conquer از تقسیم برای جدا کردن لیستی از اعداد به قسمت‌های مساوی استفاده می‌کند و سپس این اعداد قبل از ترکیب مجدد برای ایجاد یک لیست مرتب‌شده، به صورت بازگشتی (recursively) مرتب می‌شوند.

اگر به تازگی پروژه جستجوی باینری را تکمیل کرده‌اید، ممکن است بین تقسیم و کاهش اندازه یک مشکل، متوجه شباهت‌هایی شوید. حق با شماست، به این معنی که احتمالاً متوجه شده‌اید ما باید از Recursion استفاده کنیم.

این پیاده‌سازی پایتون از Merge Sort، از Recursion برای مدیریت فرآیند divide-and-conquer استفاده می‌کند. کاهش مداوم اندازه مشکل (problem) باعث می‌شود که وقتی به حالت پایه recursive رسیدیم، یعنی اندازه مشکل به اندازه یک عنصر یا کمتر باشد، مشکل حل می‌شود.

در اصل، این برنامه پایتون به تقسیم بازگشتی لیست ادامه می‌دهد تا زمانی که به حالت پایه برسد. در این مرحله، شروع به مرتب‌سازی بخش‌های کوچکتر مشکل می‌کند، و در نتیجه آرایه‌های مرتب‌شده کوچک‌تری ایجاد می‌شود که دوباره ترکیب می‌شوند تا در نهایت یک آرایه کاملاً مرتب‌سازی‌شده (sorted) ایجاد شود. اگر با نماد Big O آشنایی دارید، برایتان جالب است که بدانید Merge Sort دارای یک Big O of (n logn) است.

Source Code:

				
					'''
Merge Sort
-------------------------------------------------------------
'''


def merge_sort(a_list):
   print("Dividing ", a_list)
  
   if len(a_list) > 1:
       mid_point = len(a_list)//2
       left_half = a_list[:mid_point]
       right_half = a_list[mid_point:]

       merge_sort(left_half)
       merge_sort(right_half)

       i=0
       j=0
       k=0

       while i < len(left_half) and j < len(right_half):
           if left_half[i] <= right_half[j]:
               a_list[k] = left_half[i]
               i += 1
           else:
               a_list[k] = right_half[j]
               j += 1
           k += 1

       while i < len(left_half):
           a_list[k] = left_half[i]
           i += 1
           k += 1

       while j < len(right_half):
           a_list[k] = right_half[j]
           j += 1
           k += 1
  
   print("Merging ", a_list)


if __name__ == '__main__':
   a_list = [45, 7, 85, 24, 60, 25, 38, 63, 1]
   merge_sort(a_list)
   print(a_list)
				
			

پروژه های پایتون: Password Generator

این یک پروژه جالب پایتون است که از رازها (secrets) و ماژول‌های رشته‌ای برای تولید پسوورد قوی و ایمن استفاده می‌کند. دقیقاً مثل کاری که Password Manager های محبوب شما انجام می‌دهند.

ماژول رشته‌ای (string module) تمام حروف، اعداد و کاراکترهای خاص ممکن را به دست می‌آورد، و ماژول secrets به ما امکان می‌دهد پسووردهای ایمن به دست آوریم.

کد این پروژه نسبتاً ساده است، زیرا از یک loop برای تولید مداوم پسوورد استفاده می‌کند، تا زمانی که پسوورد تولید شده دارای حداقل یک کاراکتر خاص و دو عدد باشد. البته می‌توانید این را تغییر دهید تا با قوانین پسوورد فوق‌العاده قدرتمند شما مطابقت داشته باشد.

Source Code:

				
					'''
Password Generator
-------------------------------------------------------------
'''


import secrets
import string


def create_pw(pw_length=12):
   letters = string.ascii_letters
   digits = string.digits
   special_chars = string.punctuation

   alphabet = letters + digits + special_chars
   pwd = ''
   pw_strong = False

   while not pw_strong:
       pwd = ''
       for i in range(pw_length):
           pwd += ''.join(secrets.choice(alphabet))

       if (any(char in special_chars for char in pwd) and
               sum(char in digits for char in pwd) >= 2):
           pw_strong = True

   return pwd


if __name__ == '__main__':
   print(create_pw())
				
			

پروژه های پایتون: مبدل ارز

این یکی از پروژه های پایتون است که ما را ملزم به نصب یک کتابخانه جدید پایتون می‌کند. در این مورد، کتابخانه مورد نظر، ماژول requests است. این مورد در کتابخانه استاندارد پایتون گنجانده نشده است، بنابراین از pip command نشان‌داده‌شده در source code برای نصب آن بر روی سیستم خود استفاده کنید.

با ماژول ‌ requests، می‌توانیم درخواست‌های HTTP را به Fixer API ارسال کنیم و از این طریق، ارزها را به یکدیگر تبدیل کنیم. احتمالاً متوجه شده‌اید که ما از API شخص ثالث استفاده می‌کنیم، بنابراین برای دریافت یک API key رایگان، باید در این‌جا ثبت نام کنید. سپس می‌توانید API key خود را در فیلدی که در source code نشان داده شده است، وارد کنید و آماده حرکت شوید!

این پروژه به شما امکان می‌دهد تا تمرین بیشتری با حلقه‌ها و ورودی کاربر انجام دهید، اما این موضوع را با درخواست‌های HTTP برای بازیابی داده‌های API در فرمت JSONگسترش می‌دهد.

اگر به JSON آشنا نیستید، باید بگوییم که بسیار شبیه به دیکشنری پایتون است، به این معنی که می‌توانیم به جفت (pair) های key-value دسترسی داشته باشیم تا داده‌هایی را که به دنبال آن هستیم، fetch کنیم. در این مورد، ما به دنبال نتیجه تبدیل ارز از API call هستیم.

برای دریافت جزئیات بیشتر در مورد داده‌های مختلفی که می‌توانید بازیابی کنید، به اسناد موجود در سایت Fixer API نگاهی بیندازید.

Source Code:

				
					'''
Currency Converter
-------------------------------------------------------------
pip install requests
'''


import requests


def convert_currency():
   init_currency = input('Enter an initial currency: ')
   target_currency = input('Enter a target currency: ')

   while True:
       try:
           amount = float(input('Enter the amount: '))
       except:
           print('The amount must be a numeric value!')
           continue

       if not amount > 0:
           print('The amount must be greater than 0')
           continue
       else:
           break

   url = ('https://api.apilayer.com/fixer/convert?to='
          + target_currency + '&from=' + init_currency +
          '&amount=' + str(amount))

   payload = {}
   headers = {'apikey': 'YOUR API KEY'}
   response = requests.request('GET', url, headers=headers, data=payload)
   status_code = response.status_code

   if status_code != 200:
       print('Uh oh, there was a problem. Please try again later')
       quit()

   result = response.json()
   print('Conversion result: ' + str(result['result']))


if __name__ == '__main__':
   convert_currency()
				
			

پروژه های پایتون: ارسال خودکار ایمیل تبریک تولد!

این مورد از پروژه های پایتون، از ماژول‌های استاندارد smtplib ، EmailMessage و datetime ، به اضافه pandas و openpyxl (مطابق چیزی که در پایین می‌بینید، باید از طریق pip نصب شوند)، برای ارسال خودکار ایمیل‌های تبریک تولید استفاده می‌کند.

این برنامه از یک excel sheet که حاوی جزئیات تاریخ تولد دوستان شماست (فرمت excel sheet را در source code پایین ببینید)، اطلاعات مورد نیاز خود را می‌خواند. سپس اگر امروز روز تولد آن‌ها باشد، قبل از این‌که در spreadsheet شما بنویسد و بگوید ایمیلشان را دریافت کرده‌اند، ایمیلی برایشان ارسال می‌کند.

ما از ماژول‌های smtplib و EmailMessage برای ایجاد یک SSL connection به اکانت ایمیل و پیام خود استفاده کرده‌ایم. سپس از یک pandas dataframe برای ذخیره داده‌های spreadsheet-style در برنامه پاتون (یک مهارت ضروری برای مدیران ارشد داده) استفاده کردیم. در نهایت، ما از formatting تاریخ با تابع .strftimr() ماژول datetime استفاده کردیم.

بنابراین، برای دستیابی به این برنامه، تعداد زیادی مهارت جدید یاد گرفتیم!

اتصال برنامه به حساب Gmail

نکته مهم: از ماه می 2022، گوگل محدودیت‌های خود را برای دسترسی جیمیل به «برنامه‌هایی با امنیت پایین‌تر» افزایش داده است. برای استفاده از این کد با حساب جیمیل خود، باید چند مرحله اضافی را دنبال کنید. اما نگران نباشید، انجام دادن آن‌ها آسان است و ما آن‌ها را برای شما لیست کرده‌ایم:

  • در حساب گوگل خود، به صفحه manage account بروید
  • بر روی Security کلیک کنید
  • 2FA را فعال کنید (از هر روشی که ترجیح می‌دهید استفاده کنید)
  • روی App Passwords کلیک کنید
  • روی Select App و سپس Mail کلیک کنید
  • روی Select Device کلیک کنید و Other (custom name) را انتخاب کنید. Python Birthday App را وارد کنید.
  • روی Generate کلیک کنید و این پسوورد را ذخیره کنید

اکنون می‌توانید از این پسوورد برنامه در کد زیر استفاده کنید تا بدون مشکل، به حساب جیمیل خود دسترسی داشته باشید!

Source Code:

				
					'''
Birthday Email Sender
-------------------------------------------------------------
pip install pandas openpyxl
excel file cols:
Name, Email, Birthday (MM/DD/YYYY), Last Sent (YYYY)
'''


import pandas as pd
from datetime import datetime
import smtplib
from email.message import EmailMessage


def send_email(recipient, subject, msg):
   GMAIL_ID = 'your_email_here'
   GMAIL_PWD = 'your_password_here'

   email = EmailMessage()
   email['Subject'] = subject
   email['From'] = GMAIL_ID
   email['To'] = recipient
   email.set_content(msg)

   with smtplib.SMTP_SSL('smtp.gmail.com', 465) as gmail_obj:
       gmail_obj.ehlo()
       gmail_obj.login(GMAIL_ID, GMAIL_PWD)
       gmail_obj.send_message(email)
   print('Email sent to ' + str(recipient) + ' with Subject: \''
         + str(subject) + '\' and Message: \'' + str(msg) + '\'')


def send_bday_emails(bday_file):
   bdays_df = pd.read_excel(bday_file)
   today = datetime.now().strftime('%m-%d')
   year_now = datetime.now().strftime('%Y')
   sent_index = []

   for idx, item in bdays_df.iterrows():
       bday = item['Birthday'].to_pydatetime().strftime('%m-%d')
       if (today == bday) and year_now not in str(item['Last Sent']):
           msg = 'Happy Birthday ' + str(item['Name'] + '!!')
           send_email(item['Email'], 'Happy Birthday', msg)
           sent_index.append(idx)

   for idx in sent_index:
       bdays_df.loc[bdays_df.index[idx], 'Last Sent'] = str(year_now)

   bdays_df.to_excel(bday_file, index=False)


if __name__ == '__main__':
   send_bday_emails(bday_file='your_bdays_list.xlsx')
				
			

پروژه های پیشرفته با سورس کد

پروژه های پایتون: چت بات خود را بسازید

پروژه های پایتون: چت بات خود را بسازید

در این مورد از پروژه های پایتون، خواهید آموخت که چگونه با این زبان برنامه نویسی چت بات خود را بسازید. برای این کار، قبل از هر چیز باید بدانید که دو نوع چت بات وجود دارد: Rule-based و Self-learning.

چت بات Rule-based از قوانینی تبعیت می‌کند که بر اساس آن‌ها آموزش دیده است. در نقطه مقابل، چت بات Self-learning برای چت از رویکردهای مبتنی بر یادگیری ماشین استفاده می‌کند.

در این آموزش، من به شما نشان خواهم داد که چگونه با رویکرد Rule-based ، یک چت بات ساده و سریع ایجاد کنید.

ابتدا بیایید کتابخانه‌های لازم برای این مورد از پروژه های پایتون را وارد کنیم:

				
					from nltk.chat.util import Chat, reflections
				
			

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

				
					#Pairs is a list of patterns and responses.
pairs = [
    [
        r"(.*)my name is (.*)",
        ["Hello %2, How are you today ?",]
    ],
    [
        r"(.*)help(.*) ",
        ["I can help you ",]
    ],
     [
        r"(.*) your name ?",
        ["My name is thecleverprogrammer, but you can just call me robot and I'm a chatbot .",]
    ],
    [
        r"how are you (.*) ?",
        ["I'm doing very well", "i am great !"]
    ],
    [
        r"sorry (.*)",
        ["Its alright","Its OK, never mind that",]
    ],
    [
        r"i'm (.*) (good|well|okay|ok)",
        ["Nice to hear that","Alright, great !",]
    ],
    [
        r"(hi|hey|hello|hola|holla)(.*)",
        ["Hello", "Hey there",]
    ],
    [
        r"what (.*) want ?",
        ["Make me an offer I can't refuse",]
        
    ],
    [
        r"(.*)created(.*)",
        ["Aman Kharwal created me using Python's NLTK library ","top secret ;)",]
    ],
    [
        r"(.*) (location|city) ?",
        ['New Delhi, India',]
    ],
    [
        r"(.*)raining in (.*)",
        ["No rain in the past 4 days here in %2","In %2 there is a 50% chance of rain",]
    ],
    [
        r"how (.*) health (.*)",
        ["Health is very important, but I am a computer, so I don't need to worry about my health ",]
    ],
    [
        r"(.*)(sports|game|sport)(.*)",
        ["I'm a very big fan of Cricket",]
    ],
    [
        r"who (.*) (Cricketer|Batsman)?",
        ["Virat Kohli"]
    ],
    [
        r"quit",
        ["Bye for now. See you soon :) ","It was nice talking to you. See you soon :)"]
    ],
    [
        r"(.*)",
        ['That is nice to hear']
    ],
]
				
			

پس از این که الگوها (patterns) و پاسخ‌ها (responses) را ایجاد کردیم، بیایید نگاهی به بازتاب‌ها (reflections) بیندازیم. Reflections یک فایل دیکشنری است که حاوی مجموعه‌ای از مقادیر ورودی و خروجی مربوطه می‌باشد.

به عنوان مثال، اگر ورودی رشته I am a programmer باشد، خروجی you are a programmer خواهد بود.

				
					print(reflections)
				
			
				
					#Output
{'i am': 'you are',
'i was': 'you were',
'i': 'you',
"i'm": 'you are',
"i'd": 'you would',
"i've": 'you have',
"i'll": 'you will',
'my': 'your',
'you are': 'I am',
'you were': 'I was',
"you've": 'I have',
"you'll": 'I will',
'your': 'my',
'yours': 'mine',
'you': 'me',
'me': 'you'}
				
			

ما همچنین می‌توانیم دیکشنری reflections خود را در قالب همان reflections بالا ایجاد کنیم. در مثال، زیر نحوه انجام این کار در این مورد از پروژه های پایتون آورده شده است:

				
					my_dummy_reflections= {
    "go"     : "gone",
    "hello"    : "hey there"
}
				
			

حالا بیایید یک پیام پیش‌فرض چاپ کنیم و ساخت چت بات خود را به اتمام برسانیم:

				
					#default message at the start of chat
print("Hi, I'm thecleverprogrammer and I like to chat\nPlease type lowercase English language to start a conversation. Type quit to leave ")
#Create Chat Bot
chat = Chat(pairs, reflections)
				
			

حالا بیایید یک گفتگو را شروع کنیم:

				
					#Start conversation
chat.converse()
				
			

پروژه های پایتون: ساخت برنامه ساعت با Kivy

پروژه های پایتون: ساخت برنامه ساعت با Kivy

در این مورد از پروژه های پایتون، من با استفاده از ماژول Kivy یک برنامه ساعت ساده خواهم ساهت که از نظر مفهومی شبیه به اپلیکیشن داخلی موجود در iOS و اندروید است.

بیایید با ایجاد یک اپلیکیشن، بیشتر موارد موجود در ماژول Kivy را بیاموزیم.

موضوعات مهمی که در این مورد از پروژه های پایتون به آن خواهیم پرداخت، شامل موارد زیر هستند:

  • اصول اولیه زبان Kivy ، یک زبان خاص دامنه داخلی (DSL) که برای Layout ها و ویجت‌ها استفاده می‌شود.
  • Styling (و در نهایت Subclassing) اجزای داخلی
  • بارگیری فونت‌های سفارشی و formatting متن.
  • برنامه ریزی و گوش دادن به رویدادها.

ساخت برنامه ساعت پایتون با Kivy چگونه است؟

برنامه نهایی ما، که در تصویر زیر نشان داده شده است، تنها حدود 60 خط کد خواهد داشت که به طور مساوی بین source code پایتون و فایل تعریف تابع زبان برنامه نویسی Kivy (.kv) تقسیم می‌شود.

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

بیایید ساخت این مورد از پروژه های پایتون را شروع کنیم:

				
					# File: main.py
from kivy.app import App
class ClockApp(App):
    pass
if __name__ == '__main__':
    ClockApp().run()
				
			
				
					# File: clock.kv
BoxLayout:
    orientation: 'vertical'
    Label:
        text: '00:00:00'
				
			

بارگیری فونت‌های سفارشی

برای این برنامه خاص، ما فقط به دو استایل نیاز داریم: یک استایل سبک‌تر (Roboto-Thin.ttf) و یک استایل سنگین‌تر (Roboto-Medium.ttf) که آن‌ها را به ترتیب به fn_regular و fn_bold اختصاص می‌دهیم:

				
					from kivy.core.text import LabelBase
LabelBase.register(name='Roboto',
    fn_regular='Roboto-Thin.ttf',
    fn_bold='Roboto-Medium.ttf')
    
    # In clock.kv
Label:
    text: '00:00:00'
    font_name: 'Roboto'
    font_size: 60
				
			

Formatting متن

برای رسیدن به Formatting مورد نظر (ساعت‌ها به صورت پررنگ و بقیه متن با فونت نازک fn_regular) در این مورد از پروژه های پایتون، می‌توانیم از کد زیر استفاده کنیم:

				
					Label:
    text: '[b]00[/b]:00:00'
    markup: True
				
			

تغییر رنگ بک‌گراند

در این قسمت، رنگ بک‌گراند پنجره را تنظیم می‌کنیم. بک‌گراند پنجره («رنگ روشن» از OpenGL renderer) یکی از ویژگی‌های یک global Window object است. برای تغییر آن، این کد را درست بعد از خط __name__ == ‘__main__’ در main.py اضافه می‌کنیم:

				
					from kivy.core.window import Window
from kivy.utils import get_color_from_hex
Window.clearcolor = get_color_from_hex('#101216')
				
			

ایجاد تیک تاک برای ساعت

برای دسترسی به ویجت Label  که زمان را نگه می‌دارد، یک identifier  (id) منحصر به فرد به آن می‌دهیم. بعدتر، ما می‌توانیم به راحتی ویجت‌ها را بر اساس ویژگی id آن‌ها جستجو کنیم. این مفهوم نیز بسیار شبیه به مفاهیم توسعه وب است.

clock.kv را با اضافه کردن موارد زیر تغییر دهید:

				
					Label:
    id: time
				
			

خودشه! اکنون می‌توانیم مستقیماً با استفاده از notation موسوم به root.ids.time به این ویجت Label در کد خود دسترسی داشته باشیم. (root ما BoxLayout است).

آپدیت‌های کلاس ClockApp شامل اضافه کردن متدی به نام update_time برای نمایش زمان به شکل زیر است:

				
					def update_time(self, nap):
    self.root.ids.time.text = strftime('[b]%H[/b]:%M:%S')
				
			

حالا بیایید تابع آپدیت را در این مورد از پروژه های پایتون برنامه ریزی کنیم تا پس از آن، یک بار در ثانیه اجرا شود.

برنامه شروع می‌شود:

				
					def on_start(self):
    Clock.schedule_interval(self.update_time, 1)
				
			

Binding ویجت‌ها با استفاده از Properties

به جای این‌که برای هر ویجتی که باید از طریق کد پایتون به آن دسترسی داشته باشیم، یک ID را hardcoding کنیم، می‌توانیم یک property ایجاد کنیم و آن را به یک فایل زبان Kivy اختصاص دهیم. انگیزه انجام این کار عمدتاً اصل DRY و نام‌گذاری تمیزتر، با صرف چند خط کد بیشتر است.

چنین property را می‌توان به صورت زیر تعریف کرد:

				
					# In main.py
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
class ClockLayout(BoxLayout):
   time_prop = ObjectProperty(None)
				
			

علاوه بر این، در فایل زبان Kivy ، یعنی clock.kv ، باید این property را به یک ID مربوط bind کنیم. Custom properties هیچ تفاوتی با Default properties ندارند ندارند، دقیقاً همانگونه به نظر می‌رسند و از همان syntax استفاده می‌کنند:

				
					ClockLayout:
    time_prop: time
    Label:
        id: time
				
			

نهایی کردن Layout برنامه ساعت پایتون

انباشتن سه ویجت در BoxLayout معمولاً باعث می‌شود که هر ویجت به یک سوم اندازه موجود خود تبدیل شود. از آن‌جایی که نمی‌خواهیم دکمه‌ها در مقایسه با نمایشگر ساعت تا این اندازه بزرگ باشند، می‌توانیم یک height property را به BoxLayout افقی (داخلی) اضافه کرده و vertical property  آن به نام size_hint را روی None تنظیم کنیم.

پس از به‌روزرسانی فایل clock.kv برای نمایش کرونومترها و کنترل‌ها، باید شبیه به شکل زیر باشد (به سلسله مراتب Layout ها توجه کنید):

				
					BoxLayout:
    orientation: 'vertical'
    Label:
        id: time
        text: '[b]00[/b]:00:00'
        font_name: 'Roboto'
        font_size: 60
        markup: True
    BoxLayout:
        height: 90
        orientation: 'horizontal'
        padding: 20
        spacing: 20
        size_hint: (1, None)
        Button:
            text: 'Start'
            font_name: 'Roboto'
            font_size: 25
            bold: True
        Button:
            text: 'Reset'
            font_name: 'Roboto'
            font_size: 25
            bold: True
    Label:
        id: stopwatch
        text: '00:00.[size=40]00[/size]'
        font_name: 'Roboto'
        font_size: 60
        markup: True
				
			

کلاس‌های نام‌گذاری‌شده (Named classes)

یکی از مشکلات رایج در در رویکرد Named classes در پروژه های پایتون، این است که ما فقط می‌توانیم یک کلاس به نام Label داشته باشیم. به محض این‌که به دو مجموعه از properties مختلف که در یک نوع از ویجت اعمال می‌شوند نیاز داریم، باید کلاس‌های سفارشی خود را برای آن‌ها تعریف کنیم. به علاوه، overwriting کلاس‌های داخلی فریم‌ورک، مانند Label یا Button ، می‌تواند عواقب نامطلوبی در سراسر اپلیکیشن داشته باشد. برای مثال، اگر مؤلفه دیگری از ویجتی که ما تغییر داده‌ایم استفاده کند، برنامه به هم می‌ریزد.

خوشبختانه، حل این مشکل بسیار ساده است. بیایید یک کلاس نام‌گذاری شده برای دکمه‌ها به نام RobotoButton ایجاد کنیم:

				
					<RobotoButton@Button>:
    font_name: 'Roboto'
    font_size: 25
    bold: True
				
			

قسمت قبل از نماد @ نام کلاس جدید و پیرو آن ویجتی را که در حال گسترش آن هستیم (در پایتون، به آن کلاس RobotoButton(Button) می‌گوییم) مشخص می‌کند. کلاس به دست آمده را می‌توان به جای کلاس عمومی Button در زبان Kivy استفاده کرد:

				
					RobotoButton:
    text: 'Start'
				
			

دکمه‌های Styling

یکی از زوایای تاریک‌تر پارادایم رابط کاربری فلت (flat UI) در پروژه های پایتون، ظاهر عناصر قابل کلیک، مانند دکمه‌ها است. چرا که هیچ روش پذیرفته‌شده‌ای در جهان برای Styling آن‌ها وجود ندارد.

Kivy در این زمینه هم انعطاف‌پذیر است. این فریم‌ورک هیچ محدودیتی برای تصاویر اعمال نمی‌کند و برای اجرای هر طرحی که دوست دارید، تعدادی ویژگی مفید ارائه می‌کند. یکی از ابزارهای کاربردی که در ادامه به آن خواهیم پرداخت، Scaling تصویر 9-patch است که برای Styling دکمه‌ها و ویجت‌های مشابه که ممکن است border  داشته باشند، استفاده می‌شود.

اکنون برای اعمال جادوی 9-patch ، باید اندازه حاشیه‌هایی را که مقیاس‌بندی محدودی دارند، به Kivy اعلام کنیم. (تصویر به طور پیش‌فرض، به طور یکنوخت scale خواهد شد). بیایید دوباره فایل clock.kv را بررسی کنیم و properties زیر را به آن اضافه کنیم:

				
					<RobotoButton@Button>:
    background_normal: 'button_normal.png'
    background_down: 'button_down.png'
    border: (2, 2, 2, 2)
				
			

این را می‌توان برای override انتخابی background_* یا هر ویژگی دیگر، به عنوان مثال اختصاص بافت دیگری در حین استفاده مجدد از تعریف border width استفاده کرد:

				
					RobotoButton:
    text: 'Reset'
    background_normal: 'red_button_normal.png'
    background_down: 'red_button_down.png'
				
			

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

زمان شمارش (Counting time)

برای ایجاد یک کرونومتر در پروژه های پایتون، ابتدا باید time counter غیریکنواخت خود را بسازیم. این کار به راحتی و بدون استفاده از توابع زمان پایتون، به خاطر مدیریت رویداد Clock.schedule_interval در Kivy که زمان سپری شده بین فراخوانی‌ها را به عنوان پارامتر می‌پذیرد، به دست می‌آید. این دقیقاً همان پارامتر nap است.

این کار در کد زیر انجام می‌شود:

				
					def on_start(self):
   Clock.schedule_interval(self.update, 0.016)
def update(self, nap):
   pass
				
			

زمان بر حسب ثانیه اندازه گیری می‌شود، یعنی اگر برنامه با سرعت 60 فریم بر ثانیه اجرا شود و تابع ما را در هر فریم فراخوانی کند، میانگین nap در حدود 60-1=0.016(6) خواهد بود.

با در نظر گرفتن این پارامتر، پیگیری زمان سپری‌شده ساده است و می‌توان با افزایش یک گام، به راحتی به آن دست یافت:

				
					class ClockApp(App):
   sw_seconds = 0
    def update(self, nap):
       self.sw_seconds += nap
				
			

قرار دادن کرونومتر در یک مکان خاص

				
					def update_time(self, nap):
   self.sw_seconds += nap
    minutes, seconds = divmod(self.sw_seconds, 60)
  self.root.ids.stopwatch.text = (
     '%02d:%02d.[size=40]%02d[/size]' %
      (int(minutes), int(seconds),
       int(seconds * 100 % 100)))
Clock.schedule_interval(self.update_time, 0)
				
			

کنترل‌های کرونومتر در برنامه ساعت پایتون

				
					def start_stop(self):
    self.root.ids.start_stop.text = ('Start'
        if self.sw_started else 'Stop')
    self.sw_started = not self.sw_started
def reset(self):
    if self.sw_started:
      self.root.ids.start_stop.text = 'Start'
      self.sw_started = False
    self.sw_seconds = 0
				
			

همچنین باید property موسوم به state را اضافه کنیم تا حالت اجرا یا توقف کرونومتر را ردیابی نماییم:

				
					class ClockApp(App):
    sw_started = False
    sw_seconds = 0
    def update_clock(self, nap):
        if self.sw_started:
            self.sw_seconds += nap
				
			

کد کامل برنامه ساعت پایتون با Kivy

این کد کامل clock.kv شماست:

				
					<label>:
     font_name: 'Roboto'
     font_size: 60
     markup: True
<RobotoButton@Button>:
     background_normal: 'button_down.png'
     background_down: 'button_down.png'
     border: (2, 2, 2, 2)
     font_name: 'Roboto'
     font_size: 25
     bold: True

BoxLayout:
     orientation: 'vertical'

     Label:
          id: time
          text: '[b]00[/b]:00:00'
     BoxLayout:
          height: 90
          orientation: 'horizontal'
          padding: 20
          spacing: 20
          size_hint: (1, 0)

          RobotoButton:
               id: start_stop
               text: 'Start'
               on_press: app.start_stop()

          RobotoButton:
               id: reset
               text: 'Reset'
               background_normal: 'red_button_normal.png'
               background_down: 'red_button_down.png'
               on_press: app.reset()
     Label:
          id: stopwatch
          text: '00:00.[size=40]00[/size]'
				
			

این کد کامل main.py شماست:

				
					from time import strftime
from kivy.app import App
from kivy.clock import Clock
from kivy.core.text import LabelBase
from kivy.core.window import Window
from kivy.utils import get_color_from_hex

class clockApp(App):
    sw_started= False
    sw_seconds = 0
    def update_time(self, nap):
        if self.sw_started:
            self.sw_seconds += nap
        minutes, seconds = divmod(self.sw_seconds, 60)
        self.root.ids.stopwatch.text = (
            '%02d:%02d.[size=40]%02d[/size]'%
            (int(minutes), int(seconds),
             int(seconds* 100 % 100))
        )
        self.root.ids.time.text = strftime('[b]%H[/b]:%M:%S')
    def on_start(self):
        Clock.schedule_interval(self.update_time, 0)
    def start_stop(self):
        self.root.ids.start_stop.text =(
            'Start' if self.sw_started else 'Stop'
        )
        self.sw_started = not self.sw_started
    def reset(self):
        if self.sw_started:
            self.root.ids.start_stop.text = 'Start'
            self.sw_started = False
        self.sw_seconds = 0

if __name__ == '__main__':
    Window.clearcolor = get_color_from_hex('#101216')
    LabelBase.register(
        name='Roboto',
        fn_regular= 'Roboto-Thin.ttf',
        fn_bold= 'Roboto-Medium.ttf'
    )
    clockApp().run()
				
			
{{ reviewsTotal }}{{ options.labels.singularReviewCountLabel }}
{{ reviewsTotal }}{{ options.labels.pluralReviewCountLabel }}
{{ options.labels.newReviewButton }}
{{ userData.canReview.message }}
X