آموزش کامل برنامه نویسی شی گرایی در زبان پایتون

دسته بندی: پایتون
سطح مقاله: متوسط
زمان مطالعه: 23 دقیقه
۱۳ مهر ۱۳۹۹

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

برنامه ‌نویسی شی گرا چیست؟

برنامه نویسی شی‌ گرا (Object-Oriented Programming) که به صورت مختصر OOP نامیده می‌شود، یک نوع شیوه‌ی برنامه‌ نویسی کامپیوتری است که در آن طراحی نرم ‌افزار به جای توابع و منطق، حول محور اشیاء و داده‌ها می‌چرخد.

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

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

کلاس‌ها و اشیاء (Classes and Objects)

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

تعریف کلاس:

در پایتون، برای تعریف کلاس از کلمه‌ی کلیدی class استفاده می‌کنند و در ادامه نام کلاس به آن اختصاص داده می‌شود.

 نحوه نوشتاری (Syntax) یک کلاس:

Class Definition Syntax:

class ClassName:
    # Statement-1
    .
    .
    .
    # Statement-N

مثال:

# Python program to
# demonstrate defining
# a class

class Dog:
    pass

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

اشیاء (Objects)

اشیاء در برنامه‌ نویسی شی‌ گرا، از سه قسمت تشکیل شده‌اند:

  1. حالت (state): صفت‌های یک شی می‌توانند مقدار گرفته و خصوصیات یک شی را نشان دهند.
  2. رفتار (Behavior): در اصل کارهایی که یک شی می‌تواند انجام دهد در متدهای شی قرار می‌دهند.
  3. هویت (Identity): یک نام منحصر به فرد به شی می‌دهد و اجازه می‌دهد یک شی با دیگر اشیاء تعامل داشته باشد.

ایجاد شی:

برای ایجاد یک شی (object) در پایتون، کافی است نام شی مورد نظر را نوشته و نام کلاس مورد نظر را به آن اختصاص دهیم. در مثال زیر یک کلاس تعریف کرده و در انتها یک شی یا یک نمونه از آن کلاس ایجاد می‌کنیم.

# Python program to
# demonstrate instantiating
# a class

class Dog:
    # A simple class

    # attribute
    attr1 = "mamal"
    attr2 = "dog"

    # A sample method
    def fun(self):
        print("I'm a", self.attr1)
        print("I'm a", self.attr2)

    # Driver code

# Object instantiation
Rodger = Dog()

# Accessing class attributes
# and method through objects
print(Rodger.attr1)
Rodger.fun()

خروجی:

mamal

I'm a mamal

I'm a dog

سازنده‌ها در پایتون (constructors)

تمامی توابعی که در کلاس تعریف می‌شوند، متد (Method) نامیده می‌شوند. یکی از این متدها که سازنده‌ی کلاس نیز محسوب می‌شود، متد __init__ است. مقداردهی اولیه شی و نیز دستورالعمل‌هایی که در زمان ایجاد شی باید اجرا شود، به وسیله‌ی این متد انجام می‌پذیرد.

# A Sample class with init method

class Person:

    # init method or constructor
    def __init__(self, name):
        self.name = name

    # Sample Method
    def say_hi(self):
        print('Hello, my name is', self.name)

p = Person('Nikhil')
p.say_hi()

خروجی:

Hello, my name is Nikhil

پارامتر self:

  • در پایتون، برای متدهای کلاس باید یک پارامتر اول اضافی تعریف کرد که موقع فراخوانی، مقداری از سوی ما نمی‌گیرد و خود پایتون آن را می‌شناسد.
  • اگر متد ما هیچ آرگومانی نداشته باشد، باز هم نوشتن پارامتر self الزامی است.

متغیرهای نمونه (Instance Variables): این نوع متغیرها مختص نمونه‌ی ایجاد شده از کلاس هستند و در متد سازنده یا سایر متدهای کلاس تعریف می‌شوند. هر شی متغیر نمونه‌ی مخصوص خود دارد.

متغیرهای کلاس (class Variables): این نوع متغیر در بدنه‌ی کلاس تعریف شده و در تمامی شی‌های ایجاد شده از این کلاس، مشترک است. از این متغیرها به ندرت استفاده می‌شود.

تعریف متغیر نمونه توسط متد سازنده کلاس:

# Python program to show that the variables with a value
# assigned in the class declaration, are class variables and
# variables inside methods and constructors are instance
# variables.

# Class for Dog
class Dog:

    # Class Variable
    animal = 'dog'

    # The init method or constructor
    def __init__(self, breed, color):
        # Instance Variable
        self.breed = breed
        self.color = color

# Objects of Dog class
Rodger = Dog("Pug", "brown")
Buzo = Dog("Bulldog", "black")

print('Rodger details:')
print('Rodger is a', Rodger.animal)
print('Breed: ', Rodger.breed)
print('Color: ', Rodger.color)
print('\nBuzo details:')
print('Buzo is a', Buzo.animal)
print('Breed: ', Buzo.breed)
print('Color: ', Buzo.color)

# Class variables can be accessed using class
# name also
print("\nAccessing class variable using class name")
print(Dog.animal)

خروجی:

Rodger details:

Rodger is a dog

Breed:  Pug

Color:  brown

 

Buzo details:

Buzo is a dog

Breed:  Bulldog

Color:  black

 

Accessing class variable using class name

dog

 تعریف متغیر نمونه در سایر متد کلاس:

# Python program to show that we can create
# instance variables inside methods
# Class for Dog

class Dog:
    # Class Variable
    animal = 'dog'

    # The init method or constructor
    def __init__(self, breed):
        # Instance Variable
        self.breed = breed

    # Adds an instance variable
    def setColor(self, color):
        self.color = color

    # Retrieves instance variable
    def getColor(self):
        return self.color

# Driver Code
Rodger = Dog("pug")
Rodger.setColor("brown")
print(Rodger.getColor())

خروجی:

brown

وراثت (inheritance) در پایتون:

وراثت یا ارث‌بری در شی‌ گرایی، امکانی هست که یک کلاس می‌تواند خصوصیات یک کلاس دیگر را به ارث ببرد و علاوه بر آن خصوصیات دیگری نیز داشته باشد. بعضی از مزایای ارث‌بری:

  • قابلیت استفاده‌ی مجدد از کد را مهیا کرده و از تکرار کدهای مشابه جلوگیری می‌کند و به ما امکان می‌دهد بدون تغییر کلاس، ویژگی‌های جدیدی به آن اضافه کنیم.
  • ماهیت آن انتقالی است، به این معنی که اگر کلاس B از کلاس A ارث می‌برد پس تمام زیر کلاس‌های B نیز از کلاس A ارث می‌برند.

در زیر یک مثال ساده از ارث‌بری آورده شده است.

# A Python program to demonstrate inheritance
# Base or Super class. Note object in bracket.
# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"

class Person(object):

    # Constructor
    def __init__(self, name):
        self.name = name

    # To get name
    def getName(self):
        return self.name

    # To check if this person is an employee
    def isEmployee(self):
        return False

    # Inherited or Subclass (Note Person in bracket)
class Employee(Person):
    # Here we return true
    def isEmployee(self):
        return True

# Driver code
emp = Person("Geek1")  # An Object of Person
print(emp.getName(), emp.isEmployee())

emp = Employee("Geek2") # An Object of Employee
print(emp.getName(), emp.isEmployee())

خروجی:

Geek1 False

Geek2 True

در پایتون نسخه‌ی 3، مانند object class جاوا، object ریشه‌ی همه کلاس‌ها است.

در پایتون 3، "(class Test(object" و " class Test" یکسان هستند.

در پایتون 2، "(class Test(object" یک کلاس با object به عنوان پدر ایجاد می‌کند (کلاس سبک جدید نامیده می‌شود) و "class Test" کلاس سبک قدیمی (بدون پدر) ایجاد می‌کند. برای کسب اطلاعات بیشتر مستندات پایتون  را مطالعه کنید.

زیرکلاس (Subclassing):

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

class subclass_name (superclass_name):
    _  _ _
    _ _ _

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

# Python code to demonstrate how parent constructors
# are called.

# parent class
class Person( object ):
    # __init__ is known as the constructor
    def __init__(self, name, idnumber):
        self.name = name
        self.idnumber = idnumber

    def display(self):
        print(self.name)
        print(self.idnumber)

# child class
class Employee( Person ):
    def __init__(self, name, idnumber, salary, post):
        self.salary = salary
        self.post = post

        # invoking the __init__ of the parent class
        Person.__init__(self, name, idnumber)
   
# creation of an object variable or an instance
a = Employee('Rahul', 886012, 200000, "Intern")

# calling a function of the class Person using its instance
a.display()

خروجی:

Rahul

886012

در اینجا کلاس Employee کلاس فرزند و کلاس Person کلاس پدر است و هر آنچه در متد __init__ کلاس پدر است به فرزند ارث می‌رسد و به همین جهت، فراخوانی نام متغیرهای نمونه‌ی کلاس پدر در متد سازنده کلاس فرزند کافی است. اما اگر به هر دلیلی فراموش کنید نام متغیرهای کلاس پدر را در کلاس فرزند فراخوانی کنید، متغیرهای نمونه‌ی آن در دسترس کلاس فرزند نیستند. کد زیر به همین علت خطایی ایجاد می‌کند:

# Python program to demonstrate error if we
# forget to invoke __init__() of the parent.

class A:
    def __init__(self, n = 'Rahul'):
         self.name = n
 
class B(A):
    def __init__(self, roll):
        self.roll = roll

object = B(23)
print (object.name)

خروجی:

Traceback (most recent call last):

File "/home/de4570cca20263ac2c4149f435dba22c.py", line 12, in

print (object.name)

AttributeError: 'B' object has no attribute 'name'

انواع مختلف ارث‌بری:

  1. وراثت منفرد (Single inheritance): وقتی کلاس فرزند، فقط از یک کلاس پدر ارث ببرد، به آن وراثت منفرد می‌گویند. در بالا مثال‌هایی ذکر شد.
  2. وراثت چندگانه (Multiple inheritance): وقتی کلاس فرزند از کلاس‌های پدر متعدد ارث‌بری کند به آن وراثت چندگانه می‌گویند.

برخلاف سایر زبان‌های برنامه ‌نویسی مانند جاوا و سی‌پلاس‌پلاس، پایتون از وراثت چندگانه (Multiple inheritance) پشتیبانی می‌کند.

# Python example to show the working of multiple
# inheritance

class Base1(object):
    def __init__(self):
        self.str1 = "Geek1"
        print("Base1")

class Base2(object):
    def __init__(self):
        self.str2 = "Geek2"
        print("Base2")

class Derived(Base1, Base2):
    def __init__(self):
        # Calling constructors of Base1
        # and Base2 classes
        Base1.__init__(self)
        Base2.__init__(self)
        print("Derived")

    def printStrs(self):
        print(self.str1, self.str2)

ob = Derived()
ob.printStrs()

خروجی:

Base1

Base2

Derived

Geek1 Geek2

  1. وراثت چند سطحی (Multilevel inheritance): این نوع وراثت به زمانی مربوط می‌شود که رابطه فرزند و نوه داریم. به عنوان مثال:
# A Python program to demonstrate inheritance
# Base or Super class. Note object in bracket.
# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"

class Base(object):
    # Constructor
    def __init__(self, name):
        self.name = name

    # To get name
    def getName(self):
        return self.name

# Inherited or Sub class (Note Person in bracket)
class Child(Base):
    # Constructor
    def __init__(self, name, age):
        Base.__init__(self, name)
        self.age = age

    # To get name
    def getAge(self):
        return self.age

# Inherited or Sub class (Note Person in bracket)
class GrandChild(Child):
    # Constructor
    def __init__(self, name, age, address):
        Child.__init__(self, name, age)
        self.address = address

    # To get address
    def getAddress(self):
        return self.address

# Driver code
g = GrandChild("Geek1", 23, "Noida")
print(g.getName(), g.getAge(), g.getAddress())

خروجی:

Geek1 23 Noida
  1. وراثت سلسله مراتبی (Hierarchical Inheritance): وقتی بیش از یک کلاس از کلاس پدر ارث‌بری کنند را وراثت سلسله مراتبی می‌گویند.
  2. وراثت ترکیبی (Hybrid Inheritance): ارث‌بری تشکیل شده از انواع وراثت، را وراثت ترکیبی گویند.

خصوصی کردن متغیرهای کلاس پدر:

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

# Python program to demonstrate private members
# of the parent class

class C(object):
    def __init__(self):
        self.c = 21
 
        # d is private instance variable
        self.__d = 42

class D(C):
    def __init__(self):
        self.e = 84
        C.__init__(self)

object1 = D()
# produces an error as d is private instance variable
print(object1.d)

خروجی:

File "/home/993bb61c3e76cda5bb67bd9ea05956a1.py", line 16, in

print (object1.d)

AttributeError: type object 'D' has no attribute 'd'

از آنجایی که متغیر d با دو زیر خط خصوصی شده است، برای کلاس فرزند در دسترس نیست لذا این خطا رخ می‌دهد.

 

کپسوله سازی (Encapsulation) در پایتون

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

یک کلاس، نمونه‌ای از کپسوله سازی است، زیرا تمامی داده‌های توابع عضو، متغیرها و غیره را در خود قرار داده است.

اعضای محافظت شده (Protected members)

اعضای محافظت شده (در زبان ++C و Java)  آن دسته از اعضای کلاس هستند که خارج از کلاس قابل دسترسی نیستند، اما از داخل کلاس و زیرکلاس‌های آن قابل دسترسی هستند. برای رسیدن به این مقصود در پایتون، باید قبل از نام عضو یک خط زیر "_" گذاشت.

توجه: متد "__init__" یک متد سازنده است و به محض ایجاد یک شی، اجرا می‌شود.

# Python program to
# demonstrate protected members
# Creating a base class

class Base:
    def __init__(self):
        # Protected member
        self._a = 2

# Creating a derived class
class Derived(Base):
    def __init__(self):
        # Calling constructor of
        # Base class
        Base.__init__(self)
        print("Calling protected member of base class: ")
        print(self._a)

obj1 = Derived()
obj2 = Base()
# Calling protected member
# Outside class will  result in
# AttributeError
print(obj2.a)

خروجی:

Calling protected member of base class:

2

 

Traceback (most recent call last):

File "/home/6fb1b95dfba0e198298f9dd02469eb4a.py", line 25, in

print(obj1.a)

AttributeError: 'Base' object has no attribute 'a'

اعضای خصوصی (Private members)

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

# Python program to
# demonstrate private members
# Creating a Base class

class Base:
    def __init__(self):
        self.a = "7Lean.com"
        self.__c = "7learn.com"

# Creating a derived class
class Derived(Base):
    def __init__(self):
        # Calling constructor of
        # Base class
        Base.__init__(self)
        print("Calling private member of base class: ")
        print(self.__c)

# Driver code
obj1 = Base()
print(obj1.a)
# Uncommenting print(obj1.c) will
# raise an AttributeError
# Uncommenting obj2 = Derived() will
# also raise an AtrributeError as
# private member of base class
# is called inside derived class

خروجی:

7learn.com

 

 

Traceback (most recent call last):

File "/home/f4905b43bfcf29567e360c709d3c52bd.py", line 25, in <module>

print(obj1.c)

AttributeError: 'Base' object has no attribute 'c'

 

Traceback (most recent call last):

File "/home/4d97a4efe3ea68e55f48f1e7c7ed39cf.py", line 27, in <module>

obj2 = Derived()

File "/home/4d97a4efe3ea68e55f48f1e7c7ed39cf.py", line 20, in __init__

print(self.__c)

AttributeError: 'Derived' object has no attribute '_Derived__c'

چندریختی (Polymorphism) در پایتون

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

مثالی از توابع چندریختی ساخته شده:

# Python program to demonstrate in-built poly-
# morphic functions
# len() being used for a string

print(len("7learn"))

# len() being used for a list
print(len([10, 20, 30]))

خروجی:

6

3

مثالی از توابع چندریختی تعریف شده:

# A simple Python function to demonstrate
# Polymorphism

def add(x, y, z = 0):
    return x + y+z

# Driver code
print(add(2, 3))
print(add(2, 3, 4))

خروجی:

5

9

 

چند ریختی با متدهای کلاس:

در کد زیر می‌ببینید که، پایتون چگونه می‌تواند از دو نوع کلاس متفاوت به همان شیوه استفاده کند. ما یک حلقه‌ی تکرار for ایجاد می‌کنیم که از طریق یک تاپل (Tuple) از اشیاء تکرار می‌شود. سپس بدون نگرانی از نوع کلاس هر شی، متدها را فراخوانی می‌کنیم. ما فرض می‌کنیم این متدها در هر کلاس وجود دارد.

class India():
    def capital(self):
        print("New Delhi is the capital of India.")

    def language(self):
        print("Hindi is the most widely spoken language of India.")

    def type(self):
        print("India is a developing country.")

class USA():
    def capital(self):
        print("Washington, D.C. is the capital of USA.")

    def language(self):
        print("English is the primary language of USA.")

    def type(self):
        print("USA is a developed country.")

obj_ind = India()
obj_usa = USA()

for country in (obj_ind, obj_usa):
    country.capital()
    country.language()
    country.type()

خروجی:

New Delhi is the capital of India.

Hindi is the most widely spoken language of India.

India is a developing country.

Washington, D.C. is the capital of USA.

English is the primary language of USA.

USA is a developed country.

جمع‌بندی:

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

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

چه امتیازی به این مقاله می دید؟
نویسنده عبدالرضا مولایی
هیچوقت برای یادگیری دیر نیست؛ همیشه چیزهای جدید برای آموختن وجود دارد.. این دو جمله، همیشه آویزه‌ی گوش منه، چون باعث میشه از یادگیری چیزهای تازه هراسی نداشته باشم.

نظرات کاربران

sam

سلام ممنون از سایت خوب شما میخواستم بدونم شما آموزش هم برای این مقطع دارید؟

نازنین کریمی مقدم

سلام.
مبحث آموزش شی گرایی در پایتون مربوط به دوره پایتون وب هست و سر فصل آن در دست تهیه است. شما میتونید از صفحه دوره بررسی کنید.

ارسال دیدگاه
خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :