

#class <Название класса> [ ( <Кnaccl> [, ... , <КnaccN>])]:
#    [""" Строка дОКJ!I'-1ентирования """]
#    <Описание атрибутов и методов>

# -*- coding: utf-8 -*
class MyClass:
    """Это строка документирования"""
    print ("Инструкции вьmолняются сразу")
#input ()

#<Экземпляр класса> = <Название класса> ( [ <Параметры>] )

class MyClass:
    def __init__(self): # Конструктор
        self.x = 10     # Атрибут экземпляра класса
    def print_x(self):  # self - это ссьmка на экземпляр класса
        print(self.x)   # Вьшодим значение атрибута
c = MyClass()           #Создали экземпляр

c.print_x()             # Вызьшаем метод print_x ()
                        # self не указьшается при вызове метода
print(c.x)              # К атрибуту можно обратиться непосредственно


#Обращение к методам класса:
#<Экземпляр класса>. <Имя метода> ( [ <Ilараметры>] )

#getattr() - возвращ значение атрибута по названию, заданному строкой
#getattr(<Oбъeкт>, <Атрибут>[, <Значение по умолчанию>])

#setattr() - задание значения атрибута. НАзвание атр - в виде строки
#setattr(<Oбъeкт>, <Атрибут>, <Значение>)

#delattr(<Объект>, <Атрибут>) - удаление атрибута

#hasattr(<Объект>, <Атрибут>) - наличие указ.атрибута

class MyClass:# Определяем пустой класс
    pass
MyClass.x = 50# Создаем атрибут объекта класса
c1, c2 = MyClass(), MyClass()# Создаем два экземпляра класса
c1.у = 10# Создаем атрибут экземпляра класса
c2.у = 20# Создаем атрибут экземпляра класса
print(c1.x, c1.у)# Выведет: 50 10
print(c2.x, c2.у)# Вьшедет: 50 20

##################
#Атрибуты объекта класса и атрибуты экземпляра класса

#Атрибут объекта класса доступен всем экземплярам класса, но после изменения
# атрибута значение изменится во всех экземплярах класса.
# Атрибут экземпляра класса может хранить уникальное значение
# для каждого экземпляра.

class MyClass:
    x = 10
    def __init__(self):
        self.y=20

c1 = MyClass() #Экземпляр класса
c2 = MyClass()

print(c1.x, c2.x)
MyClass.x = 88 # Изменяем атрибут объекта класса
print(c1.x, c2.x) #изменилось в обоих экземплярах

print(c1.y, c2.y)
c1.y = 88 #Изменяем атрибут экземпляра
print(c1.y, c2.y)#изменился только этот экземпляр


#__init()
#def init rself[, <Значение!>[, ... , <ЗначениеN>]]):
#   <Инструкции>
#С помощью метода _ init () можно присвоить начальные значения атрибутам класса.

#При создании каждого экземпляра классаэтот метод вызывается автоматически
# <Экземnляр класса> <Имя класса>([<Значениеl>[, ... , <ЗначениеN>]])

#Пример

class MyClass1:
    def __init__(self,value1,value2): # Конструктор
       self.x = value1
       self.y = value2
c = MyClass1(100,300)
print(c.x,c.y)

#__del__() - деструктор класса

class MyClass:
    def __init__(self) : # Конструктор класса
        print("Вызван метод init ()")
    def __del__(self): # Деструктор класса
        print("Вызван метод del ()")


######################
#Наследование

#У нас есть класс Class1. Мы моем создать новый класс Class2, в котором
#будет доступ ко всем методам и атрибутам класса Class1, а также новым атр.и методам

class Class1:
    def func1(self):
        print("метод func1() класса Class1")
    def func2(self):
        print("метод func2() класса Class1")

class Class2(Class1):
    def func3(self):
        print("метод func3() класса Class2")

c = Class2()
c.func1()
c.func2()
c.func3()
print()

#Если имя метода в классе Class2 совпадает с именем метода класса Classl,
# то будет использоваться метод из класса Class2. Чтобы вызвать
# одноименный метод из базового класса, следует указать перед методом
# название базового класса. Кроме того. в первом параметре метода
# необходимо явно указать ссылку на экземпляр класса.

class Class1:
    def __init__(self):
        print("Конструктор базового класса")
    def func1(self):
        print("метод func1() класса Class1")

class Class2(Class1):
    def __init__(self):
        print("Конструктор подкласса")
        Class1.__init__(self) #Вызываем конструктор базового класса
    def func1(self):
        print("метод func1() класса Class2")
        Class1.func1(self)

c = Class2()
c.func1()
print()
print()
#also useable:  super([<Клacc>, <Указатель self>])

#В этом случае Class1.__init__(self) переходит в super().__init__()
# или в super(Class2, self).__init__()


#####################
#Множественное наследование
print("множественное наследование")
class Class1: # Базовьm класс для класса Class2
    def funcl(self):
        print ("Метод funcl () класса Classl")

class Class2(Class1): #Класс Class2 наследует класс Classl
    def func2(self):
        print ("Метод func2 () класса Class2")

class ClassЗ(Class1): # Класс ClassЗ наследует класс Classl
    def funcl(self):
        print("Meтoд funcl () класса ClassЗ")
    def func2 (self):
        print("Meтoд func2 () класса ClassЗ")
    def funcЗ(self):
        print ("Метод funcЗ () класса ClassЗ")
    def func4 (self) :
        print ("Метод func4 () класса ClassЗ")

class Class4(Class2, ClassЗ): #Множественное наследование
    # Наследуем func2() из класса ClassЗ, а не из класса Class2
    func2 = ClassЗ.func2
    def func4 (self):
        print ("Метод func4 () класса Class4")


c = Class4()
c.funcl()
c.func2()
c.funcЗ()
c.func4()
print()


#Для использования мат.операторов с экземплярами классов, необходимо перегружать операторы
#Пример:

class MyClass234:
    def __init__ (self, y):
        self.x=y
    def __add__ (self, y): # Перегрузка оператора +
        print ("Экземпляр слева")
        return self.x +y
    def __radd__ (self, y) : # Перегрузка оператора +
        print ("Экземпляр справа")
        return self.x +y
    def __iadd__ (self, y): # Перегрузка оператора +=
        print ("Сложение с присваиванием")
        self.x +=y
        return self

c = MyClass234(50)
print(c + 10) # Выведет:Экземпляр слева 60
print(20 + c) # Выведет:Экземпляр справа 70
c += 30 # Выведет: Сложение с присваиванием
print(c.x) # Выведет: 80

print()

################################
#Статические методы и методы класса

#Внутри класса можно создать метод, который будет доступен без создания
# экземпляра класса. Для этого перед определением метода внутри класса
# следует указать декоратор @staticmethod.
#Вызов статического метода без создания экземпляра класса осуществляется
#следующим образом:
#<Название класса>.<Название метода>(<Параметры>)
#Кроме того, можно вызвать статический метод через экземпляр класса:
#<Экземпляр класса>.<Название метода>(<Параметры>)

class AnotherClass:
    @staticmethod
    def func1(x,y):
        return x+y
    #а теперь обычный метод
    def func2(self, x, y):
        return x + y
    def func3(self, x, y):
        return AnotherClass.func1(x, y) #Вызов метода из класса

print(AnotherClass.func1(10,20)) #Вьвьшаем статический метод
c = AnotherClass()
print(c.func2(15,6)) #Вызьшаем метод класса
print(c.func1(50,12)) #Вьвьшаем статический метод
                        #через экземпляр класса
print(c.func3(23,5))  #Вызьшаем статический метод внутри класса

#внутри статического метода нет доступа к атрибутам и методам экземпляра класса.

2474b7743e2355a41ec7fc0303e10f6b00e800fc
<mask token>


class Class1:

    def __init__(self):
        print('Конструктор базового класса')
    <mask token>


class Class2(Class1):

    def __init__(self):
        print('Конструктор подкласса')
        Class1.__init__(self)

    def func1(self):
        print('метод func1() класса Class2')
        Class1.func1(self)


<mask token>


class Class1:

    def funcl(self):
        print('Метод funcl () класса Classl')


class Class2(Class1):

    def func2(self):
        print('Метод func2 () класса Class2')


class ClassЗ(Class1):

    def funcl(self):
        print('Meтoд funcl () класса ClassЗ')

    def func2(self):
        print('Meтoд func2 () класса ClassЗ')

    def funcЗ(self):
        print('Метод funcЗ () класса ClassЗ')

    def func4(self):
        print('Метод func4 () класса ClassЗ')


class Class4(Class2, ClassЗ):
    func2 = ClassЗ.func2

    def func4(self):
        print('Метод func4 () класса Class4')


<mask token>


class MyClass234:

    def __init__(self, y):
        self.x = y

    def __add__(self, y):
        print('Экземпляр слева')
        return self.x + y

    def __radd__(self, y):
        print('Экземпляр справа')
        return self.x + y

    def __iadd__(self, y):
        print('Сложение с присваиванием')
        self.x += y
        return self


<mask token>


class AnotherClass:

    @staticmethod
    def func1(x, y):
        return x + y

    def func2(self, x, y):
        return x + y

    def func3(self, x, y):
        return AnotherClass.func1(x, y)


<mask token>

<mask token>


class Class1:
    <mask token>

    def func2(self):
        print('метод func2() класса Class1')


class Class2(Class1):

    def func3(self):
        print('метод func3() класса Class2')


<mask token>


class Class1:

    def __init__(self):
        print('Конструктор базового класса')

    def func1(self):
        print('метод func1() класса Class1')


class Class2(Class1):

    def __init__(self):
        print('Конструктор подкласса')
        Class1.__init__(self)

    def func1(self):
        print('метод func1() класса Class2')
        Class1.func1(self)


<mask token>


class Class1:

    def funcl(self):
        print('Метод funcl () класса Classl')


class Class2(Class1):

    def func2(self):
        print('Метод func2 () класса Class2')


class ClassЗ(Class1):

    def funcl(self):
        print('Meтoд funcl () класса ClassЗ')

    def func2(self):
        print('Meтoд func2 () класса ClassЗ')

    def funcЗ(self):
        print('Метод funcЗ () класса ClassЗ')

    def func4(self):
        print('Метод func4 () класса ClassЗ')


class Class4(Class2, ClassЗ):
    func2 = ClassЗ.func2

    def func4(self):
        print('Метод func4 () класса Class4')


<mask token>


class MyClass234:

    def __init__(self, y):
        self.x = y

    def __add__(self, y):
        print('Экземпляр слева')
        return self.x + y

    def __radd__(self, y):
        print('Экземпляр справа')
        return self.x + y

    def __iadd__(self, y):
        print('Сложение с присваиванием')
        self.x += y
        return self


<mask token>


class AnotherClass:

    @staticmethod
    def func1(x, y):
        return x + y

    def func2(self, x, y):
        return x + y

    def func3(self, x, y):
        return AnotherClass.func1(x, y)


<mask token>

<mask token>


class MyClass:

    def __init__(self):
        print('Вызван метод init ()')

    def __del__(self):
        print('Вызван метод del ()')


class Class1:

    def func1(self):
        print('метод func1() класса Class1')

    def func2(self):
        print('метод func2() класса Class1')


class Class2(Class1):

    def func3(self):
        print('метод func3() класса Class2')


<mask token>


class Class1:

    def __init__(self):
        print('Конструктор базового класса')

    def func1(self):
        print('метод func1() класса Class1')


class Class2(Class1):

    def __init__(self):
        print('Конструктор подкласса')
        Class1.__init__(self)

    def func1(self):
        print('метод func1() класса Class2')
        Class1.func1(self)


<mask token>


class Class1:

    def funcl(self):
        print('Метод funcl () класса Classl')


class Class2(Class1):

    def func2(self):
        print('Метод func2 () класса Class2')


class ClassЗ(Class1):

    def funcl(self):
        print('Meтoд funcl () класса ClassЗ')

    def func2(self):
        print('Meтoд func2 () класса ClassЗ')

    def funcЗ(self):
        print('Метод funcЗ () класса ClassЗ')

    def func4(self):
        print('Метод func4 () класса ClassЗ')


class Class4(Class2, ClassЗ):
    func2 = ClassЗ.func2

    def func4(self):
        print('Метод func4 () класса Class4')


<mask token>


class MyClass234:

    def __init__(self, y):
        self.x = y

    def __add__(self, y):
        print('Экземпляр слева')
        return self.x + y

    def __radd__(self, y):
        print('Экземпляр справа')
        return self.x + y

    def __iadd__(self, y):
        print('Сложение с присваиванием')
        self.x += y
        return self


<mask token>


class AnotherClass:

    @staticmethod
    def func1(x, y):
        return x + y

    def func2(self, x, y):
        return x + y

    def func3(self, x, y):
        return AnotherClass.func1(x, y)


<mask token>

<mask token>


class MyClass:
    pass


<mask token>


class MyClass:
    x = 10

    def __init__(self):
        self.y = 20


<mask token>


class MyClass1:

    def __init__(self, value1, value2):
        self.x = value1
        self.y = value2


<mask token>


class MyClass:

    def __init__(self):
        print('Вызван метод init ()')

    def __del__(self):
        print('Вызван метод del ()')


class Class1:

    def func1(self):
        print('метод func1() класса Class1')

    def func2(self):
        print('метод func2() класса Class1')


class Class2(Class1):

    def func3(self):
        print('метод func3() класса Class2')


<mask token>


class Class1:

    def __init__(self):
        print('Конструктор базового класса')

    def func1(self):
        print('метод func1() класса Class1')


class Class2(Class1):

    def __init__(self):
        print('Конструктор подкласса')
        Class1.__init__(self)

    def func1(self):
        print('метод func1() класса Class2')
        Class1.func1(self)


<mask token>


class Class1:

    def funcl(self):
        print('Метод funcl () класса Classl')


class Class2(Class1):

    def func2(self):
        print('Метод func2 () класса Class2')


class ClassЗ(Class1):

    def funcl(self):
        print('Meтoд funcl () класса ClassЗ')

    def func2(self):
        print('Meтoд func2 () класса ClassЗ')

    def funcЗ(self):
        print('Метод funcЗ () класса ClassЗ')

    def func4(self):
        print('Метод func4 () класса ClassЗ')


class Class4(Class2, ClassЗ):
    func2 = ClassЗ.func2

    def func4(self):
        print('Метод func4 () класса Class4')


<mask token>


class MyClass234:

    def __init__(self, y):
        self.x = y

    def __add__(self, y):
        print('Экземпляр слева')
        return self.x + y

    def __radd__(self, y):
        print('Экземпляр справа')
        return self.x + y

    def __iadd__(self, y):
        print('Сложение с присваиванием')
        self.x += y
        return self


<mask token>


class AnotherClass:

    @staticmethod
    def func1(x, y):
        return x + y

    def func2(self, x, y):
        return x + y

    def func3(self, x, y):
        return AnotherClass.func1(x, y)


<mask token>



#class <Название класса> [ ( <Кnaccl> [, ... , <КnaccN>])]:
#    [""" Строка дОКJ!I'-1ентирования """]
#    <Описание атрибутов и методов>

# -*- coding: utf-8 -*
class MyClass:
    """Это строка документирования"""
    print ("Инструкции вьmолняются сразу")
#input ()

#<Экземпляр класса> = <Название класса> ( [ <Параметры>] )

class MyClass:
    def __init__(self): # Конструктор
        self.x = 10     # Атрибут экземпляра класса
    def print_x(self):  # self - это ссьmка на экземпляр класса
        print(self.x)   # Вьшодим значение атрибута
c = MyClass()           #Создали экземпляр

c.print_x()             # Вызьшаем метод print_x ()
                        # self не указьшается при вызове метода
print(c.x)              # К атрибуту можно обратиться непосредственно


#Обращение к методам класса:
#<Экземпляр класса>. <Имя метода> ( [ <Ilараметры>] )

#getattr() - возвращ значение атрибута по названию, заданному строкой
#getattr(<Oбъeкт>, <Атрибут>[, <Значение по умолчанию>])

#setattr() - задание значения атрибута. НАзвание атр - в виде строки
#setattr(<Oбъeкт>, <Атрибут>, <Значение>)

#delattr(<Объект>, <Атрибут>) - удаление атрибута

#hasattr(<Объект>, <Атрибут>) - наличие указ.атрибута

class MyClass:# Определяем пустой класс
    pass
MyClass.x = 50# Создаем атрибут объекта класса
c1, c2 = MyClass(), MyClass()# Создаем два экземпляра класса
c1.у = 10# Создаем атрибут экземпляра класса
c2.у = 20# Создаем атрибут экземпляра класса
print(c1.x, c1.у)# Выведет: 50 10
print(c2.x, c2.у)# Вьшедет: 50 20

##################
#Атрибуты объекта класса и атрибуты экземпляра класса

#Атрибут объекта класса доступен всем экземплярам класса, но после изменения
# атрибута значение изменится во всех экземплярах класса.
# Атрибут экземпляра класса может хранить уникальное значение
# для каждого экземпляра.

class MyClass:
    x = 10
    def __init__(self):
        self.y=20

c1 = MyClass() #Экземпляр класса
c2 = MyClass()

print(c1.x, c2.x)
MyClass.x = 88 # Изменяем атрибут объекта класса
print(c1.x, c2.x) #изменилось в обоих экземплярах

print(c1.y, c2.y)
c1.y = 88 #Изменяем атрибут экземпляра
print(c1.y, c2.y)#изменился только этот экземпляр


#__init()
#def init rself[, <Значение!>[, ... , <ЗначениеN>]]):
#   <Инструкции>
#С помощью метода _ init () можно присвоить начальные значения атрибутам класса.

#При создании каждого экземпляра классаэтот метод вызывается автоматически
# <Экземnляр класса> <Имя класса>([<Значениеl>[, ... , <ЗначениеN>]])

#Пример

class MyClass1:
    def __init__(self,value1,value2): # Конструктор
       self.x = value1
       self.y = value2
c = MyClass1(100,300)
print(c.x,c.y)

#__del__() - деструктор класса

class MyClass:
    def __init__(self) : # Конструктор класса
        print("Вызван метод init ()")
    def __del__(self): # Деструктор класса
        print("Вызван метод del ()")


######################
#Наследование

#У нас есть класс Class1. Мы моем создать новый класс Class2, в котором
#будет доступ ко всем методам и атрибутам класса Class1, а также новым атр.и методам

class Class1:
    def func1(self):
        print("метод func1() класса Class1")
    def func2(self):
        print("метод func2() класса Class1")

class Class2(Class1):
    def func3(self):
        print("метод func3() класса Class2")

c = Class2()
c.func1()
c.func2()
c.func3()
print()

#Если имя метода в классе Class2 совпадает с именем метода класса Classl,
# то будет использоваться метод из класса Class2. Чтобы вызвать
# одноименный метод из базового класса, следует указать перед методом
# название базового класса. Кроме того. в первом параметре метода
# необходимо явно указать ссылку на экземпляр класса.

class Class1:
    def __init__(self):
        print("Конструктор базового класса")
    def func1(self):
        print("метод func1() класса Class1")

class Class2(Class1):
    def __init__(self):
        print("Конструктор подкласса")
        Class1.__init__(self) #Вызываем конструктор базового класса
    def func1(self):
        print("метод func1() класса Class2")
        Class1.func1(self)

c = Class2()
c.func1()
print()
print()
#also useable:  super([<Клacc>, <Указатель self>])

#В этом случае Class1.__init__(self) переходит в super().__init__()
# или в super(Class2, self).__init__()


#####################
#Множественное наследование
print("множественное наследование")
class Class1: # Базовьm класс для класса Class2
    def funcl(self):
        print ("Метод funcl () класса Classl")

class Class2(Class1): #Класс Class2 наследует класс Classl
    def func2(self):
        print ("Метод func2 () класса Class2")

class ClassЗ(Class1): # Класс ClassЗ наследует класс Classl
    def funcl(self):
        print("Meтoд funcl () класса ClassЗ")
    def func2 (self):
        print("Meтoд func2 () класса ClassЗ")
    def funcЗ(self):
        print ("Метод funcЗ () класса ClassЗ")
    def func4 (self) :
        print ("Метод func4 () класса ClassЗ")

class Class4(Class2, ClassЗ): #Множественное наследование
    # Наследуем func2() из класса ClassЗ, а не из класса Class2
    func2 = ClassЗ.func2
    def func4 (self):
        print ("Метод func4 () класса Class4")


c = Class4()
c.funcl()
c.func2()
c.funcЗ()
c.func4()
print()


#Для использования мат.операторов с экземплярами классов, необходимо перегружать операторы
#Пример:

class MyClass234:
    def __init__ (self, y):
        self.x=y
    def __add__ (self, y): # Перегрузка оператора +
        print ("Экземпляр слева")
        return self.x +y
    def __radd__ (self, y) : # Перегрузка оператора +
        print ("Экземпляр справа")
        return self.x +y
    def __iadd__ (self, y): # Перегрузка оператора +=
        print ("Сложение с присваиванием")
        self.x +=y
        return self

c = MyClass234(50)
print(c + 10) # Выведет:Экземпляр слева 60
print(20 + c) # Выведет:Экземпляр справа 70
c += 30 # Выведет: Сложение с присваиванием
print(c.x) # Выведет: 80

print()

################################
#Статические методы и методы класса

#Внутри класса можно создать метод, который будет доступен без создания
# экземпляра класса. Для этого перед определением метода внутри класса
# следует указать декоратор @staticmethod.
#Вызов статического метода без создания экземпляра класса осуществляется
#следующим образом:
#<Название класса>.<Название метода>(<Параметры>)
#Кроме того, можно вызвать статический метод через экземпляр класса:
#<Экземпляр класса>.<Название метода>(<Параметры>)

class AnotherClass:
    @staticmethod
    def func1(x,y):
        return x+y
    #а теперь обычный метод
    def func2(self, x, y):
        return x + y
    def func3(self, x, y):
        return AnotherClass.func1(x, y) #Вызов метода из класса

print(AnotherClass.func1(10,20)) #Вьвьшаем статический метод
c = AnotherClass()
print(c.func2(15,6)) #Вызьшаем метод класса
print(c.func1(50,12)) #Вьвьшаем статический метод
                        #через экземпляр класса
print(c.func3(23,5))  #Вызьшаем статический метод внутри класса

#внутри статического метода нет доступа к атрибутам и методам экземпляра класса.
